2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
59 UCHAR RateSwitchTable[] = {
60 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
148 UCHAR RateSwitchTable11N2S[] = {
149 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
163 UCHAR RateSwitchTable11N3S[] = {
164 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
251 0x05, 0x20, 20, 15, 30,
252 0x06, 0x20, 21, 8, 20,
253 0x07, 0x20, 22, 8, 20,
254 0x08, 0x20, 23, 8, 25,
255 0x09, 0x22, 23, 8, 25,
258 UCHAR RateSwitchTable11BGN2SForABand[] = {
259 // 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)
260 0x0b, 0x09, 0, 0, 0, // Initial used item after association
261 0x00, 0x21, 0, 30,101, //50
262 0x01, 0x21, 1, 20, 50,
263 0x02, 0x21, 2, 20, 50,
264 0x03, 0x21, 3, 15, 50,
265 0x04, 0x21, 4, 15, 30,
266 0x05, 0x21, 5, 15, 30,
267 0x06, 0x20, 12, 15, 30,
268 0x07, 0x20, 13, 8, 20,
269 0x08, 0x20, 14, 8, 20,
270 0x09, 0x20, 15, 8, 25,
271 0x0a, 0x22, 15, 8, 25,
274 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
275 // 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)
276 0x0c, 0x09, 0, 0, 0, // Initial used item after association
277 0x00, 0x21, 0, 30,101, //50
278 0x01, 0x21, 1, 20, 50,
279 0x02, 0x21, 2, 20, 50,
280 0x03, 0x21, 3, 15, 50,
281 0x04, 0x21, 4, 15, 30,
282 0x05, 0x21, 5, 15, 30,
283 0x06, 0x21, 12, 15, 30,
284 0x07, 0x20, 20, 15, 30,
285 0x08, 0x20, 21, 8, 20,
286 0x09, 0x20, 22, 8, 20,
287 0x0a, 0x20, 23, 8, 25,
288 0x0b, 0x22, 23, 8, 25,
290 #endif // DOT11_N_SUPPORT //
292 PUCHAR ReasonString[] = {
294 /* 1 */ "Unspecified Reason",
295 /* 2 */ "Previous Auth no longer valid",
296 /* 3 */ "STA is leaving / has left",
297 /* 4 */ "DIS-ASSOC due to inactivity",
298 /* 5 */ "AP unable to hanle all associations",
299 /* 6 */ "class 2 error",
300 /* 7 */ "class 3 error",
301 /* 8 */ "STA is leaving / has left",
302 /* 9 */ "require auth before assoc/re-assoc",
306 /* 13 */ "invalid IE",
307 /* 14 */ "MIC error",
308 /* 15 */ "4-way handshake timeout",
309 /* 16 */ "2-way (group key) handshake timeout",
310 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
314 extern UCHAR OfdmRateToRxwiMCS[];
315 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
316 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
317 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
318 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
319 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
321 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
322 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
323 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
325 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
326 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
327 // clean environment.
328 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
329 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
331 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
332 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
334 UCHAR SsidIe = IE_SSID;
335 UCHAR SupRateIe = IE_SUPP_RATES;
336 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
337 #ifdef DOT11_N_SUPPORT
338 UCHAR HtCapIe = IE_HT_CAP;
339 UCHAR AddHtInfoIe = IE_ADD_HT;
340 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
341 #endif // DOT11_N_SUPPORT //
342 UCHAR ErpIe = IE_ERP;
343 UCHAR DsIe = IE_DS_PARM;
344 UCHAR TimIe = IE_TIM;
345 UCHAR WpaIe = IE_WPA;
346 UCHAR Wpa2Ie = IE_WPA2;
347 UCHAR IbssIe = IE_IBSS_PARM;
348 UCHAR Ccx2Ie = IE_CCX_V2;
350 extern UCHAR WPA_OUI[];
352 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
354 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
355 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
357 // Reset the RFIC setting to new series
358 RTMP_RF_REGS RF2850RegTable[] = {
359 // ch R1 R2 R3(TX0~4=0) R4
360 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
361 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
362 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
363 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
364 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
365 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
366 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
367 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
368 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
369 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
370 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
371 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
372 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
373 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
375 // 802.11 UNI / HyperLan 2
376 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
377 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
378 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
379 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
380 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
381 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
382 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
383 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
384 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
385 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
386 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
387 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
390 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
392 // 2008.04.30 modified
393 // The system team has AN to improve the EVM value
394 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
395 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
396 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
397 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
399 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
400 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
401 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
402 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
403 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
404 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
405 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
406 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
407 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
408 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
409 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
410 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
413 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
414 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
415 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
416 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
417 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
418 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
419 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
422 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
423 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
424 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
425 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
426 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
427 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
428 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
430 // still lack of MMAC(Japan) ch 34,38,42,46
432 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
434 FREQUENCY_ITEM FreqItems3020[] =
436 /**************************************************/
437 // ISM : 2.4 to 2.483 GHz //
438 /**************************************************/
440 /**************************************************/
441 //-CH---N-------R---K-----------
457 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
460 ==========================================================================
462 initialize the MLME task and its data structure (queue, spinlock,
463 timer, state machines).
468 always return NDIS_STATUS_SUCCESS
470 ==========================================================================
472 NDIS_STATUS MlmeInit(
473 IN PRTMP_ADAPTER pAd)
475 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
477 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
481 Status = MlmeQueueInit(&pAd->Mlme.Queue);
482 if(Status != NDIS_STATUS_SUCCESS)
485 pAd->Mlme.bRunning = FALSE;
486 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
488 #ifdef CONFIG_STA_SUPPORT
489 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
491 BssTableInit(&pAd->ScanTab);
493 // init STA state machines
494 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
495 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
496 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
497 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
498 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
499 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
501 // Since we are using switch/case to implement it, the init is different from the above
502 // state machine init
503 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
505 #endif // CONFIG_STA_SUPPORT //
509 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
511 // Init mlme periodic timer
512 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
514 // Set mlme periodic timer
515 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
517 // software-based RX Antenna diversity
518 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
521 #ifdef CONFIG_STA_SUPPORT
522 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
524 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
526 // only PCIe cards need these two timers
527 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
528 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
531 #endif // CONFIG_STA_SUPPORT //
535 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
541 ==========================================================================
543 main loop of the MLME
545 Mlme has to be initialized, and there are something inside the queue
547 This function is invoked from MPSetInformation and MPReceive;
548 This task guarantee only one MlmeHandler will run.
550 IRQL = DISPATCH_LEVEL
552 ==========================================================================
555 IN PRTMP_ADAPTER pAd)
557 MLME_QUEUE_ELEM *Elem = NULL;
559 // Only accept MLME and Frame from peer side, no other (control/data) frame should
560 // get into this state machine
562 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
563 if(pAd->Mlme.bRunning)
565 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
570 pAd->Mlme.bRunning = TRUE;
572 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
574 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
576 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
577 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
578 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
580 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
584 //From message type, determine which state machine I should drive
585 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
588 // if dequeue success
589 switch (Elem->Machine)
591 // STA state machines
592 #ifdef CONFIG_STA_SUPPORT
593 case ASSOC_STATE_MACHINE:
594 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
596 case AUTH_STATE_MACHINE:
597 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
599 case AUTH_RSP_STATE_MACHINE:
600 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
602 case SYNC_STATE_MACHINE:
603 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
605 case MLME_CNTL_STATE_MACHINE:
606 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
608 case WPA_PSK_STATE_MACHINE:
609 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
611 case AIRONET_STATE_MACHINE:
612 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
614 #endif // CONFIG_STA_SUPPORT //
616 case ACTION_STATE_MACHINE:
617 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
624 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
629 Elem->Occupied = FALSE;
634 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
638 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
639 pAd->Mlme.bRunning = FALSE;
640 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
644 ==========================================================================
646 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
648 Adapter - NIC Adapter pointer
650 The MLME task will no longer work properly
654 ==========================================================================
657 IN PRTMP_ADAPTER pAd)
661 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
663 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
665 // disable BEACON generation and other BEACON related hardware timers
666 AsicDisableSync(pAd);
669 #ifdef CONFIG_STA_SUPPORT
670 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
672 // Cancel pending timers
673 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
674 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
675 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
676 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
677 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
678 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
679 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
681 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
682 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
685 #endif // CONFIG_STA_SUPPORT //
687 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
688 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
692 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
695 RTMPSetLED(pAd, LED_HALT);
696 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
699 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
701 MlmeQueueDestroy(&pAd->Mlme.Queue);
702 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
704 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
707 VOID MlmeResetRalinkCounters(
708 IN PRTMP_ADAPTER pAd)
710 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
711 // clear all OneSecxxx counters.
712 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
713 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
714 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
715 pAd->RalinkCounters.OneSecRxOkCnt = 0;
716 pAd->RalinkCounters.OneSecTxFailCount = 0;
717 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
718 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
719 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
721 // TODO: for debug only. to be removed
722 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
723 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
724 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
725 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
726 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
727 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
728 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
729 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
730 pAd->RalinkCounters.OneSecTxDoneCount = 0;
731 pAd->RalinkCounters.OneSecRxCount = 0;
732 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
733 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
738 unsigned long rx_AMSDU;
739 unsigned long rx_Total;
742 ==========================================================================
744 This routine is executed periodically to -
745 1. Decide if it's a right time to turn on PwrMgmt bit of all
747 2. Calculate ChannelQuality based on statistics of the last
748 period, so that TX rate won't toggling very frequently between a
749 successful TX and a failed TX.
750 3. If the calculated ChannelQuality indicated current connection not
751 healthy, then a ROAMing attempt is tried here.
753 IRQL = DISPATCH_LEVEL
755 ==========================================================================
757 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
758 VOID MlmePeriodicExec(
759 IN PVOID SystemSpecific1,
760 IN PVOID FunctionContext,
761 IN PVOID SystemSpecific2,
762 IN PVOID SystemSpecific3)
765 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
768 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
769 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
770 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
771 if(pAd->StaCfg.WepStatus<2)
773 pAd->StaCfg.WpaSupplicantUP = 0;
777 pAd->StaCfg.WpaSupplicantUP = 1;
780 #ifdef CONFIG_STA_SUPPORT
781 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
783 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
784 // Move code to here, because following code will return when radio is off
785 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
786 (pAd->StaCfg.bHardwareRadio == TRUE) &&
787 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
788 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
789 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
793 // Read GPIO pin2 as Hardware controlled radio state
794 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
797 pAd->StaCfg.bHwRadio = TRUE;
801 pAd->StaCfg.bHwRadio = FALSE;
803 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
805 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
806 if (pAd->StaCfg.bRadio == TRUE)
809 // Update extra information
810 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
815 // Update extra information
816 pAd->ExtraInfo = HW_RADIO_OFF;
821 #endif // CONFIG_STA_SUPPORT //
823 // Do nothing if the driver is starting halt state.
824 // This might happen when timer already been fired before cancel timer with mlmehalt
825 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
826 fRTMP_ADAPTER_RADIO_OFF |
827 fRTMP_ADAPTER_RADIO_MEASUREMENT |
828 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
831 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
833 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
835 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
836 pAd->SameRxByteCount++;
839 pAd->SameRxByteCount = 0;
841 // If after BBP, still not work...need to check to reset PBF&MAC.
842 if (pAd->SameRxByteCount == 702)
844 pAd->SameRxByteCount = 0;
849 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
850 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
852 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
854 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
855 pAd->SameRxByteCount = 700;
860 // Update lastReceiveByteCount.
861 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
863 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
865 pAd->CheckDmaBusyCount = 0;
866 AsicResetFromDMABusy(pAd);
870 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
872 #ifdef CONFIG_STA_SUPPORT
873 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
875 // Do nothing if monitor mode is on
879 if (pAd->Mlme.PeriodicRound & 0x1)
881 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
882 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
883 (STA_TGN_WIFI_ON(pAd)) &&
884 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
887 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
888 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
890 else if ((STA_TGN_WIFI_ON(pAd)) &&
891 ((pAd->MACVersion & 0xffff) == 0x0101))
893 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
894 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
898 #endif // CONFIG_STA_SUPPORT //
900 pAd->bUpdateBcnCntDone = FALSE;
902 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
903 pAd->Mlme.PeriodicRound ++;
905 // execute every 500ms
906 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
908 #ifdef CONFIG_STA_SUPPORT
909 // perform dynamic tx rate switching based on past TX history
910 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
912 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
914 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
915 MlmeDynamicTxRateSwitching(pAd);
917 #endif // CONFIG_STA_SUPPORT //
920 // Normal 1 second Mlme PeriodicExec.
921 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
923 pAd->Mlme.OneSecPeriodicRound ++;
933 // Media status changed, report to NDIS
934 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
936 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
937 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
939 pAd->IndicateMediaState = NdisMediaStateConnected;
940 RTMP_IndicateMediaState(pAd);
945 pAd->IndicateMediaState = NdisMediaStateDisconnected;
946 RTMP_IndicateMediaState(pAd);
950 NdisGetSystemUpTime(&pAd->Mlme.Now32);
952 // add the most up-to-date h/w raw counters into software variable, so that
953 // the dynamic tuning mechanism below are based on most up-to-date information
954 NICUpdateRawCounters(pAd);
957 #ifdef DOT11_N_SUPPORT
958 // Need statistics after read counter. So put after NICUpdateRawCounters
959 ORIBATimerTimeout(pAd);
960 #endif // DOT11_N_SUPPORT //
963 // The time period for checking antenna is according to traffic
964 if (pAd->Mlme.bEnableAutoAntennaCheck)
966 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
967 pAd->RalinkCounters.OneSecTxRetryOkCount +
968 pAd->RalinkCounters.OneSecTxFailCount;
972 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
974 AsicEvaluateRxAnt(pAd);
979 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
981 AsicEvaluateRxAnt(pAd);
986 #ifdef CONFIG_STA_SUPPORT
987 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
988 STAMlmePeriodicExec(pAd);
989 #endif // CONFIG_STA_SUPPORT //
991 MlmeResetRalinkCounters(pAd);
993 #ifdef CONFIG_STA_SUPPORT
994 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
996 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
998 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
999 // and sending CTS-to-self over and over.
1000 // Software Patch Solution:
1001 // 1. Polling debug state register 0x10F4 every one second.
1002 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1003 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1007 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1008 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1010 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1012 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1014 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1018 #endif // CONFIG_STA_SUPPORT //
1020 RT28XX_MLME_HANDLER(pAd);
1024 pAd->bUpdateBcnCntDone = FALSE;
1027 #ifdef CONFIG_STA_SUPPORT
1028 VOID STAMlmePeriodicExec(
1033 #ifdef WPA_SUPPLICANT_SUPPORT
1034 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1035 #endif // WPA_SUPPLICANT_SUPPORT //
1037 // WPA MIC error should block association attempt for 60 seconds
1038 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1039 pAd->StaCfg.bBlockAssoc = FALSE;
1043 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1044 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1045 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1046 if(pAd->StaCfg.WepStatus<2)
1048 pAd->StaCfg.WpaSupplicantUP = 0;
1052 pAd->StaCfg.WpaSupplicantUP = 1;
1055 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1057 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1059 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1061 pAd->PreMediaState = pAd->IndicateMediaState;
1064 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1065 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1066 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1067 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1068 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1069 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1071 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1076 AsicStaBbpTuning(pAd);
1078 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1079 pAd->RalinkCounters.OneSecTxRetryOkCount +
1080 pAd->RalinkCounters.OneSecTxFailCount;
1082 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1084 // update channel quality for Roaming and UI LinkQuality display
1085 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1088 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1089 // Radio is currently in noisy environment
1090 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1091 AsicAdjustTxPower(pAd);
1095 // Is PSM bit consistent with user power management policy?
1096 // This is the only place that will set PSM bit ON.
1097 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1098 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1100 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1102 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1103 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1104 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1106 RTMPSetAGCInitValue(pAd, BW_20);
1107 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1111 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1113 // When APSD is enabled, the period changes as 20 sec
1114 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1115 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1119 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1120 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1122 if (pAd->CommonCfg.bWmmCapable)
1123 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1125 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1130 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1132 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1133 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1134 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1136 // Lost AP, send disconnect & link down event
1137 LinkDown(pAd, FALSE);
1139 #ifdef WPA_SUPPLICANT_SUPPORT
1140 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1141 if (pAd->StaCfg.WpaSupplicantUP)
1143 union iwreq_data wrqu;
1144 //send disassociate event to wpa_supplicant
1145 memset(&wrqu, 0, sizeof(wrqu));
1146 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1147 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1149 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1150 #endif // WPA_SUPPLICANT_SUPPORT //
1152 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1154 union iwreq_data wrqu;
1155 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1156 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1158 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1160 MlmeAutoReconnectLastSSID(pAd);
1162 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1164 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1165 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1166 MlmeAutoReconnectLastSSID(pAd);
1169 // Add auto seamless roaming
1170 if (pAd->StaCfg.bFastRoaming)
1172 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1174 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));
1176 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1178 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1182 else if (ADHOC_ON(pAd))
1184 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1185 // the "TX BEACON competition" for the entire past 1 sec.
1186 // So that even when ASIC's BEACONgen engine been blocked
1187 // by peer's BEACON due to slower system clock, this STA still can send out
1188 // minimum BEACON to tell the peer I'm alive.
1189 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1190 // EnqueueBeaconFrame(pAd); // software send BEACON
1192 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1193 // restore outgoing BEACON to support B/G-mixed mode
1194 if ((pAd->CommonCfg.Channel <= 14) &&
1195 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1196 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1197 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1199 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1200 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1201 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1202 MlmeUpdateTxRates(pAd, FALSE, 0);
1203 MakeIbssBeacon(pAd); // re-build BEACON frame
1204 AsicEnableIbssSync(pAd); // copy to on-chip memory
1205 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1208 #ifdef DOT11_N_SUPPORT
1209 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1211 if ((pAd->StaCfg.AdhocBGJoined) &&
1212 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1214 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1215 pAd->StaCfg.AdhocBGJoined = FALSE;
1218 if ((pAd->StaCfg.Adhoc20NJoined) &&
1219 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1221 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1222 pAd->StaCfg.Adhoc20NJoined = FALSE;
1225 #endif // DOT11_N_SUPPORT //
1228 if ((pAd->CommonCfg.Channel > 14)
1229 && (pAd->CommonCfg.bIEEE80211H == 1)
1230 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1232 RadarDetectPeriodic(pAd);
1235 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1236 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1238 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1239 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1241 MLME_START_REQ_STRUCT StartReq;
1243 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1244 LinkDown(pAd, FALSE);
1246 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1247 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1248 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1251 else // no INFRA nor ADHOC connection
1254 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1255 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1256 goto SKIP_AUTO_SCAN_CONN;
1258 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1260 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1261 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1262 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1264 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1266 MLME_SCAN_REQ_STRUCT ScanReq;
1268 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1270 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1271 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1272 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1273 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1274 // Reset Missed scan number
1275 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1277 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1278 MlmeAutoReconnectLastSSID(pAd);
1280 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1282 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1285 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1289 MlmeAutoReconnectLastSSID(pAd);
1295 SKIP_AUTO_SCAN_CONN:
1297 #ifdef DOT11_N_SUPPORT
1298 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1300 pAd->MacTab.fAnyBASession = TRUE;
1301 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1303 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1305 pAd->MacTab.fAnyBASession = FALSE;
1306 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1308 #endif // DOT11_N_SUPPORT //
1315 IN PVOID SystemSpecific1,
1316 IN PVOID FunctionContext,
1317 IN PVOID SystemSpecific2,
1318 IN PVOID SystemSpecific3)
1321 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1323 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1324 RTMP_IndicateMediaState(pAd);
1325 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1328 // IRQL = DISPATCH_LEVEL
1330 IN PRTMP_ADAPTER pAd)
1332 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1333 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1335 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1337 MLME_CNTL_STATE_MACHINE,
1338 OID_802_11_BSSID_LIST_SCAN,
1341 RT28XX_MLME_HANDLER(pAd);
1345 // IRQL = DISPATCH_LEVEL
1346 VOID MlmeAutoReconnectLastSSID(
1347 IN PRTMP_ADAPTER pAd)
1351 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1352 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1353 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1355 NDIS_802_11_SSID OidSsid;
1356 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1357 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1359 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1361 MLME_CNTL_STATE_MACHINE,
1363 sizeof(NDIS_802_11_SSID),
1365 RT28XX_MLME_HANDLER(pAd);
1368 #endif // CONFIG_STA_SUPPORT //
1371 ==========================================================================
1372 Validate SSID for connection try and rescan purpose
1373 Valid SSID will have visible chars only.
1374 The valid length is from 0 to 32.
1375 IRQL = DISPATCH_LEVEL
1376 ==========================================================================
1378 BOOLEAN MlmeValidateSSID(
1384 if (SsidLen > MAX_LEN_OF_SSID)
1387 // Check each character value
1388 for (index = 0; index < SsidLen; index++)
1390 if (pSsid[index] < 0x20)
1398 VOID MlmeSelectTxRateTable(
1399 IN PRTMP_ADAPTER pAd,
1400 IN PMAC_TABLE_ENTRY pEntry,
1402 IN PUCHAR pTableSize,
1403 IN PUCHAR pInitTxRateIdx)
1407 // decide the rate table for tuning
1408 if (pAd->CommonCfg.TxRateTableSize > 0)
1410 *ppTable = RateSwitchTable;
1411 *pTableSize = RateSwitchTable[0];
1412 *pInitTxRateIdx = RateSwitchTable[1];
1417 #ifdef CONFIG_STA_SUPPORT
1418 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1420 #ifdef DOT11_N_SUPPORT
1421 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1422 !pAd->StaCfg.AdhocBOnlyJoined &&
1423 !pAd->StaCfg.AdhocBGJoined &&
1424 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1425 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1427 *ppTable = RateSwitchTable11N1S;
1428 *pTableSize = RateSwitchTable11N1S[0];
1429 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1432 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1433 !pAd->StaCfg.AdhocBOnlyJoined &&
1434 !pAd->StaCfg.AdhocBGJoined &&
1435 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1436 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1437 (pAd->Antenna.field.TxPath == 2))
1439 if (pAd->LatchRfRegs.Channel <= 14)
1441 *ppTable = RateSwitchTable11N2S;
1442 *pTableSize = RateSwitchTable11N2S[0];
1443 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1447 *ppTable = RateSwitchTable11N2SForABand;
1448 *pTableSize = RateSwitchTable11N2SForABand[0];
1449 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1454 #endif // DOT11_N_SUPPORT //
1455 if (pAd->CommonCfg.PhyMode == PHY_11B)
1457 *ppTable = RateSwitchTable11B;
1458 *pTableSize = RateSwitchTable11B[0];
1459 *pInitTxRateIdx = RateSwitchTable11B[1];
1462 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1464 // USe B Table when Only b-only Station in my IBSS .
1465 *ppTable = RateSwitchTable11B;
1466 *pTableSize = RateSwitchTable11B[0];
1467 *pInitTxRateIdx = RateSwitchTable11B[1];
1470 else if (pAd->LatchRfRegs.Channel <= 14)
1472 *ppTable = RateSwitchTable11BG;
1473 *pTableSize = RateSwitchTable11BG[0];
1474 *pInitTxRateIdx = RateSwitchTable11BG[1];
1479 *ppTable = RateSwitchTable11G;
1480 *pTableSize = RateSwitchTable11G[0];
1481 *pInitTxRateIdx = RateSwitchTable11G[1];
1486 #endif // CONFIG_STA_SUPPORT //
1488 #ifdef DOT11_N_SUPPORT
1489 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1490 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1492 *ppTable = RateSwitchTable11BGN1S;
1493 *pTableSize = RateSwitchTable11BGN1S[0];
1494 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1499 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1500 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1502 if (pAd->LatchRfRegs.Channel <= 14)
1504 *ppTable = RateSwitchTable11BGN2S;
1505 *pTableSize = RateSwitchTable11BGN2S[0];
1506 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1511 *ppTable = RateSwitchTable11BGN2SForABand;
1512 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1513 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1519 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1521 *ppTable = RateSwitchTable11N1S;
1522 *pTableSize = RateSwitchTable11N1S[0];
1523 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1528 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1530 if (pAd->LatchRfRegs.Channel <= 14)
1532 *ppTable = RateSwitchTable11N2S;
1533 *pTableSize = RateSwitchTable11N2S[0];
1534 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1538 *ppTable = RateSwitchTable11N2SForABand;
1539 *pTableSize = RateSwitchTable11N2SForABand[0];
1540 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1545 #endif // DOT11_N_SUPPORT //
1546 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1547 if ((pEntry->RateLen == 4)
1548 #ifdef DOT11_N_SUPPORT
1549 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1550 #endif // DOT11_N_SUPPORT //
1553 *ppTable = RateSwitchTable11B;
1554 *pTableSize = RateSwitchTable11B[0];
1555 *pInitTxRateIdx = RateSwitchTable11B[1];
1560 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1561 if ((pEntry->RateLen > 8)
1562 #ifdef DOT11_N_SUPPORT
1563 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1564 #endif // DOT11_N_SUPPORT //
1567 *ppTable = RateSwitchTable11BG;
1568 *pTableSize = RateSwitchTable11BG[0];
1569 *pInitTxRateIdx = RateSwitchTable11BG[1];
1574 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1575 if ((pEntry->RateLen == 8)
1576 #ifdef DOT11_N_SUPPORT
1577 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1578 #endif // DOT11_N_SUPPORT //
1581 *ppTable = RateSwitchTable11G;
1582 *pTableSize = RateSwitchTable11G[0];
1583 *pInitTxRateIdx = RateSwitchTable11G[1];
1587 #ifdef DOT11_N_SUPPORT
1588 #endif // DOT11_N_SUPPORT //
1590 #ifdef CONFIG_STA_SUPPORT
1591 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1593 #ifdef DOT11_N_SUPPORT
1594 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1595 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1596 #endif // DOT11_N_SUPPORT //
1598 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1600 *ppTable = RateSwitchTable11B;
1601 *pTableSize = RateSwitchTable11B[0];
1602 *pInitTxRateIdx = RateSwitchTable11B[1];
1604 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1606 *ppTable = RateSwitchTable11G;
1607 *pTableSize = RateSwitchTable11G[0];
1608 *pInitTxRateIdx = RateSwitchTable11G[1];
1613 *ppTable = RateSwitchTable11BG;
1614 *pTableSize = RateSwitchTable11BG[0];
1615 *pInitTxRateIdx = RateSwitchTable11BG[1];
1619 #ifdef DOT11_N_SUPPORT
1620 if (pAd->LatchRfRegs.Channel <= 14)
1622 if (pAd->CommonCfg.TxStream == 1)
1624 *ppTable = RateSwitchTable11N1S;
1625 *pTableSize = RateSwitchTable11N1S[0];
1626 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1627 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1631 *ppTable = RateSwitchTable11N2S;
1632 *pTableSize = RateSwitchTable11N2S[0];
1633 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1634 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1639 if (pAd->CommonCfg.TxStream == 1)
1641 *ppTable = RateSwitchTable11N1S;
1642 *pTableSize = RateSwitchTable11N1S[0];
1643 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1644 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1648 *ppTable = RateSwitchTable11N2SForABand;
1649 *pTableSize = RateSwitchTable11N2SForABand[0];
1650 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1651 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1654 #endif // DOT11_N_SUPPORT //
1655 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1656 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1658 #endif // CONFIG_STA_SUPPORT //
1662 #ifdef CONFIG_STA_SUPPORT
1664 ==========================================================================
1666 This routine checks if there're other APs out there capable for
1667 roaming. Caller should call this routine only when Link up in INFRA mode
1668 and channel quality is below CQI_GOOD_THRESHOLD.
1670 IRQL = DISPATCH_LEVEL
1673 ==========================================================================
1675 VOID MlmeCheckForRoaming(
1676 IN PRTMP_ADAPTER pAd,
1680 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1683 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1684 // put all roaming candidates into RoamTab, and sort in RSSI order
1685 BssTableInit(pRoamTab);
1686 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1688 pBss = &pAd->ScanTab.BssEntry[i];
1690 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1691 continue; // AP disappear
1692 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1693 continue; // RSSI too weak. forget it.
1694 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1695 continue; // skip current AP
1696 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1697 continue; // only AP with stronger RSSI is eligible for roaming
1699 // AP passing all above rules is put into roaming candidate table
1700 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1701 pRoamTab->BssNr += 1;
1704 if (pRoamTab->BssNr > 0)
1706 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1707 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1709 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1710 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1711 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1712 RT28XX_MLME_HANDLER(pAd);
1715 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1719 ==========================================================================
1721 This routine checks if there're other APs out there capable for
1722 roaming. Caller should call this routine only when link up in INFRA mode
1723 and channel quality is below CQI_GOOD_THRESHOLD.
1725 IRQL = DISPATCH_LEVEL
1728 ==========================================================================
1730 VOID MlmeCheckForFastRoaming(
1731 IN PRTMP_ADAPTER pAd,
1735 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1738 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1739 // put all roaming candidates into RoamTab, and sort in RSSI order
1740 BssTableInit(pRoamTab);
1741 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1743 pBss = &pAd->ScanTab.BssEntry[i];
1745 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1746 continue; // RSSI too weak. forget it.
1747 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1748 continue; // skip current AP
1749 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1750 continue; // skip different SSID
1751 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1752 continue; // skip AP without better RSSI
1754 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));
1755 // AP passing all above rules is put into roaming candidate table
1756 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1757 pRoamTab->BssNr += 1;
1760 if (pRoamTab->BssNr > 0)
1762 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1763 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1765 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1766 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1767 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1768 RT28XX_MLME_HANDLER(pAd);
1771 // Maybe site survey required
1774 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1776 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1777 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1778 pAd->StaCfg.ScanCnt = 2;
1779 pAd->StaCfg.LastScanTime = Now;
1784 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1788 ==========================================================================
1790 This routine calculates TxPER, RxPER of the past N-sec period. And
1791 according to the calculation result, ChannelQuality is calculated here
1792 to decide if current AP is still doing the job.
1794 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1796 StaCfg.ChannelQuality - 0..100
1798 IRQL = DISPATCH_LEVEL
1800 NOTE: This routine decide channle quality based on RX CRC error ratio.
1801 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1802 is performed right before this routine, so that this routine can decide
1803 channel quality based on the most up-to-date information
1804 ==========================================================================
1806 VOID MlmeCalculateChannelQuality(
1807 IN PRTMP_ADAPTER pAd,
1810 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1814 ULONG BeaconLostTime = BEACON_LOST_TIME;
1816 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1819 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1821 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1822 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1830 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1831 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1835 // calculate RX PER - don't take RxPER into consideration if too few sample
1837 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1841 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1844 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1846 if (INFRA_ON(pAd) &&
1847 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1848 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1850 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1851 pAd->Mlme.ChannelQuality = 0;
1858 else if (MaxRssi < -90)
1861 NorRssi = (MaxRssi + 90) * 2;
1863 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1864 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1865 TX_WEIGHTING * (100 - TxPRR) +
1866 RX_WEIGHTING* (100 - RxPER)) / 100;
1867 if (pAd->Mlme.ChannelQuality >= 100)
1868 pAd->Mlme.ChannelQuality = 100;
1874 IN PRTMP_ADAPTER pAd,
1875 IN PMAC_TABLE_ENTRY pEntry,
1876 IN PRTMP_TX_RATE_SWITCH pTxRate)
1878 UCHAR MaxMode = MODE_OFDM;
1880 #ifdef DOT11_N_SUPPORT
1881 MaxMode = MODE_HTGREENFIELD;
1883 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1884 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1886 #endif // DOT11_N_SUPPORT //
1887 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1889 if (pTxRate->CurrMCS < MCS_AUTO)
1890 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1892 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1893 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1897 // If peer adhoc is b-only mode, we can't send 11g rate.
1898 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1899 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1902 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1904 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1905 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1906 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1908 // Patch speed error in status page
1909 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1913 if (pTxRate->Mode <= MaxMode)
1914 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1916 #ifdef DOT11_N_SUPPORT
1917 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1918 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1920 #endif // DOT11_N_SUPPORT //
1921 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1923 #ifdef DOT11_N_SUPPORT
1924 // Reexam each bandwidth's SGI support.
1925 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1927 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1928 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1929 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1930 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1933 // Turn RTS/CTS rate to 6Mbps.
1934 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1936 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1937 if (pAd->MacTab.fAnyBASession)
1939 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1943 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1946 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1948 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1949 if (pAd->MacTab.fAnyBASession)
1951 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1955 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1958 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1960 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1963 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1965 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1967 #endif // DOT11_N_SUPPORT //
1969 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1970 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1971 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1972 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1973 #ifdef DOT11_N_SUPPORT
1974 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1975 pAd->WIFItestbed.bGreenField)
1976 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1977 #endif // DOT11_N_SUPPORT //
1980 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1984 ==========================================================================
1986 This routine calculates the acumulated TxPER of eaxh TxRate. And
1987 according to the calculation result, change CommonCfg.TxRate which
1988 is the stable TX Rate we expect the Radio situation could sustained.
1990 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1994 IRQL = DISPATCH_LEVEL
1997 call this routine every second
1998 ==========================================================================
2000 VOID MlmeDynamicTxRateSwitching(
2001 IN PRTMP_ADAPTER pAd)
2003 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2004 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2005 ULONG TxErrorRatio = 0;
2006 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2007 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2009 UCHAR TableSize = 0;
2010 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2011 CHAR Rssi, RssiOffset = 0;
2012 TX_STA_CNT1_STRUC StaTx1;
2013 TX_STA_CNT0_STRUC TxStaCnt0;
2014 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2015 MAC_TABLE_ENTRY *pEntry;
2017 /*if (pAd->Antenna.field.RxPath > 1)
2018 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2020 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2023 // walk through MAC table, see if need to change AP's TX rate toward each entry
2025 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2027 pEntry = &pAd->MacTab.Content[i];
2029 // check if this entry need to switch rate automatically
2030 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2033 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2035 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2037 // Update statistic counter
2038 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2039 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2040 pAd->bUpdateBcnCntDone = TRUE;
2041 TxRetransmit = StaTx1.field.TxRetransmit;
2042 TxSuccess = StaTx1.field.TxSuccess;
2043 TxFailCount = TxStaCnt0.field.TxFailCount;
2044 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2046 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2047 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2048 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2049 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2050 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2051 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2053 // if no traffic in the past 1-sec period, don't change TX rate,
2054 // but clear all bad history. because the bad history may affect the next
2055 // Chariot throughput test
2056 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2057 pAd->RalinkCounters.OneSecTxRetryOkCount +
2058 pAd->RalinkCounters.OneSecTxFailCount;
2061 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2065 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2067 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2068 pEntry->OneSecTxRetryOkCount +
2069 pEntry->OneSecTxFailCount;
2072 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2075 CurrRateIdx = pEntry->CurrTxRateIndex;
2077 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2079 if (CurrRateIdx >= TableSize)
2081 CurrRateIdx = TableSize - 1;
2084 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2085 // So need to sync here.
2086 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2087 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2088 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2092 // Need to sync Real Tx rate and our record.
2093 // Then return for next DRS.
2094 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2095 pEntry->CurrTxRateIndex = InitTxRateIdx;
2096 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2098 // reset all OneSecTx counters
2099 RESET_ONE_SEC_TX_CNT(pEntry);
2103 // decide the next upgrade rate and downgrade rate, if any
2104 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2106 UpRateIdx = CurrRateIdx + 1;
2107 DownRateIdx = CurrRateIdx -1;
2109 else if (CurrRateIdx == 0)
2111 UpRateIdx = CurrRateIdx + 1;
2112 DownRateIdx = CurrRateIdx;
2114 else if (CurrRateIdx == (TableSize - 1))
2116 UpRateIdx = CurrRateIdx;
2117 DownRateIdx = CurrRateIdx - 1;
2120 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2122 #ifdef DOT11_N_SUPPORT
2123 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2125 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2126 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2129 #endif // DOT11_N_SUPPORT //
2131 TrainUp = pCurrTxRate->TrainUp;
2132 TrainDown = pCurrTxRate->TrainDown;
2135 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2138 // Keep the last time TxRateChangeAction status.
2140 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2145 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2146 // (criteria copied from RT2500 for Netopia case)
2148 if (TxTotalCnt <= 15)
2152 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2153 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2154 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2155 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2157 // check the existence and index of each needed MCS
2158 while (idx < pTable[0])
2160 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2162 if (pCurrTxRate->CurrMCS == MCS_0)
2166 else if (pCurrTxRate->CurrMCS == MCS_1)
2170 else if (pCurrTxRate->CurrMCS == MCS_2)
2174 else if (pCurrTxRate->CurrMCS == MCS_3)
2178 else if (pCurrTxRate->CurrMCS == MCS_4)
2182 else if (pCurrTxRate->CurrMCS == MCS_5)
2186 else if (pCurrTxRate->CurrMCS == MCS_6)
2190 //else if (pCurrTxRate->CurrMCS == MCS_7)
2191 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2195 else if (pCurrTxRate->CurrMCS == MCS_12)
2199 else if (pCurrTxRate->CurrMCS == MCS_13)
2203 else if (pCurrTxRate->CurrMCS == MCS_14)
2207 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2208 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
2212 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2216 else if (pCurrTxRate->CurrMCS == MCS_21)
2220 else if (pCurrTxRate->CurrMCS == MCS_22)
2224 else if (pCurrTxRate->CurrMCS == MCS_23)
2231 if (pAd->LatchRfRegs.Channel <= 14)
2233 if (pAd->NicConfig2.field.ExternalLNAForG)
2244 if (pAd->NicConfig2.field.ExternalLNAForA)
2253 #ifdef DOT11_N_SUPPORT
2255 if ((pTable == RateSwitchTable11BGN3S) ||
2256 (pTable == RateSwitchTable11N3S) ||
2257 (pTable == RateSwitchTable))
2258 {// N mode with 3 stream // 3*3
2259 if (MCS23 && (Rssi >= -70))
2261 else if (MCS22 && (Rssi >= -72))
2263 else if (MCS21 && (Rssi >= -76))
2265 else if (MCS20 && (Rssi >= -78))
2267 else if (MCS4 && (Rssi >= -82))
2269 else if (MCS3 && (Rssi >= -84))
2271 else if (MCS2 && (Rssi >= -86))
2273 else if (MCS1 && (Rssi >= -88))
2278 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2279 {// N mode with 2 stream
2280 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2282 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2284 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2286 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2288 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2290 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2292 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2294 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2299 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2300 {// N mode with 1 stream
2301 if (MCS7 && (Rssi > (-72+RssiOffset)))
2303 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2305 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2307 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2309 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2311 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2313 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2319 #endif // DOT11_N_SUPPORT //
2321 if (MCS7 && (Rssi > -70))
2323 else if (MCS6 && (Rssi > -74))
2325 else if (MCS5 && (Rssi > -78))
2327 else if (MCS4 && (Rssi > -82))
2329 else if (MCS4 == 0) // for B-only mode
2331 else if (MCS3 && (Rssi > -85))
2333 else if (MCS2 && (Rssi > -87))
2335 else if (MCS1 && (Rssi > -90))
2342 pEntry->CurrTxRateIndex = TxRateIdx;
2343 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2344 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2347 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2348 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2349 pEntry->fLastSecAccordingRSSI = TRUE;
2350 // reset all OneSecTx counters
2351 RESET_ONE_SEC_TX_CNT(pEntry);
2356 if (pEntry->fLastSecAccordingRSSI == TRUE)
2358 pEntry->fLastSecAccordingRSSI = FALSE;
2359 pEntry->LastSecTxRateChangeAction = 0;
2360 // reset all OneSecTx counters
2361 RESET_ONE_SEC_TX_CNT(pEntry);
2368 BOOLEAN bTrainUpDown = FALSE;
2370 pEntry->CurrTxRateStableTime ++;
2372 // downgrade TX quality if PER >= Rate-Down threshold
2373 if (TxErrorRatio >= TrainDown)
2375 bTrainUpDown = TRUE;
2376 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2378 // upgrade TX quality if PER <= Rate-Up threshold
2379 else if (TxErrorRatio <= TrainUp)
2381 bTrainUpDown = TRUE;
2382 bUpgradeQuality = TRUE;
2383 if (pEntry->TxQuality[CurrRateIdx])
2384 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2386 if (pEntry->TxRateUpPenalty)
2387 pEntry->TxRateUpPenalty --;
2388 else if (pEntry->TxQuality[UpRateIdx])
2389 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2392 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2396 // perform DRS - consider TxRate Down first, then rate up.
2397 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2399 pEntry->CurrTxRateIndex = DownRateIdx;
2401 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2403 pEntry->CurrTxRateIndex = UpRateIdx;
2408 // if rate-up happen, clear all bad history of all TX rates
2409 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2411 pEntry->CurrTxRateStableTime = 0;
2412 pEntry->TxRateUpPenalty = 0;
2413 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2414 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2415 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2418 // For TxRate fast train up
2420 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2422 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2424 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2426 bTxRateChanged = TRUE;
2428 // if rate-down happen, only clear DownRate's bad history
2429 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2431 pEntry->CurrTxRateStableTime = 0;
2432 pEntry->TxRateUpPenalty = 0; // no penalty
2433 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2434 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2435 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2438 // For TxRate fast train down
2440 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2442 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2444 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2446 bTxRateChanged = TRUE;
2450 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2451 bTxRateChanged = FALSE;
2454 pEntry->LastTxOkCount = TxSuccess;
2456 // reset all OneSecTx counters
2457 RESET_ONE_SEC_TX_CNT(pEntry);
2459 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2460 if (bTxRateChanged && pNextTxRate)
2462 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2468 ========================================================================
2469 Routine Description:
2470 Station side, Auto TxRate faster train up timer call back function.
2473 SystemSpecific1 - Not used.
2474 FunctionContext - Pointer to our Adapter context.
2475 SystemSpecific2 - Not used.
2476 SystemSpecific3 - Not used.
2481 ========================================================================
2483 VOID StaQuickResponeForRateUpExec(
2484 IN PVOID SystemSpecific1,
2485 IN PVOID FunctionContext,
2486 IN PVOID SystemSpecific2,
2487 IN PVOID SystemSpecific3)
2489 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2490 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2492 ULONG TxErrorRatio = 0;
2493 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2494 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2496 UCHAR TableSize = 0;
2497 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2498 TX_STA_CNT1_STRUC StaTx1;
2499 TX_STA_CNT0_STRUC TxStaCnt0;
2501 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2502 MAC_TABLE_ENTRY *pEntry;
2505 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2508 // walk through MAC table, see if need to change AP's TX rate toward each entry
2510 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2512 pEntry = &pAd->MacTab.Content[i];
2514 // check if this entry need to switch rate automatically
2515 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2518 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2519 if (pAd->Antenna.field.TxPath > 1)
2520 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2522 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2524 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2526 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2528 // decide the next upgrade rate and downgrade rate, if any
2529 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2531 UpRateIdx = CurrRateIdx + 1;
2532 DownRateIdx = CurrRateIdx -1;
2534 else if (CurrRateIdx == 0)
2536 UpRateIdx = CurrRateIdx + 1;
2537 DownRateIdx = CurrRateIdx;
2539 else if (CurrRateIdx == (TableSize - 1))
2541 UpRateIdx = CurrRateIdx;
2542 DownRateIdx = CurrRateIdx - 1;
2545 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2547 #ifdef DOT11_N_SUPPORT
2548 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2550 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2551 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2554 #endif // DOT11_N_SUPPORT //
2556 TrainUp = pCurrTxRate->TrainUp;
2557 TrainDown = pCurrTxRate->TrainDown;
2560 if (pAd->MacTab.Size == 1)
2562 // Update statistic counter
2563 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2564 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2566 TxRetransmit = StaTx1.field.TxRetransmit;
2567 TxSuccess = StaTx1.field.TxSuccess;
2568 TxFailCount = TxStaCnt0.field.TxFailCount;
2569 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2571 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2572 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2573 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2574 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2575 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2576 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2579 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2583 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2584 pEntry->OneSecTxRetryOkCount +
2585 pEntry->OneSecTxFailCount;
2588 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2593 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2594 // (criteria copied from RT2500 for Netopia case)
2596 if (TxTotalCnt <= 12)
2598 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2599 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2601 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2603 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2604 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2606 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2608 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2611 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2617 ULONG OneSecTxNoRetryOKRationCount;
2619 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2624 // downgrade TX quality if PER >= Rate-Down threshold
2625 if (TxErrorRatio >= TrainDown)
2627 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2630 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2632 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2634 // perform DRS - consider TxRate Down first, then rate up.
2635 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2637 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2639 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2640 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2645 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2647 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2651 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2653 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2658 // if rate-up happen, clear all bad history of all TX rates
2659 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2661 pAd->DrsCounters.TxRateUpPenalty = 0;
2662 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2663 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2665 // if rate-down happen, only clear DownRate's bad history
2666 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2668 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2670 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2671 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2672 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2676 bTxRateChanged = FALSE;
2679 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2680 if (bTxRateChanged && pNextTxRate)
2682 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2688 ==========================================================================
2690 This routine is executed periodically inside MlmePeriodicExec() after
2691 association with an AP.
2692 It checks if StaCfg.Psm is consistent with user policy (recorded in
2693 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2694 there're some conditions to consider:
2695 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2696 the time when Mibss==TRUE
2697 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2698 if outgoing traffic available in TxRing or MgmtRing.
2700 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2702 IRQL = DISPATCH_LEVEL
2704 ==========================================================================
2706 VOID MlmeCheckPsmChange(
2707 IN PRTMP_ADAPTER pAd,
2713 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2714 // 2. user wants either MAX_PSP or FAST_PSP
2715 // 3. but current psm is not in PWR_SAVE
2716 // 4. CNTL state machine is not doing SCANning
2717 // 5. no TX SUCCESS event for the past 1-sec period
2718 #ifdef NDIS51_MINIPORT
2719 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2720 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2723 PowerMode = pAd->StaCfg.WindowsPowerMode;
2725 if (INFRA_ON(pAd) &&
2726 (PowerMode != Ndis802_11PowerModeCAM) &&
2727 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2728 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2730 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2731 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2732 MlmeSetPsmBit(pAd, PWR_SAVE);
2733 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2735 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2739 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2744 // IRQL = PASSIVE_LEVEL
2745 // IRQL = DISPATCH_LEVEL
2747 IN PRTMP_ADAPTER pAd,
2750 AUTO_RSP_CFG_STRUC csr4;
2752 pAd->StaCfg.Psm = psm;
2753 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2754 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2755 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2756 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2758 #endif // CONFIG_STA_SUPPORT //
2761 // IRQL = DISPATCH_LEVEL
2762 VOID MlmeSetTxPreamble(
2763 IN PRTMP_ADAPTER pAd,
2764 IN USHORT TxPreamble)
2766 AUTO_RSP_CFG_STRUC csr4;
2769 // Always use Long preamble before verifiation short preamble functionality works well.
2770 // Todo: remove the following line if short preamble functionality works
2772 //TxPreamble = Rt802_11PreambleLong;
2774 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2775 if (TxPreamble == Rt802_11PreambleLong)
2777 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2778 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2779 csr4.field.AutoResponderPreamble = 0;
2783 // NOTE: 1Mbps should always use long preamble
2784 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2785 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2786 csr4.field.AutoResponderPreamble = 1;
2789 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2793 ==========================================================================
2795 Update basic rate bitmap
2796 ==========================================================================
2799 VOID UpdateBasicRateBitmap(
2800 IN PRTMP_ADAPTER pAdapter)
2803 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2804 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2805 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2806 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2807 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2810 /* if A mode, always use fix BasicRateBitMap */
2811 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2812 if (pAdapter->CommonCfg.Channel > 14)
2813 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2816 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2818 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2822 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2828 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2830 if (bitmap & (1 << i))
2832 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2834 if (sup_p[j] == rate[i])
2839 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2841 if (ext_p[j] == rate[i])
2847 } /* End of UpdateBasicRateBitmap */
2849 // IRQL = PASSIVE_LEVEL
2850 // IRQL = DISPATCH_LEVEL
2851 // bLinkUp is to identify the inital link speed.
2852 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2853 VOID MlmeUpdateTxRates(
2854 IN PRTMP_ADAPTER pAd,
2859 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2860 UCHAR MinSupport = RATE_54;
2861 ULONG BasicRateBitmap = 0;
2862 UCHAR CurrBasicRate = RATE_1;
2863 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2864 PHTTRANSMIT_SETTING pHtPhy = NULL;
2865 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2866 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2867 BOOLEAN *auto_rate_cur_p;
2868 UCHAR HtMcs = MCS_AUTO;
2870 // find max desired rate
2871 UpdateBasicRateBitmap(pAd);
2874 auto_rate_cur_p = NULL;
2875 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2877 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2879 case 2: Rate = RATE_1; num++; break;
2880 case 4: Rate = RATE_2; num++; break;
2881 case 11: Rate = RATE_5_5; num++; break;
2882 case 22: Rate = RATE_11; num++; break;
2883 case 12: Rate = RATE_6; num++; break;
2884 case 18: Rate = RATE_9; num++; break;
2885 case 24: Rate = RATE_12; num++; break;
2886 case 36: Rate = RATE_18; num++; break;
2887 case 48: Rate = RATE_24; num++; break;
2888 case 72: Rate = RATE_36; num++; break;
2889 case 96: Rate = RATE_48; num++; break;
2890 case 108: Rate = RATE_54; num++; break;
2891 //default: Rate = RATE_1; break;
2893 if (MaxDesire < Rate) MaxDesire = Rate;
2896 //===========================================================================
2897 //===========================================================================
2899 #ifdef CONFIG_STA_SUPPORT
2900 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2902 pHtPhy = &pAd->StaCfg.HTPhyMode;
2903 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2904 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2906 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2907 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2909 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2910 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2911 (MaxDesire > RATE_11))
2913 MaxDesire = RATE_11;
2916 #endif // CONFIG_STA_SUPPORT //
2918 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2919 pMinHtPhy->word = 0;
2920 pMaxHtPhy->word = 0;
2923 // Auto rate switching is enabled only if more than one DESIRED RATES are
2924 // specified; otherwise disabled
2927 *auto_rate_cur_p = FALSE;
2931 *auto_rate_cur_p = TRUE;
2935 if (HtMcs != MCS_AUTO)
2937 *auto_rate_cur_p = FALSE;
2941 *auto_rate_cur_p = TRUE;
2945 #ifdef CONFIG_STA_SUPPORT
2946 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2948 pSupRate = &pAd->StaActive.SupRate[0];
2949 pExtRate = &pAd->StaActive.ExtRate[0];
2950 SupRateLen = pAd->StaActive.SupRateLen;
2951 ExtRateLen = pAd->StaActive.ExtRateLen;
2954 #endif // CONFIG_STA_SUPPORT //
2956 pSupRate = &pAd->CommonCfg.SupRate[0];
2957 pExtRate = &pAd->CommonCfg.ExtRate[0];
2958 SupRateLen = pAd->CommonCfg.SupRateLen;
2959 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2962 // find max supported rate
2963 for (i=0; i<SupRateLen; i++)
2965 switch (pSupRate[i] & 0x7f)
2967 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2968 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2969 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2970 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2971 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2972 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2973 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2974 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2975 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2976 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2977 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2978 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2979 default: Rate = RATE_1; break;
2981 if (MaxSupport < Rate) MaxSupport = Rate;
2983 if (MinSupport > Rate) MinSupport = Rate;
2986 for (i=0; i<ExtRateLen; i++)
2988 switch (pExtRate[i] & 0x7f)
2990 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2991 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2992 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2993 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2994 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2995 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2996 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2997 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2998 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2999 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3000 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3001 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3002 default: Rate = RATE_1; break;
3004 if (MaxSupport < Rate) MaxSupport = Rate;
3006 if (MinSupport > Rate) MinSupport = Rate;
3009 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3011 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3012 // the DURATION field of outgoing uniicast DATA/MGMT frame
3013 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3015 if (BasicRateBitmap & (0x01 << i))
3016 CurrBasicRate = (UCHAR)i;
3017 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3020 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3021 // max tx rate = min {max desire rate, max supported rate}
3022 if (MaxSupport < MaxDesire)
3023 pAd->CommonCfg.MaxTxRate = MaxSupport;
3025 pAd->CommonCfg.MaxTxRate = MaxDesire;
3027 pAd->CommonCfg.MinTxRate = MinSupport;
3028 if (*auto_rate_cur_p)
3031 #ifdef CONFIG_STA_SUPPORT
3032 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3033 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3034 #endif // CONFIG_STA_SUPPORT //
3035 if (bLinkUp == TRUE)
3036 pAd->CommonCfg.TxRate = RATE_24;
3038 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3041 pAd->CommonCfg.TxRate = RATE_11;
3043 pAd->CommonCfg.TxRate = RATE_24;
3045 // should never exceed MaxTxRate (consider 11B-only mode)
3046 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3047 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3049 pAd->CommonCfg.TxRateIndex = 0;
3053 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3054 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3055 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3057 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3058 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3059 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3060 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3063 if (pAd->CommonCfg.TxRate <= RATE_11)
3065 pMaxHtPhy->field.MODE = MODE_CCK;
3066 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3067 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3071 pMaxHtPhy->field.MODE = MODE_OFDM;
3072 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3073 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3074 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3076 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3079 pHtPhy->word = (pMaxHtPhy->word);
3080 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3082 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3083 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3084 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3088 switch (pAd->CommonCfg.PhyMode)
3090 case PHY_11BG_MIXED:
3092 #ifdef DOT11_N_SUPPORT
3093 case PHY_11BGN_MIXED:
3094 #endif // DOT11_N_SUPPORT //
3095 pAd->CommonCfg.MlmeRate = RATE_1;
3096 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3097 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3098 pAd->CommonCfg.RtsRate = RATE_11;
3102 #ifdef DOT11_N_SUPPORT
3103 case PHY_11AGN_MIXED:
3104 case PHY_11GN_MIXED:
3106 case PHY_11AN_MIXED:
3108 #endif // DOT11_N_SUPPORT //
3109 pAd->CommonCfg.MlmeRate = RATE_6;
3110 pAd->CommonCfg.RtsRate = RATE_6;
3111 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3112 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3114 case PHY_11ABG_MIXED:
3115 #ifdef DOT11_N_SUPPORT
3116 case PHY_11ABGN_MIXED:
3117 #endif // DOT11_N_SUPPORT //
3118 if (pAd->CommonCfg.Channel <= 14)
3120 pAd->CommonCfg.MlmeRate = RATE_1;
3121 pAd->CommonCfg.RtsRate = RATE_1;
3122 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3123 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3127 pAd->CommonCfg.MlmeRate = RATE_6;
3128 pAd->CommonCfg.RtsRate = RATE_6;
3129 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3130 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3134 pAd->CommonCfg.MlmeRate = RATE_6;
3135 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3136 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3137 pAd->CommonCfg.RtsRate = RATE_1;
3141 // Keep Basic Mlme Rate.
3143 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3144 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3145 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3147 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3148 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3151 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3152 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3153 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3154 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3155 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3156 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3157 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 ));
3160 #ifdef DOT11_N_SUPPORT
3162 ==========================================================================
3164 This function update HT Rate setting.
3165 Input Wcid value is valid for 2 case :
3166 1. it's used for Station in infra mode that copy AP rate to Mactable.
3167 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3169 IRQL = DISPATCH_LEVEL
3171 ==========================================================================
3173 VOID MlmeUpdateHtTxRates(
3174 IN PRTMP_ADAPTER pAd,
3177 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3179 RT_HT_CAPABILITY *pRtHtCap = NULL;
3180 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3183 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3184 PHTTRANSMIT_SETTING pHtPhy = NULL;
3185 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3186 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3187 BOOLEAN *auto_rate_cur_p;
3189 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3191 auto_rate_cur_p = NULL;
3193 #ifdef CONFIG_STA_SUPPORT
3194 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3196 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3197 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3198 pHtPhy = &pAd->StaCfg.HTPhyMode;
3199 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3200 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3202 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3204 #endif // CONFIG_STA_SUPPORT //
3206 #ifdef CONFIG_STA_SUPPORT
3207 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3209 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3212 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3213 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3214 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3215 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3216 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3217 pMaxHtPhy->field.STBC = STBC_USE;
3219 pMaxHtPhy->field.STBC = STBC_NONE;
3222 #endif // CONFIG_STA_SUPPORT //
3224 if (pDesireHtPhy->bHtEnable == FALSE)
3227 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3228 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3229 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3230 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3231 pMaxHtPhy->field.STBC = STBC_USE;
3233 pMaxHtPhy->field.STBC = STBC_NONE;
3236 // Decide MAX ht rate.
3237 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3238 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3240 pMaxHtPhy->field.MODE = MODE_HTMIX;
3242 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3243 pMaxHtPhy->field.BW = BW_40;
3245 pMaxHtPhy->field.BW = BW_20;
3247 if (pMaxHtPhy->field.BW == BW_20)
3248 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3250 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3252 for (i=23; i>=0; i--) // 3*3
3255 bitmask = (1<<(i-(j*8)));
3257 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3259 pMaxHtPhy->field.MCS = i;
3267 // Copy MIN ht rate. rt2860???
3268 pMinHtPhy->field.BW = BW_20;
3269 pMinHtPhy->field.MCS = 0;
3270 pMinHtPhy->field.STBC = 0;
3271 pMinHtPhy->field.ShortGI = 0;
3272 //If STA assigns fixed rate. update to fixed here.
3273 #ifdef CONFIG_STA_SUPPORT
3274 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3276 if (pDesireHtPhy->MCSSet[4] != 0)
3278 pMaxHtPhy->field.MCS = 32;
3279 pMinHtPhy->field.MCS = 32;
3280 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3283 for (i=23; (CHAR)i >= 0; i--) // 3*3
3286 bitmask = (1<<(i-(j*8)));
3287 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3289 pMaxHtPhy->field.MCS = i;
3290 pMinHtPhy->field.MCS = i;
3297 #endif // CONFIG_STA_SUPPORT //
3301 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3302 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3303 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3304 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3305 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3307 // use default now. rt2860
3308 if (pDesireHtPhy->MCSSet[0] != 0xff)
3309 *auto_rate_cur_p = FALSE;
3311 *auto_rate_cur_p = TRUE;
3313 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3314 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3315 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3316 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3318 #endif // DOT11_N_SUPPORT //
3320 // IRQL = DISPATCH_LEVEL
3322 IN PRTMP_ADAPTER pAd)
3324 RT28XX_MLME_RADIO_OFF(pAd);
3327 // IRQL = DISPATCH_LEVEL
3329 IN PRTMP_ADAPTER pAd)
3331 RT28XX_MLME_RADIO_ON(pAd);
3334 // ===========================================================================================
3336 // ===========================================================================================
3339 /*! \brief initialize BSS table
3340 * \param p_tab pointer to the table
3345 IRQL = PASSIVE_LEVEL
3346 IRQL = DISPATCH_LEVEL
3355 Tab->BssOverlapNr = 0;
3356 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3358 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3359 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3363 #ifdef DOT11_N_SUPPORT
3365 IN PRTMP_ADAPTER pAd,
3370 Tab->numAsOriginator = 0;
3371 Tab->numAsRecipient = 0;
3372 NdisAllocateSpinLock(&pAd->BATabLock);
3373 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3375 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3376 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3378 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3380 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3383 #endif // DOT11_N_SUPPORT //
3385 /*! \brief search the BSS table by SSID
3386 * \param p_tab pointer to the bss table
3387 * \param ssid SSID string
3388 * \return index of the table, BSS_NOT_FOUND if not in the table
3391 * \note search by sequential search
3393 IRQL = DISPATCH_LEVEL
3396 ULONG BssTableSearch(
3403 for (i = 0; i < Tab->BssNr; i++)
3406 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3407 // We should distinguish this case.
3409 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3410 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3411 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3416 return (ULONG)BSS_NOT_FOUND;
3419 ULONG BssSsidTableSearch(
3428 for (i = 0; i < Tab->BssNr; i++)
3431 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3432 // We should distinguish this case.
3434 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3435 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3436 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3437 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3442 return (ULONG)BSS_NOT_FOUND;
3445 ULONG BssTableSearchWithSSID(
3454 for (i = 0; i < Tab->BssNr; i++)
3456 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3457 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3458 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3459 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3460 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3461 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3466 return (ULONG)BSS_NOT_FOUND;
3469 // IRQL = DISPATCH_LEVEL
3470 VOID BssTableDeleteEntry(
3471 IN OUT BSS_TABLE *Tab,
3477 for (i = 0; i < Tab->BssNr; i++)
3479 if ((Tab->BssEntry[i].Channel == Channel) &&
3480 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3482 for (j = i; j < Tab->BssNr - 1; j++)
3484 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3486 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3493 #ifdef DOT11_N_SUPPORT
3495 ========================================================================
3496 Routine Description:
3497 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3500 // IRQL = DISPATCH_LEVEL
3501 ========================================================================
3503 VOID BATableDeleteORIEntry(
3504 IN OUT PRTMP_ADAPTER pAd,
3505 IN BA_ORI_ENTRY *pBAORIEntry)
3508 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3510 NdisAcquireSpinLock(&pAd->BATabLock);
3511 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3513 pAd->BATable.numAsOriginator -= 1;
3514 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3515 // Erase Bitmap flag.
3517 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3518 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3519 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3520 pBAORIEntry->Token = 1;
3521 // Not clear Sequence here.
3522 NdisReleaseSpinLock(&pAd->BATabLock);
3525 #endif // DOT11_N_SUPPORT //
3533 IRQL = DISPATCH_LEVEL
3537 IN PRTMP_ADAPTER pAd,
3538 OUT BSS_ENTRY *pBss,
3543 IN USHORT BeaconPeriod,
3544 IN PCF_PARM pCfParm,
3546 IN USHORT CapabilityInfo,
3548 IN UCHAR SupRateLen,
3550 IN UCHAR ExtRateLen,
3551 IN HT_CAPABILITY_IE *pHtCapability,
3552 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3553 IN UCHAR HtCapabilityLen,
3554 IN UCHAR AddHtInfoLen,
3555 IN UCHAR NewExtChanOffset,
3558 IN LARGE_INTEGER TimeStamp,
3560 IN PEDCA_PARM pEdcaParm,
3561 IN PQOS_CAPABILITY_PARM pQosCapability,
3562 IN PQBSS_LOAD_PARM pQbssLoad,
3563 IN USHORT LengthVIE,
3564 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3566 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3567 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3571 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3572 // Or send beacon /probe response with SSID len matching real SSID length,
3573 // but SSID is all zero. such as "00-00-00-00" with length 4.
3574 // We have to prevent this case overwrite correct table
3575 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3577 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3578 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3579 pBss->SsidLen = SsidLen;
3585 pBss->BssType = BssType;
3586 pBss->BeaconPeriod = BeaconPeriod;
3587 if (BssType == BSS_INFRA)
3589 if (pCfParm->bValid)
3591 pBss->CfpCount = pCfParm->CfpCount;
3592 pBss->CfpPeriod = pCfParm->CfpPeriod;
3593 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3594 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3599 pBss->AtimWin = AtimWin;
3602 pBss->CapabilityInfo = CapabilityInfo;
3603 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3604 // Combine with AuthMode, they will decide the connection methods.
3605 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3606 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3607 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3608 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3610 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3611 pBss->SupRateLen = SupRateLen;
3612 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3613 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3614 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3615 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3616 pBss->NewExtChanOffset = NewExtChanOffset;
3617 pBss->ExtRateLen = ExtRateLen;
3618 pBss->Channel = Channel;
3619 pBss->CentralChannel = Channel;
3621 // Update CkipFlag. if not exists, the value is 0x0
3622 pBss->CkipFlag = CkipFlag;
3624 // New for microsoft Fixed IEs
3625 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3626 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3627 pBss->FixIEs.Capabilities = CapabilityInfo;
3629 // New for microsoft Variable IEs
3632 pBss->VarIELen = LengthVIE;
3633 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3640 pBss->AddHtInfoLen = 0;
3641 pBss->HtCapabilityLen = 0;
3642 #ifdef DOT11_N_SUPPORT
3643 if (HtCapabilityLen> 0)
3645 pBss->HtCapabilityLen = HtCapabilityLen;
3646 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3647 if (AddHtInfoLen > 0)
3649 pBss->AddHtInfoLen = AddHtInfoLen;
3650 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3652 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3654 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3656 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3658 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3662 #endif // DOT11_N_SUPPORT //
3664 BssCipherParse(pBss);
3668 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3670 pBss->EdcaParm.bValid = FALSE;
3672 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3674 pBss->QosCapability.bValid = FALSE;
3676 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3678 pBss->QbssLoad.bValid = FALSE;
3680 #ifdef CONFIG_STA_SUPPORT
3681 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3687 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3688 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3690 pEid = (PEID_STRUCT) pVIE;
3692 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3697 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3699 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3701 pBss->WpaIE.IELen = 0;
3704 pBss->WpaIE.IELen = pEid->Len + 2;
3705 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3709 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3711 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3713 pBss->RsnIE.IELen = 0;
3716 pBss->RsnIE.IELen = pEid->Len + 2;
3717 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3721 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3722 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3725 #endif // CONFIG_STA_SUPPORT //
3729 * \brief insert an entry into the bss table
3730 * \param p_tab The BSS table
3731 * \param Bssid BSSID
3733 * \param ssid_len Length of SSID
3735 * \param beacon_period
3742 * \param channel_idx
3746 * \note If SSID is identical, the old entry will be replaced by the new one
3748 IRQL = DISPATCH_LEVEL
3751 ULONG BssTableSetEntry(
3752 IN PRTMP_ADAPTER pAd,
3758 IN USHORT BeaconPeriod,
3761 IN USHORT CapabilityInfo,
3763 IN UCHAR SupRateLen,
3765 IN UCHAR ExtRateLen,
3766 IN HT_CAPABILITY_IE *pHtCapability,
3767 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3768 IN UCHAR HtCapabilityLen,
3769 IN UCHAR AddHtInfoLen,
3770 IN UCHAR NewExtChanOffset,
3773 IN LARGE_INTEGER TimeStamp,
3775 IN PEDCA_PARM pEdcaParm,
3776 IN PQOS_CAPABILITY_PARM pQosCapability,
3777 IN PQBSS_LOAD_PARM pQbssLoad,
3778 IN USHORT LengthVIE,
3779 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3783 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3784 if (Idx == BSS_NOT_FOUND)
3786 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3789 // It may happen when BSS Table was full.
3790 // The desired AP will not be added into BSS Table
3791 // In this case, if we found the desired AP then overwrite BSS Table.
3793 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3795 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3796 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3798 Idx = Tab->BssOverlapNr;
3799 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3800 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3801 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3802 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3808 return BSS_NOT_FOUND;
3812 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3813 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3814 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3819 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3820 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3821 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3827 #ifdef CONFIG_STA_SUPPORT
3828 // IRQL = DISPATCH_LEVEL
3829 VOID BssTableSsidSort(
3830 IN PRTMP_ADAPTER pAd,
3831 OUT BSS_TABLE *OutTab,
3836 BssTableInit(OutTab);
3838 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3840 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3841 BOOLEAN bIsHiddenApIncluded = FALSE;
3843 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3844 (pAd->MlmeAux.Channel > 14) &&
3845 RadarChannelCheck(pAd, pInBss->Channel))
3849 bIsHiddenApIncluded = TRUE;
3852 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3853 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3855 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3856 #ifdef DOT11_N_SUPPORT
3857 // 2.4G/5G N only mode
3858 if ((pInBss->HtCapabilityLen == 0) &&
3859 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3861 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3864 #endif // DOT11_N_SUPPORT //
3867 // Check the Authmode first
3868 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3870 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3871 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3875 // Check cipher suite, AP must have more secured cipher than station setting
3876 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3878 // If it's not mixed mode, we should only let BSS pass with the same encryption
3879 if (pInBss->WPA.bMixMode == FALSE)
3880 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3883 // check group cipher
3884 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3885 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3886 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3889 // check pairwise cipher, skip if none matched
3890 // If profile set to AES, let it pass without question.
3891 // If profile set to TKIP, we must find one mateched
3892 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3893 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3894 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3897 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3899 // If it's not mixed mode, we should only let BSS pass with the same encryption
3900 if (pInBss->WPA2.bMixMode == FALSE)
3901 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3904 // check group cipher
3905 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3906 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3907 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3910 // check pairwise cipher, skip if none matched
3911 // If profile set to AES, let it pass without question.
3912 // If profile set to TKIP, we must find one mateched
3913 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3914 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3915 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3919 // Bss Type matched, SSID matched.
3920 // We will check wepstatus for qualification Bss
3921 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3923 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3925 // For the SESv2 case, we will not qualify WepStatus.
3931 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3932 // It definitely will fail. So, skip it.
3933 // CCX also require not even try to connect it!!
3937 #ifdef DOT11_N_SUPPORT
3938 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3939 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3940 if ((pInBss->CentralChannel != pInBss->Channel) &&
3941 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3943 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3945 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3947 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3951 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3957 #endif // DOT11_N_SUPPORT //
3959 // copy matching BSS from InTab to OutTab
3960 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3964 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3966 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3969 #ifdef DOT11_N_SUPPORT
3970 // 2.4G/5G N only mode
3971 if ((pInBss->HtCapabilityLen == 0) &&
3972 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3974 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3977 #endif // DOT11_N_SUPPORT //
3980 // Check the Authmode first
3981 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3983 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3984 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3988 // Check cipher suite, AP must have more secured cipher than station setting
3989 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3991 // If it's not mixed mode, we should only let BSS pass with the same encryption
3992 if (pInBss->WPA.bMixMode == FALSE)
3993 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3996 // check group cipher
3997 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4000 // check pairwise cipher, skip if none matched
4001 // If profile set to AES, let it pass without question.
4002 // If profile set to TKIP, we must find one mateched
4003 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4004 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4005 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4008 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4010 // If it's not mixed mode, we should only let BSS pass with the same encryption
4011 if (pInBss->WPA2.bMixMode == FALSE)
4012 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4015 // check group cipher
4016 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4019 // check pairwise cipher, skip if none matched
4020 // If profile set to AES, let it pass without question.
4021 // If profile set to TKIP, we must find one mateched
4022 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4023 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4024 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4028 // Bss Type matched, SSID matched.
4029 // We will check wepstatus for qualification Bss
4030 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4033 #ifdef DOT11_N_SUPPORT
4034 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4035 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4036 if ((pInBss->CentralChannel != pInBss->Channel) &&
4037 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4039 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4041 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4043 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4046 #endif // DOT11_N_SUPPORT //
4048 // copy matching BSS from InTab to OutTab
4049 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4054 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4058 BssTableSortByRssi(OutTab);
4062 // IRQL = DISPATCH_LEVEL
4063 VOID BssTableSortByRssi(
4064 IN OUT BSS_TABLE *OutTab)
4069 for (i = 0; i < OutTab->BssNr - 1; i++)
4071 for (j = i+1; j < OutTab->BssNr; j++)
4073 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4075 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4076 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4077 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4082 #endif // CONFIG_STA_SUPPORT //
4085 VOID BssCipherParse(
4086 IN OUT PBSS_ENTRY pBss)
4090 PRSN_IE_HEADER_STRUCT pRsnHeader;
4091 PCIPHER_SUITE_STRUCT pCipher;
4092 PAKM_SUITE_STRUCT pAKM;
4095 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4098 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4102 pBss->WepStatus = Ndis802_11WEPEnabled;
4106 pBss->WepStatus = Ndis802_11WEPDisabled;
4108 // Set default to disable & open authentication before parsing variable IE
4109 pBss->AuthMode = Ndis802_11AuthModeOpen;
4110 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4113 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4114 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4115 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4116 pBss->WPA.RsnCapability = 0;
4117 pBss->WPA.bMixMode = FALSE;
4119 // Init WPA2 setting
4120 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4121 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4122 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4123 pBss->WPA2.RsnCapability = 0;
4124 pBss->WPA2.bMixMode = FALSE;
4127 Length = (INT) pBss->VarIELen;
4131 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4132 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4133 pEid = (PEID_STRUCT) pTmp;
4137 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4138 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4144 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4145 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4146 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4147 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4150 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4151 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4152 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4155 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4156 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4157 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4163 // if Cisco IE_WPA, break
4166 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4171 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4173 // if unsupported vendor specific IE
4176 // Skip OUI, version, and multicast suite
4177 // This part should be improved in the future when AP supported multiple cipher suite.
4178 // For now, it's OK since almost all APs have fixed cipher suite supported.
4179 // pTmp = (PUCHAR) pEid->Octet;
4182 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4190 // Parse group cipher
4194 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4197 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4200 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4203 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4208 // number of unicast suite
4211 // skip all unicast cipher suites
4212 //Count = *(PUSHORT) pTmp;
4213 Count = (pTmp[1]<<8) + pTmp[0];
4214 pTmp += sizeof(USHORT);
4216 // Parsing all unicast cipher suite
4221 TmpCipher = Ndis802_11WEPDisabled;
4225 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4226 TmpCipher = Ndis802_11Encryption1Enabled;
4229 TmpCipher = Ndis802_11Encryption2Enabled;
4232 TmpCipher = Ndis802_11Encryption3Enabled;
4237 if (TmpCipher > pBss->WPA.PairCipher)
4239 // Move the lower cipher suite to PairCipherAux
4240 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4241 pBss->WPA.PairCipher = TmpCipher;
4245 pBss->WPA.PairCipherAux = TmpCipher;
4251 // 4. get AKM suite counts
4252 //Count = *(PUSHORT) pTmp;
4253 Count = (pTmp[1]<<8) + pTmp[0];
4254 pTmp += sizeof(USHORT);
4260 // Set AP support WPA mode
4261 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4262 pBss->AuthMode = Ndis802_11AuthModeWPA;
4264 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4267 // Set AP support WPA mode
4268 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4269 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4271 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4278 // Fixed for WPA-None
4279 if (pBss->BssType == BSS_ADHOC)
4281 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4282 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4283 pBss->WepStatus = pBss->WPA.GroupCipher;
4284 // Patched bugs for old driver
4285 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4286 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4289 pBss->WepStatus = pBss->WPA.PairCipher;
4291 // Check the Pair & Group, if different, turn on mixed mode flag
4292 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4293 pBss->WPA.bMixMode = TRUE;
4298 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4300 // 0. Version must be 1
4301 if (le2cpu16(pRsnHeader->Version) != 1)
4303 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4305 // 1. Check group cipher
4306 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4307 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4310 // Parse group cipher
4311 switch (pCipher->Type)
4314 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4317 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4320 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4323 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4328 // set to correct offset for next parsing
4329 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4331 // 2. Get pairwise cipher counts
4332 //Count = *(PUSHORT) pTmp;
4333 Count = (pTmp[1]<<8) + pTmp[0];
4334 pTmp += sizeof(USHORT);
4336 // 3. Get pairwise cipher
4337 // Parsing all unicast cipher suite
4341 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4342 TmpCipher = Ndis802_11WEPDisabled;
4343 switch (pCipher->Type)
4346 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4347 TmpCipher = Ndis802_11Encryption1Enabled;
4350 TmpCipher = Ndis802_11Encryption2Enabled;
4353 TmpCipher = Ndis802_11Encryption3Enabled;
4358 if (TmpCipher > pBss->WPA2.PairCipher)
4360 // Move the lower cipher suite to PairCipherAux
4361 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4362 pBss->WPA2.PairCipher = TmpCipher;
4366 pBss->WPA2.PairCipherAux = TmpCipher;
4368 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4372 // 4. get AKM suite counts
4373 //Count = *(PUSHORT) pTmp;
4374 Count = (pTmp[1]<<8) + pTmp[0];
4375 pTmp += sizeof(USHORT);
4377 // 5. Get AKM ciphers
4378 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4379 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4385 // Set AP support WPA mode
4386 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4387 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4389 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4392 // Set AP support WPA mode
4393 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4394 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4396 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4401 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4403 // Fixed for WPA-None
4404 if (pBss->BssType == BSS_ADHOC)
4406 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4407 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4408 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4409 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4410 pBss->WepStatus = pBss->WPA.GroupCipher;
4411 // Patched bugs for old driver
4412 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4413 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4415 pBss->WepStatus = pBss->WPA2.PairCipher;
4417 // 6. Get RSN capability
4418 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4419 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4420 pTmp += sizeof(USHORT);
4422 // Check the Pair & Group, if different, turn on mixed mode flag
4423 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4424 pBss->WPA2.bMixMode = TRUE;
4430 Length -= (pEid->Len + 2);
4434 // ===========================================================================================
4436 // ===========================================================================================
4438 /*! \brief generates a random mac address value for IBSS BSSID
4439 * \param Addr the bssid location
4444 VOID MacAddrRandomBssid(
4445 IN PRTMP_ADAPTER pAd,
4450 for (i = 0; i < MAC_ADDR_LEN; i++)
4452 pAddr[i] = RandomByte(pAd);
4455 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4458 /*! \brief init the management mac frame header
4459 * \param p_hdr mac header
4460 * \param subtype subtype of the frame
4461 * \param p_ds destination address, don't care if it is a broadcast address
4463 * \pre the station has the following information in the pAd->StaCfg
4467 * \note this function initializes the following field
4469 IRQL = PASSIVE_LEVEL
4470 IRQL = DISPATCH_LEVEL
4473 VOID MgtMacHeaderInit(
4474 IN PRTMP_ADAPTER pAd,
4475 IN OUT PHEADER_802_11 pHdr80211,
4481 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4483 pHdr80211->FC.Type = BTYPE_MGMT;
4484 pHdr80211->FC.SubType = SubType;
4485 pHdr80211->FC.ToDs = ToDs;
4486 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4487 #ifdef CONFIG_STA_SUPPORT
4488 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4489 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4490 #endif // CONFIG_STA_SUPPORT //
4491 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4494 // ===========================================================================================
4496 // ===========================================================================================
4498 /*!***************************************************************************
4499 * This routine build an outgoing frame, and fill all information specified
4500 * in argument list to the frame body. The actual frame size is the summation
4503 * Buffer - pointer to a pre-allocated memory segment
4504 * args - a list of <int arg_size, arg> pairs.
4505 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4506 * function will FAIL!!!
4508 * Size of the buffer
4510 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4512 IRQL = PASSIVE_LEVEL
4513 IRQL = DISPATCH_LEVEL
4515 ****************************************************************************/
4516 ULONG MakeOutgoingFrame(
4518 OUT ULONG *FrameLen, ...)
4525 // calculates the total length
4527 va_start(Args, FrameLen);
4530 leng = va_arg(Args, int);
4531 if (leng == END_OF_ARGS)
4535 p = va_arg(Args, PVOID);
4536 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4537 TotLeng = TotLeng + leng;
4540 va_end(Args); /* clean up */
4541 *FrameLen = TotLeng;
4545 // ===========================================================================================
4547 // ===========================================================================================
4549 /*! \brief Initialize The MLME Queue, used by MLME Functions
4550 * \param *Queue The MLME Queue
4551 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4554 * \note Because this is done only once (at the init stage), no need to be locked
4556 IRQL = PASSIVE_LEVEL
4559 NDIS_STATUS MlmeQueueInit(
4560 IN MLME_QUEUE *Queue)
4564 NdisAllocateSpinLock(&Queue->Lock);
4570 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4572 Queue->Entry[i].Occupied = FALSE;
4573 Queue->Entry[i].MsgLen = 0;
4574 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4577 return NDIS_STATUS_SUCCESS;
4580 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4581 * \param *Queue The MLME Queue
4582 * \param Machine The State Machine Id
4583 * \param MsgType The Message Type
4584 * \param MsgLen The Message length
4585 * \param *Msg The message pointer
4586 * \return TRUE if enqueue is successful, FALSE if the queue is full
4589 * \note The message has to be initialized
4591 IRQL = PASSIVE_LEVEL
4592 IRQL = DISPATCH_LEVEL
4595 BOOLEAN MlmeEnqueue(
4596 IN PRTMP_ADAPTER pAd,
4603 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4605 // Do nothing if the driver is starting halt state.
4606 // This might happen when timer already been fired before cancel timer with mlmehalt
4607 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4610 // First check the size, it MUST not exceed the mlme queue size
4611 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4613 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4617 if (MlmeQueueFull(Queue))
4622 NdisAcquireSpinLock(&(Queue->Lock));
4626 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4631 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4632 Queue->Entry[Tail].Occupied = TRUE;
4633 Queue->Entry[Tail].Machine = Machine;
4634 Queue->Entry[Tail].MsgType = MsgType;
4635 Queue->Entry[Tail].MsgLen = MsgLen;
4639 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4642 NdisReleaseSpinLock(&(Queue->Lock));
4646 /*! \brief This function is used when Recv gets a MLME message
4647 * \param *Queue The MLME Queue
4648 * \param TimeStampHigh The upper 32 bit of timestamp
4649 * \param TimeStampLow The lower 32 bit of timestamp
4650 * \param Rssi The receiving RSSI strength
4651 * \param MsgLen The length of the message
4652 * \param *Msg The message pointer
4653 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4657 IRQL = DISPATCH_LEVEL
4660 BOOLEAN MlmeEnqueueForRecv(
4661 IN PRTMP_ADAPTER pAd,
4663 IN ULONG TimeStampHigh,
4664 IN ULONG TimeStampLow,
4673 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4675 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4677 // Do nothing if the driver is starting halt state.
4678 // This might happen when timer already been fired before cancel timer with mlmehalt
4679 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4681 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4685 // First check the size, it MUST not exceed the mlme queue size
4686 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4688 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4692 if (MlmeQueueFull(Queue))
4697 #ifdef CONFIG_STA_SUPPORT
4698 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4700 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4702 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4706 #endif // CONFIG_STA_SUPPORT //
4708 // OK, we got all the informations, it is time to put things into queue
4709 NdisAcquireSpinLock(&(Queue->Lock));
4713 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4717 Queue->Entry[Tail].Occupied = TRUE;
4718 Queue->Entry[Tail].Machine = Machine;
4719 Queue->Entry[Tail].MsgType = MsgType;
4720 Queue->Entry[Tail].MsgLen = MsgLen;
4721 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4722 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4723 Queue->Entry[Tail].Rssi0 = Rssi0;
4724 Queue->Entry[Tail].Rssi1 = Rssi1;
4725 Queue->Entry[Tail].Rssi2 = Rssi2;
4726 Queue->Entry[Tail].Signal = Signal;
4727 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4729 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4733 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4736 NdisReleaseSpinLock(&(Queue->Lock));
4738 RT28XX_MLME_HANDLER(pAd);
4744 /*! \brief Dequeue a message from the MLME Queue
4745 * \param *Queue The MLME Queue
4746 * \param *Elem The message dequeued from MLME Queue
4747 * \return TRUE if the Elem contains something, FALSE otherwise
4751 IRQL = DISPATCH_LEVEL
4754 BOOLEAN MlmeDequeue(
4755 IN MLME_QUEUE *Queue,
4756 OUT MLME_QUEUE_ELEM **Elem)
4758 NdisAcquireSpinLock(&(Queue->Lock));
4759 *Elem = &(Queue->Entry[Queue->Head]);
4762 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4766 NdisReleaseSpinLock(&(Queue->Lock));
4770 // IRQL = DISPATCH_LEVEL
4771 VOID MlmeRestartStateMachine(
4772 IN PRTMP_ADAPTER pAd)
4774 MLME_QUEUE_ELEM *Elem = NULL;
4775 #ifdef CONFIG_STA_SUPPORT
4777 #endif // CONFIG_STA_SUPPORT //
4779 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4781 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4782 if(pAd->Mlme.bRunning)
4784 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4789 pAd->Mlme.bRunning = TRUE;
4791 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4793 // Remove all Mlme queues elements
4794 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4796 //From message type, determine which state machine I should drive
4797 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4799 // free MLME element
4800 Elem->Occupied = FALSE;
4805 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4809 #ifdef CONFIG_STA_SUPPORT
4810 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4812 // Cancel all timer events
4813 // Be careful to cancel new added timer
4814 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4815 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4816 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4817 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4818 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4819 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4821 #endif // CONFIG_STA_SUPPORT //
4823 // Change back to original channel in case of doing scan
4824 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4825 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4827 // Resume MSDU which is turned off durning scan
4828 RTMPResumeMsduTransmission(pAd);
4830 #ifdef CONFIG_STA_SUPPORT
4831 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4833 // Set all state machines back IDLE
4834 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4835 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4836 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4837 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4838 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4839 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4841 #endif // CONFIG_STA_SUPPORT //
4843 // Remove running state
4844 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4845 pAd->Mlme.bRunning = FALSE;
4846 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4849 /*! \brief test if the MLME Queue is empty
4850 * \param *Queue The MLME Queue
4851 * \return TRUE if the Queue is empty, FALSE otherwise
4855 IRQL = DISPATCH_LEVEL
4858 BOOLEAN MlmeQueueEmpty(
4859 IN MLME_QUEUE *Queue)
4863 NdisAcquireSpinLock(&(Queue->Lock));
4864 Ans = (Queue->Num == 0);
4865 NdisReleaseSpinLock(&(Queue->Lock));
4870 /*! \brief test if the MLME Queue is full
4871 * \param *Queue The MLME Queue
4872 * \return TRUE if the Queue is empty, FALSE otherwise
4876 IRQL = PASSIVE_LEVEL
4877 IRQL = DISPATCH_LEVEL
4880 BOOLEAN MlmeQueueFull(
4881 IN MLME_QUEUE *Queue)
4885 NdisAcquireSpinLock(&(Queue->Lock));
4886 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4887 NdisReleaseSpinLock(&(Queue->Lock));
4892 /*! \brief The destructor of MLME Queue
4897 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4899 IRQL = PASSIVE_LEVEL
4902 VOID MlmeQueueDestroy(
4903 IN MLME_QUEUE *pQueue)
4905 NdisAcquireSpinLock(&(pQueue->Lock));
4909 NdisReleaseSpinLock(&(pQueue->Lock));
4910 NdisFreeSpinLock(&(pQueue->Lock));
4913 /*! \brief To substitute the message type if the message is coming from external
4914 * \param pFrame The frame received
4915 * \param *Machine The state machine
4916 * \param *MsgType the message type for the state machine
4917 * \return TRUE if the substitution is successful, FALSE otherwise
4921 IRQL = DISPATCH_LEVEL
4924 #ifdef CONFIG_STA_SUPPORT
4925 BOOLEAN MsgTypeSubst(
4926 IN PRTMP_ADAPTER pAd,
4927 IN PFRAME_802_11 pFrame,
4935 // Pointer to start of data frames including SNAP header
4936 pData = (PUCHAR) pFrame + LENGTH_802_11;
4938 // The only data type will pass to this function is EAPOL frame
4939 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4941 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4943 // Cisco Aironet SNAP header
4944 *Machine = AIRONET_STATE_MACHINE;
4945 *MsgType = MT2_AIRONET_MSG;
4949 *Machine = WPA_PSK_STATE_MACHINE;
4950 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4951 return(WpaMsgTypeSubst(EAPType, MsgType));
4955 switch (pFrame->Hdr.FC.SubType)
4957 case SUBTYPE_ASSOC_REQ:
4958 *Machine = ASSOC_STATE_MACHINE;
4959 *MsgType = MT2_PEER_ASSOC_REQ;
4961 case SUBTYPE_ASSOC_RSP:
4962 *Machine = ASSOC_STATE_MACHINE;
4963 *MsgType = MT2_PEER_ASSOC_RSP;
4965 case SUBTYPE_REASSOC_REQ:
4966 *Machine = ASSOC_STATE_MACHINE;
4967 *MsgType = MT2_PEER_REASSOC_REQ;
4969 case SUBTYPE_REASSOC_RSP:
4970 *Machine = ASSOC_STATE_MACHINE;
4971 *MsgType = MT2_PEER_REASSOC_RSP;
4973 case SUBTYPE_PROBE_REQ:
4974 *Machine = SYNC_STATE_MACHINE;
4975 *MsgType = MT2_PEER_PROBE_REQ;
4977 case SUBTYPE_PROBE_RSP:
4978 *Machine = SYNC_STATE_MACHINE;
4979 *MsgType = MT2_PEER_PROBE_RSP;
4981 case SUBTYPE_BEACON:
4982 *Machine = SYNC_STATE_MACHINE;
4983 *MsgType = MT2_PEER_BEACON;
4986 *Machine = SYNC_STATE_MACHINE;
4987 *MsgType = MT2_PEER_ATIM;
4989 case SUBTYPE_DISASSOC:
4990 *Machine = ASSOC_STATE_MACHINE;
4991 *MsgType = MT2_PEER_DISASSOC_REQ;
4994 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4995 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4996 if (Seq == 1 || Seq == 3)
4998 *Machine = AUTH_RSP_STATE_MACHINE;
4999 *MsgType = MT2_PEER_AUTH_ODD;
5001 else if (Seq == 2 || Seq == 4)
5003 *Machine = AUTH_STATE_MACHINE;
5004 *MsgType = MT2_PEER_AUTH_EVEN;
5011 case SUBTYPE_DEAUTH:
5012 *Machine = AUTH_RSP_STATE_MACHINE;
5013 *MsgType = MT2_PEER_DEAUTH;
5015 case SUBTYPE_ACTION:
5016 *Machine = ACTION_STATE_MACHINE;
5017 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5018 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5020 *MsgType = MT2_ACT_INVALID;
5024 *MsgType = (pFrame->Octet[0]&0x7F);
5034 #endif // CONFIG_STA_SUPPORT //
5036 // ===========================================================================================
5038 // ===========================================================================================
5040 /*! \brief Initialize the state machine.
5041 * \param *S pointer to the state machine
5042 * \param Trans State machine transition function
5043 * \param StNr number of states
5044 * \param MsgNr number of messages
5045 * \param DefFunc default function, when there is invalid state/message combination
5046 * \param InitState initial state of the state machine
5047 * \param Base StateMachine base, internal use only
5048 * \pre p_sm should be a legal pointer
5051 IRQL = PASSIVE_LEVEL
5054 VOID StateMachineInit(
5055 IN STATE_MACHINE *S,
5056 IN STATE_MACHINE_FUNC Trans[],
5059 IN STATE_MACHINE_FUNC DefFunc,
5065 // set number of states and messages
5070 S->TransFunc = Trans;
5072 // init all state transition to default function
5073 for (i = 0; i < StNr; i++)
5075 for (j = 0; j < MsgNr; j++)
5077 S->TransFunc[i * MsgNr + j] = DefFunc;
5081 // set the starting state
5082 S->CurrState = InitState;
5085 /*! \brief This function fills in the function pointer into the cell in the state machine
5086 * \param *S pointer to the state machine
5088 * \param Msg incoming message
5089 * \param f the function to be executed when (state, message) combination occurs at the state machine
5090 * \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
5093 IRQL = PASSIVE_LEVEL
5096 VOID StateMachineSetAction(
5097 IN STATE_MACHINE *S,
5100 IN STATE_MACHINE_FUNC Func)
5104 MsgIdx = Msg - S->Base;
5106 if (St < S->NrState && MsgIdx < S->NrMsg)
5108 // boundary checking before setting the action
5109 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5113 /*! \brief This function does the state transition
5114 * \param *Adapter the NIC adapter pointer
5115 * \param *S the state machine
5116 * \param *Elem the message to be executed
5119 IRQL = DISPATCH_LEVEL
5122 VOID StateMachinePerformAction(
5123 IN PRTMP_ADAPTER pAd,
5124 IN STATE_MACHINE *S,
5125 IN MLME_QUEUE_ELEM *Elem)
5127 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5131 ==========================================================================
5133 The drop function, when machine executes this, the message is simply
5134 ignored. This function does nothing, the message is freed in
5135 StateMachinePerformAction()
5136 ==========================================================================
5139 IN PRTMP_ADAPTER pAd,
5140 IN MLME_QUEUE_ELEM *Elem)
5144 // ===========================================================================================
5146 // ===========================================================================================
5149 ==========================================================================
5152 IRQL = PASSIVE_LEVEL
5154 ==========================================================================
5157 IN PRTMP_ADAPTER pAd,
5161 pAd->Mlme.ShiftReg = 1;
5163 pAd->Mlme.ShiftReg = Seed;
5167 ==========================================================================
5169 ==========================================================================
5172 IN PRTMP_ADAPTER pAd)
5179 if (pAd->Mlme.ShiftReg == 0)
5180 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5182 for (i = 0; i < 8; i++)
5184 if (pAd->Mlme.ShiftReg & 0x00000001)
5186 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5191 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5194 R = (R << 1) | Result;
5200 VOID AsicUpdateAutoFallBackTable(
5201 IN PRTMP_ADAPTER pAd,
5202 IN PUCHAR pRateTable)
5205 HT_FBK_CFG0_STRUC HtCfg0;
5206 HT_FBK_CFG1_STRUC HtCfg1;
5207 LG_FBK_CFG0_STRUC LgCfg0;
5208 LG_FBK_CFG1_STRUC LgCfg1;
5209 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5211 // set to initial value
5212 HtCfg0.word = 0x65432100;
5213 HtCfg1.word = 0xedcba988;
5214 LgCfg0.word = 0xedcba988;
5215 LgCfg1.word = 0x00002100;
5217 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5218 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5220 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5221 switch (pCurrTxRate->Mode)
5227 switch(pCurrTxRate->CurrMCS)
5230 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5233 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5236 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5239 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5242 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5245 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5248 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5251 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5256 #ifdef DOT11_N_SUPPORT
5260 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5262 switch(pCurrTxRate->CurrMCS)
5265 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5268 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5271 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5274 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5277 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5280 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5283 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5286 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5289 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5292 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5295 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5298 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5301 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5304 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5307 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5310 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5313 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5318 #endif // DOT11_N_SUPPORT //
5321 pNextTxRate = pCurrTxRate;
5324 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5325 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5326 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5327 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5331 ========================================================================
5333 Routine Description:
5334 Set MAC register value according operation mode.
5335 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5336 If MM or GF mask is not set, those passing argument doesn't not take effect.
5338 Operation mode meaning:
5339 = 0 : Pure HT, no preotection.
5340 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5341 = 0x10: No Transmission in 40M is protected.
5342 = 0x11: Transmission in both 40M and 20M shall be protected
5344 we should choose not to use GF. But still set correct ASIC registers.
5345 ========================================================================
5347 VOID AsicUpdateProtect(
5348 IN PRTMP_ADAPTER pAd,
5349 IN USHORT OperationMode,
5351 IN BOOLEAN bDisableBGProtect,
5352 IN BOOLEAN bNonGFExist)
5354 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5360 #ifdef DOT11_N_SUPPORT
5361 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5366 if (pAd->BATable.numAsOriginator)
5369 // enable the RTS/CTS to avoid channel collision
5371 SetMask = ALLN_SETPROTECT;
5374 #endif // DOT11_N_SUPPORT //
5376 // Config ASIC RTS threshold register
5377 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5378 MacReg &= 0xFF0000FF;
5380 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5382 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5384 #ifdef DOT11_N_SUPPORT
5385 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5386 #endif // DOT11_N_SUPPORT //
5387 (pAd->CommonCfg.bAggregationCapable == TRUE))
5388 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5390 MacReg |= (0x1000 << 8);
5394 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5398 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5400 // Initial common protection settings
5401 RTMPZeroMemory(Protect, sizeof(Protect));
5404 ProtCfg.field.TxopAllowGF40 = 1;
5405 ProtCfg.field.TxopAllowGF20 = 1;
5406 ProtCfg.field.TxopAllowMM40 = 1;
5407 ProtCfg.field.TxopAllowMM20 = 1;
5408 ProtCfg.field.TxopAllowOfdm = 1;
5409 ProtCfg.field.TxopAllowCck = 1;
5410 ProtCfg.field.RTSThEn = 1;
5411 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5413 // update PHY mode and rate
5414 if (pAd->CommonCfg.Channel > 14)
5415 ProtCfg.field.ProtectRate = 0x4000;
5416 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5418 // Handle legacy(B/G) protection
5419 if (bDisableBGProtect)
5421 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5422 ProtCfg.field.ProtectCtrl = 0;
5423 Protect[0] = ProtCfg.word;
5424 Protect[1] = ProtCfg.word;
5428 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5429 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5430 Protect[0] = ProtCfg.word;
5431 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5432 Protect[1] = ProtCfg.word;
5435 #ifdef DOT11_N_SUPPORT
5436 // Decide HT frame protection.
5437 if ((SetMask & ALLN_SETPROTECT) != 0)
5439 switch(OperationMode)
5443 // 1.All STAs in the BSS are 20/40 MHz HT
5444 // 2. in ai 20/40MHz BSS
5445 // 3. all STAs are 20MHz in a 20MHz BSS
5446 // Pure HT. no protection.
5450 // PROT_TXOP(25:20) -- 010111
5451 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5452 // PROT_CTRL(17:16) -- 00 (None)
5453 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5454 Protect[2] = 0x01744004;
5458 // PROT_TXOP(25:20) -- 111111
5459 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5460 // PROT_CTRL(17:16) -- 00 (None)
5461 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5462 Protect[3] = 0x03f44084;
5466 // PROT_TXOP(25:20) -- 010111
5467 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5468 // PROT_CTRL(17:16) -- 00 (None)
5469 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5470 Protect[4] = 0x01744004;
5474 // PROT_TXOP(25:20) -- 111111
5475 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5476 // PROT_CTRL(17:16) -- 00 (None)
5477 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5478 Protect[5] = 0x03f44084;
5482 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5483 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5484 Protect[4] = 0x01754004;
5485 Protect[5] = 0x03f54084;
5487 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5491 // This is "HT non-member protection mode."
5492 // If there may be non-HT STAs my BSS
5493 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5494 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5495 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5497 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5498 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5500 //Assign Protection method for 20&40 MHz packets
5501 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5502 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5503 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5504 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5505 Protect[2] = ProtCfg.word;
5506 Protect[3] = ProtCfg4.word;
5507 Protect[4] = ProtCfg.word;
5508 Protect[5] = ProtCfg4.word;
5509 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5513 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5514 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5515 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5517 //Assign Protection method for 40MHz packets
5518 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5519 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5520 Protect[2] = ProtCfg.word;
5521 Protect[3] = ProtCfg4.word;
5524 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5525 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5527 Protect[4] = ProtCfg.word;
5528 Protect[5] = ProtCfg4.word;
5530 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5534 // HT mixed mode. PROTECT ALL!
5536 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5537 ProtCfg4.word = 0x03f44084;
5538 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5539 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5541 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5542 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5544 //Assign Protection method for 20&40 MHz packets
5545 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5546 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5547 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5548 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5549 Protect[2] = ProtCfg.word;
5550 Protect[3] = ProtCfg4.word;
5551 Protect[4] = ProtCfg.word;
5552 Protect[5] = ProtCfg4.word;
5553 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5557 // Special on for Atheros problem n chip.
5558 Protect[2] = 0x01754004;
5559 Protect[3] = 0x03f54084;
5560 Protect[4] = 0x01754004;
5561 Protect[5] = 0x03f54084;
5562 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5566 #endif // DOT11_N_SUPPORT //
5568 offset = CCK_PROT_CFG;
5569 for (i = 0;i < 6;i++)
5571 if ((SetMask & (1<< i)))
5573 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5579 ==========================================================================
5582 IRQL = PASSIVE_LEVEL
5583 IRQL = DISPATCH_LEVEL
5585 ==========================================================================
5587 VOID AsicSwitchChannel(
5588 IN PRTMP_ADAPTER pAd,
5592 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5593 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5595 UINT32 Value = 0; //BbpReg, Value;
5596 RTMP_RF_REGS *RFRegTable;
5598 // Search Tx power value
5599 for (index = 0; index < pAd->ChannelListNum; index++)
5601 if (Channel == pAd->ChannelList[index].Channel)
5603 TxPwer = pAd->ChannelList[index].Power;
5604 TxPwer2 = pAd->ChannelList[index].Power2;
5609 if (index == MAX_NUM_OF_CHANNELS)
5611 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5615 RFRegTable = RF2850RegTable;
5617 switch (pAd->RfIcType)
5624 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5626 if (Channel == RFRegTable[index].Channel)
5628 R2 = RFRegTable[index].R2;
5629 if (pAd->Antenna.field.TxPath == 1)
5631 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5634 if (pAd->Antenna.field.RxPath == 2)
5636 R2 |= 0x40; // write 1 to off Rxpath.
5638 else if (pAd->Antenna.field.RxPath == 1)
5640 R2 |= 0x20040; // write 1 to off RxPath
5645 // initialize R3, R4
5646 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5647 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5649 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5651 if ((TxPwer >= -7) && (TxPwer < 0))
5653 TxPwer = (7+TxPwer);
5654 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5655 R3 |= (TxPwer << 10);
5656 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5660 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5661 R3 |= (TxPwer << 10) | (1 << 9);
5665 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5667 TxPwer2 = (7+TxPwer2);
5668 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5669 R4 |= (TxPwer2 << 7);
5670 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5674 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5675 R4 |= (TxPwer2 << 7) | (1 << 6);
5680 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5681 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5684 // Based on BBP current mode before changing RF channel.
5685 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5691 pAd->LatchRfRegs.Channel = Channel;
5692 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5693 pAd->LatchRfRegs.R2 = R2;
5694 pAd->LatchRfRegs.R3 = R3;
5695 pAd->LatchRfRegs.R4 = R4;
5697 // Set RF value 1's set R3[bit2] = [0]
5698 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5699 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5700 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5701 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5705 // Set RF value 2's set R3[bit2] = [1]
5706 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5707 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5708 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5709 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5713 // Set RF value 3's set R3[bit2] = [0]
5714 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5715 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5716 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5717 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5729 // Change BBP setting during siwtch from a->g, g->a
5732 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5734 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5735 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5736 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5737 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.
5738 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5740 // Rx High power VGA offset for LNA select
5741 if (pAd->NicConfig2.field.ExternalLNAForG)
5743 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5744 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5748 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5749 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5752 // 5G band selection PIN, bit1 and bit2 are complement
5753 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5756 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5758 // Turn off unused PA or LNA when only 1T or 1R
5759 if (pAd->Antenna.field.TxPath == 1)
5761 TxPinCfg &= 0xFFFFFFF3;
5763 if (pAd->Antenna.field.RxPath == 1)
5765 TxPinCfg &= 0xFFFFF3FF;
5768 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5772 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5774 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5775 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5776 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5777 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.
5778 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5780 // Rx High power VGA offset for LNA select
5781 if (pAd->NicConfig2.field.ExternalLNAForA)
5783 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5787 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5790 // 5G band selection PIN, bit1 and bit2 are complement
5791 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5794 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5796 // Turn off unused PA or LNA when only 1T or 1R
5797 if (pAd->Antenna.field.TxPath == 1)
5799 TxPinCfg &= 0xFFFFFFF3;
5801 if (pAd->Antenna.field.RxPath == 1)
5803 TxPinCfg &= 0xFFFFF3FF;
5806 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5809 // R66 should be set according to Channel and use 20MHz when scanning
5810 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5812 RTMPSetAGCInitValue(pAd, BW_20);
5814 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5817 // On 11A, We should delay and wait RF/BBP to be stable
5818 // and the appropriate time should be 1000 micro seconds
5819 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5821 RTMPusecDelay(1000);
5823 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",
5826 (R3 & 0x00003e00) >> 9,
5827 (R4 & 0x000007c0) >> 6,
5828 pAd->Antenna.field.TxPath,
5829 pAd->LatchRfRegs.R1,
5830 pAd->LatchRfRegs.R2,
5831 pAd->LatchRfRegs.R3,
5832 pAd->LatchRfRegs.R4));
5836 ==========================================================================
5838 This function is required for 2421 only, and should not be used during
5839 site survey. It's only required after NIC decided to stay at a channel
5840 for a longer period.
5841 When this function is called, it's always after AsicSwitchChannel().
5843 IRQL = PASSIVE_LEVEL
5844 IRQL = DISPATCH_LEVEL
5846 ==========================================================================
5848 VOID AsicLockChannel(
5849 IN PRTMP_ADAPTER pAd,
5855 ==========================================================================
5858 IRQL = PASSIVE_LEVEL
5859 IRQL = DISPATCH_LEVEL
5861 ==========================================================================
5863 VOID AsicAntennaSelect(
5864 IN PRTMP_ADAPTER pAd,
5870 ========================================================================
5872 Routine Description:
5873 Antenna miscellaneous setting.
5876 pAd Pointer to our adapter
5877 BandState Indicate current Band State.
5882 IRQL <= DISPATCH_LEVEL
5885 1.) Frame End type control
5886 only valid for G only (RF_2527 & RF_2529)
5887 0: means DPDT, set BBP R4 bit 5 to 1
5888 1: means SPDT, set BBP R4 bit 5 to 0
5891 ========================================================================
5893 VOID AsicAntennaSetting(
5894 IN PRTMP_ADAPTER pAd,
5895 IN ABGBAND_STATE BandState)
5899 VOID AsicRfTuningExec(
5900 IN PVOID SystemSpecific1,
5901 IN PVOID FunctionContext,
5902 IN PVOID SystemSpecific2,
5903 IN PVOID SystemSpecific3)
5908 ==========================================================================
5910 Gives CCK TX rate 2 more dB TX power.
5911 This routine works only in LINK UP in INFRASTRUCTURE mode.
5913 calculate desired Tx power in RF R3.Tx0~5, should consider -
5914 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5915 1. TxPowerPercentage
5916 2. auto calibration based on TSSI feedback
5917 3. extra 2 db for CCK
5918 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5920 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5921 it should be called AFTER MlmeDynamicTxRatSwitching()
5922 ==========================================================================
5924 VOID AsicAdjustTxPower(
5925 IN PRTMP_ADAPTER pAd)
5929 BOOLEAN bAutoTxAgc = FALSE;
5930 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5931 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5932 PCHAR pTxAgcCompensate;
5936 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5937 || (pAd->bPCIclkOff == TRUE)
5938 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
5939 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
5942 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5944 if (pAd->CommonCfg.CentralChannel > 14)
5946 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5947 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5948 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5949 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5950 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5954 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5955 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5956 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5957 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5958 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5963 if (pAd->CommonCfg.Channel > 14)
5965 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5966 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5967 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5968 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5969 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5973 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5974 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5975 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5976 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5977 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5981 // TX power compensation for temperature variation based on TSSI. try every 4 second
5982 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5984 if (pAd->CommonCfg.Channel <= 14)
5987 bAutoTxAgc = pAd->bAutoTxAgcG;
5988 TssiRef = pAd->TssiRefG;
5989 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5990 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5991 TxAgcStep = pAd->TxAgcStepG;
5992 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5997 bAutoTxAgc = pAd->bAutoTxAgcA;
5998 TssiRef = pAd->TssiRefA;
5999 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6000 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6001 TxAgcStep = pAd->TxAgcStepA;
6002 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6007 /* BbpR1 is unsigned char */
6008 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6010 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6011 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6012 /* step value is defined in pAd->TxAgcStepG for tx power value */
6014 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6015 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6016 above value are examined in mass factory production */
6017 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6019 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6020 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6021 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6023 if (BbpR49 > pTssiMinusBoundary[1])
6025 // Reading is larger than the reference value
6026 // check for how large we need to decrease the Tx power
6027 for (idx = 1; idx < 5; idx++)
6029 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6032 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6033 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6035 DeltaPwr += (*pTxAgcCompensate);
6036 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6037 BbpR49, TssiRef, TxAgcStep, idx-1));
6039 else if (BbpR49 < pTssiPlusBoundary[1])
6041 // Reading is smaller than the reference value
6042 // check for how large we need to increase the Tx power
6043 for (idx = 1; idx < 5; idx++)
6045 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6048 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6049 *pTxAgcCompensate = TxAgcStep * (idx-1);
6050 DeltaPwr += (*pTxAgcCompensate);
6051 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6052 BbpR49, TssiRef, TxAgcStep, idx-1));
6056 *pTxAgcCompensate = 0;
6057 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6058 BbpR49, TssiRef, TxAgcStep, 0));
6064 if (pAd->CommonCfg.Channel <= 14)
6066 bAutoTxAgc = pAd->bAutoTxAgcG;
6067 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6071 bAutoTxAgc = pAd->bAutoTxAgcA;
6072 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6076 DeltaPwr += (*pTxAgcCompensate);
6079 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6082 /* calculate delta power based on the percentage specified from UI */
6083 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6084 // We lower TX power here according to the percentage specified from UI
6085 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6087 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6089 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6093 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6097 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6101 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6106 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6111 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6113 /* reset different new tx power for different TX rate */
6116 if (TxPwr[i] != 0xffffffff)
6120 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6122 if ((Value + DeltaPwr) < 0)
6124 Value = 0; /* min */
6126 else if ((Value + DeltaPwr) > 0xF)
6128 Value = 0xF; /* max */
6132 Value += DeltaPwr; /* temperature compensation */
6135 /* fill new value to CSR offset */
6136 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6139 /* write tx power value to CSR */
6140 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6141 TX power for OFDM 6M/9M
6142 TX power for CCK5.5M/11M
6143 TX power for CCK1M/2M */
6144 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6145 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6151 #ifdef CONFIG_STA_SUPPORT
6153 ==========================================================================
6155 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6156 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6157 the wakeup timer timeout. Driver has to issue a separate command to wake
6160 IRQL = DISPATCH_LEVEL
6162 ==========================================================================
6164 VOID AsicSleepThenAutoWakeup(
6165 IN PRTMP_ADAPTER pAd,
6166 IN USHORT TbttNumToNextWakeUp)
6168 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6172 ==========================================================================
6174 AsicForceWakeup() is used whenever manual wakeup is required
6175 AsicForceSleep() should only be used when not in INFRA BSS. When
6176 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6177 ==========================================================================
6179 VOID AsicForceSleep(
6180 IN PRTMP_ADAPTER pAd)
6186 ==========================================================================
6188 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6191 IRQL = PASSIVE_LEVEL
6192 IRQL = DISPATCH_LEVEL
6193 ==========================================================================
6195 VOID AsicForceWakeup(
6196 IN PRTMP_ADAPTER pAd,
6199 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6200 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6202 #endif // CONFIG_STA_SUPPORT //
6204 ==========================================================================
6208 IRQL = DISPATCH_LEVEL
6210 ==========================================================================
6213 IN PRTMP_ADAPTER pAd,
6217 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6218 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6220 Addr4 = (ULONG)(pBssid[0]) |
6221 (ULONG)(pBssid[1] << 8) |
6222 (ULONG)(pBssid[2] << 16) |
6223 (ULONG)(pBssid[3] << 24);
6224 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6227 // always one BSSID in STA mode
6228 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6230 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6233 VOID AsicSetMcastWC(
6234 IN PRTMP_ADAPTER pAd)
6236 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6239 pEntry->Sst = SST_ASSOC;
6240 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6241 pEntry->PsMode = PWR_ACTIVE;
6242 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6243 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6247 ==========================================================================
6250 IRQL = DISPATCH_LEVEL
6252 ==========================================================================
6254 VOID AsicDelWcidTab(
6255 IN PRTMP_ADAPTER pAd,
6258 ULONG Addr0 = 0x0, Addr1 = 0x0;
6261 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6262 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6263 RTMP_IO_WRITE32(pAd, offset, Addr0);
6265 RTMP_IO_WRITE32(pAd, offset, Addr1);
6269 ==========================================================================
6272 IRQL = DISPATCH_LEVEL
6274 ==========================================================================
6277 IN PRTMP_ADAPTER pAd)
6279 TX_LINK_CFG_STRUC TxLinkCfg;
6282 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6283 TxLinkCfg.field.TxRDGEn = 1;
6284 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6286 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6289 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6291 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6295 ==========================================================================
6298 IRQL = DISPATCH_LEVEL
6300 ==========================================================================
6302 VOID AsicDisableRDG(
6303 IN PRTMP_ADAPTER pAd)
6305 TX_LINK_CFG_STRUC TxLinkCfg;
6309 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6310 TxLinkCfg.field.TxRDGEn = 0;
6311 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6313 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6316 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6317 #ifdef DOT11_N_SUPPORT
6318 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6319 #endif // DOT11_N_SUPPORT //
6322 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6323 if (pAd->CommonCfg.bEnableTxBurst)
6326 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6330 ==========================================================================
6333 IRQL = PASSIVE_LEVEL
6334 IRQL = DISPATCH_LEVEL
6336 ==========================================================================
6338 VOID AsicDisableSync(
6339 IN PRTMP_ADAPTER pAd)
6341 BCN_TIME_CFG_STRUC csr;
6343 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6345 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6346 // that NIC will never wakes up because TSF stops and no more
6348 pAd->TbttTickCount = 0;
6349 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6350 csr.field.bBeaconGen = 0;
6351 csr.field.bTBTTEnable = 0;
6352 csr.field.TsfSyncMode = 0;
6353 csr.field.bTsfTicking = 0;
6354 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6359 ==========================================================================
6362 IRQL = DISPATCH_LEVEL
6364 ==========================================================================
6366 VOID AsicEnableBssSync(
6367 IN PRTMP_ADAPTER pAd)
6369 BCN_TIME_CFG_STRUC csr;
6371 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6373 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6374 #ifdef CONFIG_STA_SUPPORT
6375 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6377 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6378 csr.field.bTsfTicking = 1;
6379 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6380 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6381 csr.field.bTBTTEnable = 1;
6383 #endif // CONFIG_STA_SUPPORT //
6384 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6388 ==========================================================================
6391 BEACON frame in shared memory should be built ok before this routine
6392 can be called. Otherwise, a garbage frame maybe transmitted out every
6395 IRQL = DISPATCH_LEVEL
6397 ==========================================================================
6399 VOID AsicEnableIbssSync(
6400 IN PRTMP_ADAPTER pAd)
6402 BCN_TIME_CFG_STRUC csr9;
6406 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6408 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6409 csr9.field.bBeaconGen = 0;
6410 csr9.field.bTBTTEnable = 0;
6411 csr9.field.bTsfTicking = 0;
6412 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6414 // move BEACON TXD and frame content to on-chip memory
6415 ptr = (PUCHAR)&pAd->BeaconTxWI;
6416 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6418 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6419 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6423 // start right after the 16-byte TXWI field
6424 ptr = pAd->BeaconBuf;
6425 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6427 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6428 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6432 // start sending BEACON
6433 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6434 csr9.field.bTsfTicking = 1;
6435 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6436 csr9.field.bTBTTEnable = 1;
6437 csr9.field.bBeaconGen = 1;
6438 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6442 ==========================================================================
6445 IRQL = PASSIVE_LEVEL
6446 IRQL = DISPATCH_LEVEL
6448 ==========================================================================
6450 VOID AsicSetEdcaParm(
6451 IN PRTMP_ADAPTER pAd,
6452 IN PEDCA_PARM pEdcaParm)
6454 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6455 AC_TXOP_CSR0_STRUC csr0;
6456 AC_TXOP_CSR1_STRUC csr1;
6457 AIFSN_CSR_STRUC AifsnCsr;
6458 CWMIN_CSR_STRUC CwminCsr;
6459 CWMAX_CSR_STRUC CwmaxCsr;
6466 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6468 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6469 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6470 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6472 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6473 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6476 //========================================================
6477 // MAC Register has a copy .
6478 //========================================================
6479 if( pAd->CommonCfg.bEnableTxBurst )
6481 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6482 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6485 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6486 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6487 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6488 Ac0Cfg.field.Aifsn = 2;
6489 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6491 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6492 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6493 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6494 Ac1Cfg.field.Aifsn = 2;
6495 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6497 if (pAd->CommonCfg.PhyMode == PHY_11B)
6499 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6500 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6504 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6505 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6507 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6508 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6509 Ac2Cfg.field.Aifsn = 2;
6510 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6511 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6512 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6513 Ac3Cfg.field.Aifsn = 2;
6514 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6516 //========================================================
6517 // DMA Register has a copy too.
6518 //========================================================
6519 csr0.field.Ac0Txop = 0; // QID_AC_BE
6520 csr0.field.Ac1Txop = 0; // QID_AC_BK
6521 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6522 if (pAd->CommonCfg.PhyMode == PHY_11B)
6524 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6525 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6529 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6530 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6532 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6535 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6536 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6537 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6538 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6539 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6542 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6543 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6544 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6545 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6546 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6548 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6550 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6554 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6555 //========================================================
6556 // MAC Register has a copy.
6557 //========================================================
6559 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6560 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6562 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6564 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6565 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6566 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6567 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6569 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6570 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6571 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6572 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6574 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6575 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6576 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6577 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6578 #ifdef CONFIG_STA_SUPPORT
6579 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6581 // Tuning for Wi-Fi WMM S06
6582 if (pAd->CommonCfg.bWiFiTest &&
6583 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6584 Ac2Cfg.field.Aifsn -= 1;
6586 // Tuning for TGn Wi-Fi 5.2.32
6587 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6588 if (STA_TGN_WIFI_ON(pAd) &&
6589 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6591 Ac0Cfg.field.Aifsn = 3;
6592 Ac2Cfg.field.AcTxop = 5;
6595 #endif // CONFIG_STA_SUPPORT //
6597 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6598 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6599 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6600 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6603 if (pAd->CommonCfg.bWiFiTest)
6605 if (Ac3Cfg.field.AcTxop == 102)
6607 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6608 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6609 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6610 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6611 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6614 //#endif // WIFI_TEST //
6616 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6617 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6618 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6619 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6622 //========================================================
6623 // DMA Register has a copy too.
6624 //========================================================
6625 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6626 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6627 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6629 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6630 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6631 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6634 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6635 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6636 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6637 #ifdef CONFIG_STA_SUPPORT
6638 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6639 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6640 #endif // CONFIG_STA_SUPPORT //
6641 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6644 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6645 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6646 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6647 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6648 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6651 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6652 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6653 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6654 #ifdef CONFIG_STA_SUPPORT
6655 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6657 // Tuning for Wi-Fi WMM S06
6658 if (pAd->CommonCfg.bWiFiTest &&
6659 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6660 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6662 // Tuning for TGn Wi-Fi 5.2.32
6663 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6664 if (STA_TGN_WIFI_ON(pAd) &&
6665 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6667 AifsnCsr.field.Aifsn0 = 3;
6668 AifsnCsr.field.Aifsn2 = 7;
6671 #endif // CONFIG_STA_SUPPORT //
6673 #ifdef CONFIG_STA_SUPPORT
6674 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6675 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6676 #endif // CONFIG_STA_SUPPORT //
6677 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6679 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6682 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6683 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6684 pEdcaParm->Aifsn[0],
6685 pEdcaParm->Cwmin[0],
6686 pEdcaParm->Cwmax[0],
6687 pEdcaParm->Txop[0]<<5,
6688 pEdcaParm->bACM[0]));
6689 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6690 pEdcaParm->Aifsn[1],
6691 pEdcaParm->Cwmin[1],
6692 pEdcaParm->Cwmax[1],
6693 pEdcaParm->Txop[1]<<5,
6694 pEdcaParm->bACM[1]));
6695 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6696 pEdcaParm->Aifsn[2],
6697 pEdcaParm->Cwmin[2],
6698 pEdcaParm->Cwmax[2],
6699 pEdcaParm->Txop[2]<<5,
6700 pEdcaParm->bACM[2]));
6701 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6702 pEdcaParm->Aifsn[3],
6703 pEdcaParm->Cwmin[3],
6704 pEdcaParm->Cwmax[3],
6705 pEdcaParm->Txop[3]<<5,
6706 pEdcaParm->bACM[3]));
6712 ==========================================================================
6715 IRQL = PASSIVE_LEVEL
6716 IRQL = DISPATCH_LEVEL
6718 ==========================================================================
6720 VOID AsicSetSlotTime(
6721 IN PRTMP_ADAPTER pAd,
6722 IN BOOLEAN bUseShortSlotTime)
6725 UINT32 RegValue = 0;
6727 #ifdef CONFIG_STA_SUPPORT
6728 if (pAd->CommonCfg.Channel > 14)
6729 bUseShortSlotTime = TRUE;
6730 #endif // CONFIG_STA_SUPPORT //
6732 if (bUseShortSlotTime)
6733 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6735 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6737 SlotTime = (bUseShortSlotTime)? 9 : 20;
6739 #ifdef CONFIG_STA_SUPPORT
6740 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6742 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6743 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6744 #ifdef DOT11_N_SUPPORT
6745 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6746 #endif // DOT11_N_SUPPORT //
6749 // In this case, we will think it is doing Wi-Fi test
6750 // And we will not set to short slot when bEnableTxBurst is TRUE.
6752 else if (pAd->CommonCfg.bEnableTxBurst)
6755 #endif // CONFIG_STA_SUPPORT //
6758 // For some reasons, always set it to short slot time.
6760 // ToDo: Should consider capability with 11B
6762 #ifdef CONFIG_STA_SUPPORT
6763 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6765 if (pAd->StaCfg.BssType == BSS_ADHOC)
6768 #endif // CONFIG_STA_SUPPORT //
6770 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6771 RegValue = RegValue & 0xFFFFFF00;
6773 RegValue |= SlotTime;
6775 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6779 ========================================================================
6781 Add Shared key information into ASIC.
6782 Update shared key, TxMic and RxMic to Asic Shared key table
6783 Update its cipherAlg to Asic Shared key Mode.
6786 ========================================================================
6788 VOID AsicAddSharedKeyEntry(
6789 IN PRTMP_ADAPTER pAd,
6797 ULONG offset; //, csr0;
6798 SHAREDKEY_MODE_STRUC csr1;
6801 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6802 //============================================================================================
6804 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6805 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6806 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]));
6809 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6810 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6814 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6815 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6817 //============================================================================================
6819 // fill key material - key + TX MIC + RX MIC
6821 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6822 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6824 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6827 offset += MAX_LEN_OF_SHARE_KEY;
6832 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6841 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6847 // Update cipher algorithm. WSTA always use BSS0
6849 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6850 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6851 if ((BssIndex%2) == 0)
6854 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6855 else if (KeyIdx == 1)
6856 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6857 else if (KeyIdx == 2)
6858 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6860 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6865 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6866 else if (KeyIdx == 1)
6867 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6868 else if (KeyIdx == 2)
6869 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6871 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6873 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6874 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6878 // IRQL = DISPATCH_LEVEL
6879 VOID AsicRemoveSharedKeyEntry(
6880 IN PRTMP_ADAPTER pAd,
6885 SHAREDKEY_MODE_STRUC csr1;
6887 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6889 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6890 if ((BssIndex%2) == 0)
6893 csr1.field.Bss0Key0CipherAlg = 0;
6894 else if (KeyIdx == 1)
6895 csr1.field.Bss0Key1CipherAlg = 0;
6896 else if (KeyIdx == 2)
6897 csr1.field.Bss0Key2CipherAlg = 0;
6899 csr1.field.Bss0Key3CipherAlg = 0;
6904 csr1.field.Bss1Key0CipherAlg = 0;
6905 else if (KeyIdx == 1)
6906 csr1.field.Bss1Key1CipherAlg = 0;
6907 else if (KeyIdx == 2)
6908 csr1.field.Bss1Key2CipherAlg = 0;
6910 csr1.field.Bss1Key3CipherAlg = 0;
6912 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6913 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6914 ASSERT(BssIndex < 4);
6920 VOID AsicUpdateWCIDAttribute(
6921 IN PRTMP_ADAPTER pAd,
6925 IN BOOLEAN bUsePairewiseKeyTable)
6927 ULONG WCIDAttri = 0, offset;
6930 // Update WCID attribute.
6931 // Only TxKey could update WCID attribute.
6933 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6934 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6935 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6938 VOID AsicUpdateWCIDIVEIV(
6939 IN PRTMP_ADAPTER pAd,
6946 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6948 RTMP_IO_WRITE32(pAd, offset, uIV);
6949 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6952 VOID AsicUpdateRxWCIDTable(
6953 IN PRTMP_ADAPTER pAd,
6960 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6961 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6962 RTMP_IO_WRITE32(pAd, offset, Addr);
6963 Addr = pAddr[4] + (pAddr[5] << 8);
6964 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6969 ========================================================================
6971 Routine Description:
6972 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6975 pAd Pointer to our adapter
6976 WCID WCID Entry number.
6977 BssIndex BSSID index, station or none multiple BSSID support
6978 this value should be 0.
6979 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6980 pCipherKey Pointer to Cipher Key.
6981 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6982 otherwise PairewiseKey table
6983 bTxKey This is the transmit key if enabled.
6989 This routine will set the relative key stuff to Asic including WCID attribute,
6990 Cipher Key, Cipher algorithm and IV/EIV.
6992 IV/EIV will be update if this CipherKey is the transmission key because
6993 ASIC will base on IV's KeyID value to select Cipher Key.
6995 If bTxKey sets to FALSE, this is not the TX key, but it could be
6998 For AP mode bTxKey must be always set to TRUE.
6999 ========================================================================
7001 VOID AsicAddKeyEntry(
7002 IN PRTMP_ADAPTER pAd,
7006 IN PCIPHER_KEY pCipherKey,
7007 IN BOOLEAN bUsePairewiseKeyTable,
7012 PUCHAR pKey = pCipherKey->Key;
7013 PUCHAR pTxMic = pCipherKey->TxMic;
7014 PUCHAR pRxMic = pCipherKey->RxMic;
7015 PUCHAR pTxtsc = pCipherKey->TxTsc;
7016 UCHAR CipherAlg = pCipherKey->CipherAlg;
7017 SHAREDKEY_MODE_STRUC csr1;
7020 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7022 // 1.) decide key table offset
7024 if (bUsePairewiseKeyTable)
7025 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7027 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7030 // 2.) Set Key to Asic
7032 //for (i = 0; i < KeyLen; i++)
7033 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7035 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7037 offset += MAX_LEN_OF_PEER_KEY;
7040 // 3.) Set MIC key if available
7044 for (i = 0; i < 8; i++)
7046 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7049 offset += LEN_TKIP_TXMICK;
7053 for (i = 0; i < 8; i++)
7055 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7061 // 4.) Modify IV/EIV if needs
7062 // This will force Asic to use this key ID by setting IV.
7066 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7070 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7071 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7072 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7074 IV4 = (KeyIdx << 6);
7075 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7076 IV4 |= 0x20; // turn on extension bit means EIV existence
7078 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7084 for (i = 0; i < 4; i++)
7086 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7089 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7092 if (!bUsePairewiseKeyTable)
7095 // Only update the shared key security mode
7097 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7098 if ((BssIndex % 2) == 0)
7101 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7102 else if (KeyIdx == 1)
7103 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7104 else if (KeyIdx == 2)
7105 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7107 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7112 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7113 else if (KeyIdx == 1)
7114 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7115 else if (KeyIdx == 2)
7116 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7118 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7120 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7123 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7128 ========================================================================
7130 Add Pair-wise key material into ASIC.
7131 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7134 ========================================================================
7136 VOID AsicAddPairwiseKeyEntry(
7137 IN PRTMP_ADAPTER pAd,
7140 IN CIPHER_KEY *pCipherKey)
7144 PUCHAR pKey = pCipherKey->Key;
7145 PUCHAR pTxMic = pCipherKey->TxMic;
7146 PUCHAR pRxMic = pCipherKey->RxMic;
7148 UCHAR CipherAlg = pCipherKey->CipherAlg;
7152 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7153 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7155 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7157 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7160 RTMP_IO_READ32(pAd, offset + i, &Value);
7163 offset += MAX_LEN_OF_PEER_KEY;
7170 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7178 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7182 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7183 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7184 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]));
7187 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7188 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7192 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7193 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7197 ========================================================================
7199 Remove Pair-wise key material from ASIC.
7202 ========================================================================
7204 VOID AsicRemovePairwiseKeyEntry(
7205 IN PRTMP_ADAPTER pAd,
7212 // re-set the entry's WCID attribute as OPEN-NONE.
7213 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7214 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7215 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7218 BOOLEAN AsicSendCommandToMcu(
7219 IN PRTMP_ADAPTER pAd,
7225 HOST_CMD_CSR_STRUC H2MCmd;
7226 H2M_MAILBOX_STRUC H2MMailbox;
7231 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7232 if (H2MMailbox.field.Owner == 0)
7244 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7246 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7248 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7249 // Reset DMA/CPU ring index
7250 RTMPRingCleanUp(pAd, QID_AC_BK);
7251 RTMPRingCleanUp(pAd, QID_AC_BE);
7252 RTMPRingCleanUp(pAd, QID_AC_VI);
7253 RTMPRingCleanUp(pAd, QID_AC_VO);
7254 RTMPRingCleanUp(pAd, QID_HCCA);
7255 RTMPRingCleanUp(pAd, QID_MGMT);
7256 RTMPRingCleanUp(pAd, QID_RX);
7259 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7261 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7262 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7267 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7268 H2MMailbox.field.CmdToken = Token;
7269 H2MMailbox.field.HighByte = Arg1;
7270 H2MMailbox.field.LowByte = Arg0;
7271 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7274 H2MCmd.field.HostCommand = Command;
7275 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7277 if (Command != 0x80)
7284 BOOLEAN AsicCheckCommanOk(
7285 IN PRTMP_ADAPTER pAd,
7288 UINT32 CmdStatus = 0, CID = 0, i;
7289 UINT32 ThisCIDMask = 0;
7294 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7295 // Find where the command is. Because this is randomly specified by firmware.
7296 if ((CID & CID0MASK) == Command)
7298 ThisCIDMask = CID0MASK;
7301 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7303 ThisCIDMask = CID1MASK;
7306 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7308 ThisCIDMask = CID2MASK;
7311 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7313 ThisCIDMask = CID3MASK;
7321 // Get CommandStatus Value
7322 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7324 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7327 // If Status is 1, the comamnd is success.
7328 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7329 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7331 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7332 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7333 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7336 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7340 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7342 // Clear Command and Status.
7343 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7344 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7350 ========================================================================
7352 Routine Description:
7353 Verify the support rate for different PHY type
7356 pAd Pointer to our adapter
7361 IRQL = PASSIVE_LEVEL
7363 ========================================================================
7365 VOID RTMPCheckRates(
7366 IN PRTMP_ADAPTER pAd,
7367 IN OUT UCHAR SupRate[],
7368 IN OUT UCHAR *SupRateLen)
7370 UCHAR RateIdx, i, j;
7371 UCHAR NewRate[12], NewRateLen;
7375 if (pAd->CommonCfg.PhyMode == PHY_11B)
7380 // Check for support rates exclude basic rate bit
7381 for (i = 0; i < *SupRateLen; i++)
7382 for (j = 0; j < RateIdx; j++)
7383 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7384 NewRate[NewRateLen++] = SupRate[i];
7386 *SupRateLen = NewRateLen;
7387 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7390 #ifdef CONFIG_STA_SUPPORT
7391 #ifdef DOT11_N_SUPPORT
7392 BOOLEAN RTMPCheckChannel(
7393 IN PRTMP_ADAPTER pAd,
7394 IN UCHAR CentralChannel,
7398 UCHAR UpperChannel = 0, LowerChannel = 0;
7399 UCHAR NoEffectChannelinList = 0;
7401 // Find upper and lower channel according to 40MHz current operation.
7402 if (CentralChannel < Channel)
7404 UpperChannel = Channel;
7405 if (CentralChannel > 2)
7406 LowerChannel = CentralChannel - 2;
7410 else if (CentralChannel > Channel)
7412 UpperChannel = CentralChannel + 2;
7413 LowerChannel = Channel;
7416 for (k = 0;k < pAd->ChannelListNum;k++)
7418 if (pAd->ChannelList[k].Channel == UpperChannel)
7420 NoEffectChannelinList ++;
7422 if (pAd->ChannelList[k].Channel == LowerChannel)
7424 NoEffectChannelinList ++;
7428 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7429 if (NoEffectChannelinList == 2)
7436 ========================================================================
7438 Routine Description:
7439 Verify the support rate for HT phy type
7442 pAd Pointer to our adapter
7445 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7447 IRQL = PASSIVE_LEVEL
7449 ========================================================================
7451 BOOLEAN RTMPCheckHt(
7452 IN PRTMP_ADAPTER pAd,
7454 IN HT_CAPABILITY_IE *pHtCapability,
7455 IN ADD_HT_INFO_IE *pAddHtInfo)
7457 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7460 // If use AMSDU, set flag.
7461 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7462 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7463 // Save Peer Capability
7464 if (pHtCapability->HtCapInfo.ShortGIfor20)
7465 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7466 if (pHtCapability->HtCapInfo.ShortGIfor40)
7467 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7468 if (pHtCapability->HtCapInfo.TxSTBC)
7469 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7470 if (pHtCapability->HtCapInfo.RxSTBC)
7471 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7472 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7474 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7477 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7479 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7482 // Will check ChannelWidth for MCSSet[4] below
7483 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7484 switch (pAd->CommonCfg.RxStream)
7487 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7488 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7489 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7490 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7493 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7494 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7495 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7496 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7499 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7500 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7501 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7502 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7506 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7508 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7509 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7510 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7512 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7514 // Send Assoc Req with my HT capability.
7515 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7516 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7517 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7518 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7519 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7520 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7521 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7522 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7523 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7524 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7525 if (pAd->CommonCfg.bRdg)
7527 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7528 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7531 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7532 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7534 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7537 #endif // DOT11_N_SUPPORT //
7538 #endif // CONFIG_STA_SUPPORT //
7541 ========================================================================
7543 Routine Description:
7544 Verify the support rate for different PHY type
7547 pAd Pointer to our adapter
7552 IRQL = PASSIVE_LEVEL
7554 ========================================================================
7556 VOID RTMPUpdateMlmeRate(
7557 IN PRTMP_ADAPTER pAd)
7560 UCHAR ProperMlmeRate; //= RATE_54;
7561 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7562 BOOLEAN bMatch = FALSE;
7564 switch (pAd->CommonCfg.PhyMode)
7567 ProperMlmeRate = RATE_11;
7568 MinimumRate = RATE_1;
7570 case PHY_11BG_MIXED:
7571 #ifdef DOT11_N_SUPPORT
7572 case PHY_11ABGN_MIXED:
7573 case PHY_11BGN_MIXED:
7574 #endif // DOT11_N_SUPPORT //
7575 if ((pAd->MlmeAux.SupRateLen == 4) &&
7576 (pAd->MlmeAux.ExtRateLen == 0))
7578 ProperMlmeRate = RATE_11;
7580 ProperMlmeRate = RATE_24;
7582 if (pAd->MlmeAux.Channel <= 14)
7583 MinimumRate = RATE_1;
7585 MinimumRate = RATE_6;
7588 #ifdef DOT11_N_SUPPORT
7589 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7590 case PHY_11GN_MIXED:
7591 case PHY_11AGN_MIXED:
7592 case PHY_11AN_MIXED:
7594 #endif // DOT11_N_SUPPORT //
7595 ProperMlmeRate = RATE_24;
7596 MinimumRate = RATE_6;
7598 case PHY_11ABG_MIXED:
7599 ProperMlmeRate = RATE_24;
7600 if (pAd->MlmeAux.Channel <= 14)
7601 MinimumRate = RATE_1;
7603 MinimumRate = RATE_6;
7606 ProperMlmeRate = RATE_1;
7607 MinimumRate = RATE_1;
7611 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7613 for (j = 0; j < RateIdx; j++)
7615 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7617 if (j == ProperMlmeRate)
7629 if (bMatch == FALSE)
7631 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7633 for (j = 0; j < RateIdx; j++)
7635 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7637 if (j == ProperMlmeRate)
7650 if (bMatch == FALSE)
7652 ProperMlmeRate = MinimumRate;
7655 pAd->CommonCfg.MlmeRate = MinimumRate;
7656 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7657 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7659 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7660 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7661 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7662 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7666 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7667 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7668 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7669 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7672 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7676 IN PRTMP_ADAPTER pAd,
7683 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7688 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7690 larger = max(Rssi0, Rssi1);
7693 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7695 larger = max(larger, Rssi2);
7705 ========================================================================
7706 Routine Description:
7707 Periodic evaluate antenna link status
7710 pAd - Adapter pointer
7715 ========================================================================
7717 VOID AsicEvaluateRxAnt(
7718 IN PRTMP_ADAPTER pAd)
7722 #ifdef CONFIG_STA_SUPPORT
7723 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7725 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7726 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7727 fRTMP_ADAPTER_RADIO_OFF |
7728 fRTMP_ADAPTER_NIC_NOT_EXIST |
7729 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7732 if (pAd->StaCfg.Psm == PWR_SAVE)
7735 #endif // CONFIG_STA_SUPPORT //
7737 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7739 if(pAd->Antenna.field.RxPath == 3)
7743 else if(pAd->Antenna.field.RxPath == 2)
7747 else if(pAd->Antenna.field.RxPath == 1)
7751 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7752 #ifdef CONFIG_STA_SUPPORT
7753 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7754 pAd->StaCfg.BBPR3 = BBPR3;
7755 #endif // CONFIG_STA_SUPPORT //
7756 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7759 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7760 pAd->RalinkCounters.OneSecTxRetryOkCount +
7761 pAd->RalinkCounters.OneSecTxFailCount;
7763 if (TxTotalCnt > 50)
7765 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7766 pAd->Mlme.bLowThroughput = FALSE;
7770 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7771 pAd->Mlme.bLowThroughput = TRUE;
7777 ========================================================================
7778 Routine Description:
7779 After evaluation, check antenna link status
7782 pAd - Adapter pointer
7787 ========================================================================
7789 VOID AsicRxAntEvalTimeout(
7790 IN PVOID SystemSpecific1,
7791 IN PVOID FunctionContext,
7792 IN PVOID SystemSpecific2,
7793 IN PVOID SystemSpecific3)
7795 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7796 #ifdef CONFIG_STA_SUPPORT
7798 CHAR larger = -127, rssi0, rssi1, rssi2;
7799 #endif // CONFIG_STA_SUPPORT //
7801 #ifdef CONFIG_STA_SUPPORT
7802 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7804 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7805 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7806 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7807 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7810 if (pAd->StaCfg.Psm == PWR_SAVE)
7814 // if the traffic is low, use average rssi as the criteria
7815 if (pAd->Mlme.bLowThroughput == TRUE)
7817 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7818 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7819 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7823 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7824 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7825 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7828 if(pAd->Antenna.field.RxPath == 3)
7830 larger = max(rssi0, rssi1);
7832 if (larger > (rssi2 + 20))
7833 pAd->Mlme.RealRxPath = 2;
7835 pAd->Mlme.RealRxPath = 3;
7837 else if(pAd->Antenna.field.RxPath == 2)
7839 if (rssi0 > (rssi1 + 20))
7840 pAd->Mlme.RealRxPath = 1;
7842 pAd->Mlme.RealRxPath = 2;
7845 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7847 if(pAd->Mlme.RealRxPath == 3)
7851 else if(pAd->Mlme.RealRxPath == 2)
7855 else if(pAd->Mlme.RealRxPath == 1)
7859 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7860 pAd->StaCfg.BBPR3 = BBPR3;
7863 #endif // CONFIG_STA_SUPPORT //
7869 VOID APSDPeriodicExec(
7870 IN PVOID SystemSpecific1,
7871 IN PVOID FunctionContext,
7872 IN PVOID SystemSpecific2,
7873 IN PVOID SystemSpecific3)
7875 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7877 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7880 pAd->CommonCfg.TriggerTimerCount++;
7885 ========================================================================
7886 Routine Description:
7887 Set/reset MAC registers according to bPiggyBack parameter
7890 pAd - Adapter pointer
7891 bPiggyBack - Enable / Disable Piggy-Back
7896 ========================================================================
7898 VOID RTMPSetPiggyBack(
7899 IN PRTMP_ADAPTER pAd,
7900 IN BOOLEAN bPiggyBack)
7902 TX_LINK_CFG_STRUC TxLinkCfg;
7904 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7906 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7907 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7911 ========================================================================
7912 Routine Description:
7913 check if this entry need to switch rate automatically
7923 ========================================================================
7925 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7926 IN PRTMP_ADAPTER pAd,
7927 IN PMAC_TABLE_ENTRY pEntry)
7929 BOOLEAN result = TRUE;
7932 #ifdef CONFIG_STA_SUPPORT
7933 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7935 // only associated STA counts
7936 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7938 result = pAd->StaCfg.bAutoTxRateSwitch;
7943 #endif // CONFIG_STA_SUPPORT //
7951 BOOLEAN RTMPAutoRateSwitchCheck(
7952 IN PRTMP_ADAPTER pAd)
7955 #ifdef CONFIG_STA_SUPPORT
7956 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7958 if (pAd->StaCfg.bAutoTxRateSwitch)
7961 #endif // CONFIG_STA_SUPPORT //
7967 ========================================================================
7968 Routine Description:
7969 check if this entry need to fix tx legacy rate
7979 ========================================================================
7981 UCHAR RTMPStaFixedTxMode(
7982 IN PRTMP_ADAPTER pAd,
7983 IN PMAC_TABLE_ENTRY pEntry)
7985 UCHAR tx_mode = FIXED_TXMODE_HT;
7988 #ifdef CONFIG_STA_SUPPORT
7989 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7991 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7993 #endif // CONFIG_STA_SUPPORT //
7999 ========================================================================
8000 Routine Description:
8001 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8011 ========================================================================
8013 VOID RTMPUpdateLegacyTxSetting(
8014 UCHAR fixed_tx_mode,
8015 PMAC_TABLE_ENTRY pEntry)
8017 HTTRANSMIT_SETTING TransmitSetting;
8019 if (fixed_tx_mode == FIXED_TXMODE_HT)
8022 TransmitSetting.word = 0;
8024 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8025 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8027 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8029 TransmitSetting.field.MODE = MODE_CCK;
8030 // CCK mode allow MCS 0~3
8031 if (TransmitSetting.field.MCS > MCS_3)
8032 TransmitSetting.field.MCS = MCS_3;
8036 TransmitSetting.field.MODE = MODE_OFDM;
8037 // OFDM mode allow MCS 0~7
8038 if (TransmitSetting.field.MCS > MCS_7)
8039 TransmitSetting.field.MCS = MCS_7;
8042 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8044 pEntry->HTPhyMode.word = TransmitSetting.word;
8045 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8046 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8050 #ifdef CONFIG_STA_SUPPORT
8052 ==========================================================================
8054 dynamic tune BBP R66 to find a balance between sensibility and
8057 IRQL = DISPATCH_LEVEL
8059 ==========================================================================
8061 VOID AsicStaBbpTuning(
8062 IN PRTMP_ADAPTER pAd)
8064 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8067 // 2860C did not support Fase CCA, therefore can't tune
8068 if (pAd->MACVersion == 0x28600100)
8074 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8077 if ((pAd->OpMode == OPMODE_STA)
8078 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8080 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8081 && (pAd->bPCIclkOff == FALSE))
8083 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8086 if (pAd->Antenna.field.RxPath > 1)
8087 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8089 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8091 if (pAd->LatchRfRegs.Channel <= 14)
8094 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8096 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8097 if (OrigR66Value != R66)
8099 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8104 R66 = 0x2E + GET_LNA_GAIN(pAd);
8105 if (OrigR66Value != R66)
8107 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8114 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8116 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8118 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8119 if (OrigR66Value != R66)
8121 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8126 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8127 if (OrigR66Value != R66)
8129 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8135 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8137 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8138 if (OrigR66Value != R66)
8140 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8145 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8146 if (OrigR66Value != R66)
8148 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8158 VOID AsicResetFromDMABusy(
8159 IN PRTMP_ADAPTER pAd)
8162 BOOLEAN bCtrl = FALSE;
8164 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8166 // Be sure restore link control value so we can write register.
8167 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8168 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8170 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8171 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8172 RTMPusecDelay(6000);
8173 pAd->bPCIclkOff = FALSE;
8177 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8179 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8181 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8182 // Reset DMA/CPU ring index
8183 RTMPRingCleanUp(pAd, QID_AC_BK);
8184 RTMPRingCleanUp(pAd, QID_AC_BE);
8185 RTMPRingCleanUp(pAd, QID_AC_VI);
8186 RTMPRingCleanUp(pAd, QID_AC_VO);
8187 RTMPRingCleanUp(pAd, QID_HCCA);
8188 RTMPRingCleanUp(pAd, QID_MGMT);
8189 RTMPRingCleanUp(pAd, QID_RX);
8192 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8194 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8196 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8197 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8198 RTMPPCIeLinkCtrlSetting(pAd, 3);
8200 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8201 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8202 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8206 IN PRTMP_ADAPTER pAd)
8208 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8210 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8211 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8212 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8214 // After hard-reset BBP, initialize all BBP values.
8215 NICRestoreBBPValue(pAd);
8216 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8220 IN PRTMP_ADAPTER pAd)
8224 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8225 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8227 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8229 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8231 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8235 IN PRTMP_ADAPTER pAd)
8237 ULONG Value1, Value2;
8240 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8241 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8244 // sum should be equals to 0xff, which is the total buffer size.
8245 if ((Value1 + Value2) < 0xff)
8247 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8248 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8250 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8252 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8254 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8257 #endif // CONFIG_STA_SUPPORT //
8259 VOID RTMPSetAGCInitValue(
8260 IN PRTMP_ADAPTER pAd,
8265 if (pAd->LatchRfRegs.Channel <= 14)
8267 R66 = 0x2E + GET_LNA_GAIN(pAd);
8268 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8272 if (BandWidth == BW_20)
8274 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8275 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8277 #ifdef DOT11_N_SUPPORT
8280 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8281 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8283 #endif // DOT11_N_SUPPORT //
8288 VOID AsicTurnOffRFClk(
8289 IN PRTMP_ADAPTER pAd,
8294 UINT32 R1 = 0, R2 = 0, R3 = 0;
8296 RTMP_RF_REGS *RFRegTable;
8298 RFRegTable = RF2850RegTable;
8300 switch (pAd->RfIcType)
8307 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8309 if (Channel == RFRegTable[index].Channel)
8311 R1 = RFRegTable[index].R1 & 0xffffdfff;
8312 R2 = RFRegTable[index].R2 & 0xfffbffff;
8313 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8315 RTMP_RF_IO_WRITE32(pAd, R1);
8316 RTMP_RF_IO_WRITE32(pAd, R2);
8318 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8319 // Set RF R2 bit18=0, R3 bit[18:19]=0
8320 //if (pAd->StaCfg.bRadio == FALSE)
8323 RTMP_RF_IO_WRITE32(pAd, R3);
8325 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8326 Channel, pAd->RfIcType, R2, R3));
8329 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8330 Channel, pAd->RfIcType, R2));
8342 VOID AsicTurnOnRFClk(
8343 IN PRTMP_ADAPTER pAd,
8348 UINT32 R1 = 0, R2 = 0, R3 = 0;
8350 RTMP_RF_REGS *RFRegTable;
8352 RFRegTable = RF2850RegTable;
8354 switch (pAd->RfIcType)
8361 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8363 if (Channel == RFRegTable[index].Channel)
8365 R3 = pAd->LatchRfRegs.R3;
8368 RTMP_RF_IO_WRITE32(pAd, R3);
8370 R1 = RFRegTable[index].R1;
8371 RTMP_RF_IO_WRITE32(pAd, R1);
8373 R2 = RFRegTable[index].R2;
8374 if (pAd->Antenna.field.TxPath == 1)
8376 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8379 if (pAd->Antenna.field.RxPath == 2)
8381 R2 |= 0x40; // write 1 to off Rxpath.
8383 else if (pAd->Antenna.field.RxPath == 1)
8385 R2 |= 0x20040; // write 1 to off RxPath
8387 RTMP_RF_IO_WRITE32(pAd, R2);
8398 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",