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 DOT11_N_SUPPORT
54 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
55 #endif // DOT11_N_SUPPORT //
57 UCHAR RateSwitchTable[] = {
58 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
59 0x11, 0x00, 0, 0, 0, // Initial used item after association
60 0x00, 0x00, 0, 40, 101,
61 0x01, 0x00, 1, 40, 50,
62 0x02, 0x00, 2, 35, 45,
63 0x03, 0x00, 3, 20, 45,
64 0x04, 0x21, 0, 30, 50,
65 0x05, 0x21, 1, 20, 50,
66 0x06, 0x21, 2, 20, 50,
67 0x07, 0x21, 3, 15, 50,
68 0x08, 0x21, 4, 15, 30,
69 0x09, 0x21, 5, 10, 25,
72 0x0c, 0x20, 12, 15, 30,
73 0x0d, 0x20, 13, 8, 20,
74 0x0e, 0x20, 14, 8, 20,
75 0x0f, 0x20, 15, 8, 25,
76 0x10, 0x22, 15, 8, 25,
94 UCHAR RateSwitchTable11B[] = {
95 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
96 0x04, 0x03, 0, 0, 0, // Initial used item after association
97 0x00, 0x00, 0, 40, 101,
98 0x01, 0x00, 1, 40, 50,
99 0x02, 0x00, 2, 35, 45,
100 0x03, 0x00, 3, 20, 45,
103 UCHAR RateSwitchTable11BG[] = {
104 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
105 0x0a, 0x00, 0, 0, 0, // Initial used item after association
106 0x00, 0x00, 0, 40, 101,
107 0x01, 0x00, 1, 40, 50,
108 0x02, 0x00, 2, 35, 45,
109 0x03, 0x00, 3, 20, 45,
110 0x04, 0x10, 2, 20, 35,
111 0x05, 0x10, 3, 16, 35,
112 0x06, 0x10, 4, 10, 25,
113 0x07, 0x10, 5, 16, 25,
114 0x08, 0x10, 6, 10, 25,
115 0x09, 0x10, 7, 10, 13,
118 UCHAR RateSwitchTable11G[] = {
119 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
120 0x08, 0x00, 0, 0, 0, // Initial used item after association
121 0x00, 0x10, 0, 20, 101,
122 0x01, 0x10, 1, 20, 35,
123 0x02, 0x10, 2, 20, 35,
124 0x03, 0x10, 3, 16, 35,
125 0x04, 0x10, 4, 10, 25,
126 0x05, 0x10, 5, 16, 25,
127 0x06, 0x10, 6, 10, 25,
128 0x07, 0x10, 7, 10, 13,
131 #ifdef DOT11_N_SUPPORT
132 UCHAR RateSwitchTable11N1S[] = {
133 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
134 0x09, 0x00, 0, 0, 0, // Initial used item after association
135 0x00, 0x21, 0, 30, 101,
136 0x01, 0x21, 1, 20, 50,
137 0x02, 0x21, 2, 20, 50,
138 0x03, 0x21, 3, 15, 50,
139 0x04, 0x21, 4, 15, 30,
140 0x05, 0x21, 5, 10, 25,
141 0x06, 0x21, 6, 8, 14,
142 0x07, 0x21, 7, 8, 14,
143 0x08, 0x23, 7, 8, 14,
146 UCHAR RateSwitchTable11N2S[] = {
147 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
148 0x0a, 0x00, 0, 0, 0, // Initial used item after association
149 0x00, 0x21, 0, 30, 101,
150 0x01, 0x21, 1, 20, 50,
151 0x02, 0x21, 2, 20, 50,
152 0x03, 0x21, 3, 15, 50,
153 0x04, 0x21, 4, 15, 30,
154 0x05, 0x20, 12, 15, 30,
155 0x06, 0x20, 13, 8, 20,
156 0x07, 0x20, 14, 8, 20,
157 0x08, 0x20, 15, 8, 25,
158 0x09, 0x22, 15, 8, 25,
161 UCHAR RateSwitchTable11N3S[] = {
162 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
163 0x0a, 0x00, 0, 0, 0, // Initial used item after association
164 0x00, 0x21, 0, 30, 101,
165 0x01, 0x21, 1, 20, 50,
166 0x02, 0x21, 2, 20, 50,
167 0x03, 0x21, 3, 15, 50,
168 0x04, 0x21, 4, 15, 30,
169 0x05, 0x20, 12, 15, 30,
170 0x06, 0x20, 13, 8, 20,
171 0x07, 0x20, 14, 8, 20,
172 0x08, 0x20, 15, 8, 25,
173 0x09, 0x22, 15, 8, 25,
176 UCHAR RateSwitchTable11N2SForABand[] = {
177 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
178 0x0b, 0x09, 0, 0, 0, // Initial used item after association
179 0x00, 0x21, 0, 30, 101,
180 0x01, 0x21, 1, 20, 50,
181 0x02, 0x21, 2, 20, 50,
182 0x03, 0x21, 3, 15, 50,
183 0x04, 0x21, 4, 15, 30,
184 0x05, 0x21, 5, 15, 30,
185 0x06, 0x20, 12, 15, 30,
186 0x07, 0x20, 13, 8, 20,
187 0x08, 0x20, 14, 8, 20,
188 0x09, 0x20, 15, 8, 25,
189 0x0a, 0x22, 15, 8, 25,
192 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
193 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
194 0x0b, 0x09, 0, 0, 0, // Initial used item after association
195 0x00, 0x21, 0, 30, 101,
196 0x01, 0x21, 1, 20, 50,
197 0x02, 0x21, 2, 20, 50,
198 0x03, 0x21, 3, 15, 50,
199 0x04, 0x21, 4, 15, 30,
200 0x05, 0x21, 5, 15, 30,
201 0x06, 0x20, 12, 15, 30,
202 0x07, 0x20, 13, 8, 20,
203 0x08, 0x20, 14, 8, 20,
204 0x09, 0x20, 15, 8, 25,
205 0x0a, 0x22, 15, 8, 25,
208 UCHAR RateSwitchTable11BGN1S[] = {
209 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
210 0x0d, 0x00, 0, 0, 0, // Initial used item after association
211 0x00, 0x00, 0, 40, 101,
212 0x01, 0x00, 1, 40, 50,
213 0x02, 0x00, 2, 35, 45,
214 0x03, 0x00, 3, 20, 45,
215 0x04, 0x21, 0, 30,101, //50
216 0x05, 0x21, 1, 20, 50,
217 0x06, 0x21, 2, 20, 50,
218 0x07, 0x21, 3, 15, 50,
219 0x08, 0x21, 4, 15, 30,
220 0x09, 0x21, 5, 10, 25,
221 0x0a, 0x21, 6, 8, 14,
222 0x0b, 0x21, 7, 8, 14,
223 0x0c, 0x23, 7, 8, 14,
226 UCHAR RateSwitchTable11BGN2S[] = {
227 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
228 0x0a, 0x00, 0, 0, 0, // Initial used item after association
229 0x00, 0x21, 0, 30,101, //50
230 0x01, 0x21, 1, 20, 50,
231 0x02, 0x21, 2, 20, 50,
232 0x03, 0x21, 3, 15, 50,
233 0x04, 0x21, 4, 15, 30,
234 0x05, 0x20, 12, 15, 30,
235 0x06, 0x20, 13, 8, 20,
236 0x07, 0x20, 14, 8, 20,
237 0x08, 0x20, 15, 8, 25,
238 0x09, 0x22, 15, 8, 25,
241 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
242 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
243 0x0a, 0x00, 0, 0, 0, // Initial used item after association
244 0x00, 0x21, 0, 30,101, //50
245 0x01, 0x21, 1, 20, 50,
246 0x02, 0x21, 2, 20, 50,
247 0x03, 0x21, 3, 20, 50,
248 0x04, 0x21, 4, 15, 50,
249 0x05, 0x20, 20, 15, 30,
250 0x06, 0x20, 21, 8, 20,
251 0x07, 0x20, 22, 8, 20,
252 0x08, 0x20, 23, 8, 25,
253 0x09, 0x22, 23, 8, 25,
256 UCHAR RateSwitchTable11BGN2SForABand[] = {
257 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
258 0x0b, 0x09, 0, 0, 0, // Initial used item after association
259 0x00, 0x21, 0, 30,101, //50
260 0x01, 0x21, 1, 20, 50,
261 0x02, 0x21, 2, 20, 50,
262 0x03, 0x21, 3, 15, 50,
263 0x04, 0x21, 4, 15, 30,
264 0x05, 0x21, 5, 15, 30,
265 0x06, 0x20, 12, 15, 30,
266 0x07, 0x20, 13, 8, 20,
267 0x08, 0x20, 14, 8, 20,
268 0x09, 0x20, 15, 8, 25,
269 0x0a, 0x22, 15, 8, 25,
272 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
273 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
274 0x0c, 0x09, 0, 0, 0, // Initial used item after association
275 0x00, 0x21, 0, 30,101, //50
276 0x01, 0x21, 1, 20, 50,
277 0x02, 0x21, 2, 20, 50,
278 0x03, 0x21, 3, 15, 50,
279 0x04, 0x21, 4, 15, 30,
280 0x05, 0x21, 5, 15, 30,
281 0x06, 0x21, 12, 15, 30,
282 0x07, 0x20, 20, 15, 30,
283 0x08, 0x20, 21, 8, 20,
284 0x09, 0x20, 22, 8, 20,
285 0x0a, 0x20, 23, 8, 25,
286 0x0b, 0x22, 23, 8, 25,
288 #endif // DOT11_N_SUPPORT //
290 PUCHAR ReasonString[] = {
292 /* 1 */ "Unspecified Reason",
293 /* 2 */ "Previous Auth no longer valid",
294 /* 3 */ "STA is leaving / has left",
295 /* 4 */ "DIS-ASSOC due to inactivity",
296 /* 5 */ "AP unable to hanle all associations",
297 /* 6 */ "class 2 error",
298 /* 7 */ "class 3 error",
299 /* 8 */ "STA is leaving / has left",
300 /* 9 */ "require auth before assoc/re-assoc",
304 /* 13 */ "invalid IE",
305 /* 14 */ "MIC error",
306 /* 15 */ "4-way handshake timeout",
307 /* 16 */ "2-way (group key) handshake timeout",
308 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
312 extern UCHAR OfdmRateToRxwiMCS[];
313 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
314 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
315 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
316 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
317 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
319 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
320 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
321 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
323 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
324 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
325 // clean environment.
326 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
327 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
329 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
330 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
332 UCHAR SsidIe = IE_SSID;
333 UCHAR SupRateIe = IE_SUPP_RATES;
334 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
335 #ifdef DOT11_N_SUPPORT
336 UCHAR HtCapIe = IE_HT_CAP;
337 UCHAR AddHtInfoIe = IE_ADD_HT;
338 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
339 #endif // DOT11_N_SUPPORT //
340 UCHAR ErpIe = IE_ERP;
341 UCHAR DsIe = IE_DS_PARM;
342 UCHAR TimIe = IE_TIM;
343 UCHAR WpaIe = IE_WPA;
344 UCHAR Wpa2Ie = IE_WPA2;
345 UCHAR IbssIe = IE_IBSS_PARM;
346 UCHAR Ccx2Ie = IE_CCX_V2;
348 extern UCHAR WPA_OUI[];
350 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
352 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
353 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
355 // Reset the RFIC setting to new series
356 RTMP_RF_REGS RF2850RegTable[] = {
357 // ch R1 R2 R3(TX0~4=0) R4
358 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
359 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
360 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
361 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
362 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
363 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
364 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
365 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
366 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
367 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
368 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
369 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
370 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
371 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
373 // 802.11 UNI / HyperLan 2
374 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
375 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
376 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
377 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
378 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
379 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
380 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
381 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
382 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
383 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
384 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
385 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
388 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
390 // 2008.04.30 modified
391 // The system team has AN to improve the EVM value
392 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
393 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
394 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
395 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
397 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
398 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
399 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
400 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
401 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
402 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
403 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
404 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
405 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
406 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
407 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
408 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
411 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
412 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
413 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
414 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
415 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
416 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
417 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
420 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
421 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
422 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
423 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
424 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
425 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
426 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
428 // still lack of MMAC(Japan) ch 34,38,42,46
430 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
432 FREQUENCY_ITEM FreqItems3020[] =
434 /**************************************************/
435 // ISM : 2.4 to 2.483 GHz //
436 /**************************************************/
438 /**************************************************/
439 //-CH---N-------R---K-----------
455 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
458 ==========================================================================
460 initialize the MLME task and its data structure (queue, spinlock,
461 timer, state machines).
466 always return NDIS_STATUS_SUCCESS
468 ==========================================================================
470 NDIS_STATUS MlmeInit(
471 IN PRTMP_ADAPTER pAd)
473 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
475 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
479 Status = MlmeQueueInit(&pAd->Mlme.Queue);
480 if(Status != NDIS_STATUS_SUCCESS)
483 pAd->Mlme.bRunning = FALSE;
484 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
486 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
488 BssTableInit(&pAd->ScanTab);
490 // init STA state machines
491 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
492 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
493 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
494 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
495 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
496 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
498 // Since we are using switch/case to implement it, the init is different from the above
499 // state machine init
500 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
503 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
505 // Init mlme periodic timer
506 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
508 // Set mlme periodic timer
509 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
511 // software-based RX Antenna diversity
512 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
514 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
516 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
518 // only PCIe cards need these two timers
519 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
520 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
525 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
531 ==========================================================================
533 main loop of the MLME
535 Mlme has to be initialized, and there are something inside the queue
537 This function is invoked from MPSetInformation and MPReceive;
538 This task guarantee only one MlmeHandler will run.
540 IRQL = DISPATCH_LEVEL
542 ==========================================================================
545 IN PRTMP_ADAPTER pAd)
547 MLME_QUEUE_ELEM *Elem = NULL;
549 // Only accept MLME and Frame from peer side, no other (control/data) frame should
550 // get into this state machine
552 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
553 if(pAd->Mlme.bRunning)
555 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
560 pAd->Mlme.bRunning = TRUE;
562 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
564 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
566 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
567 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
568 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
570 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
574 //From message type, determine which state machine I should drive
575 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
578 // if dequeue success
579 switch (Elem->Machine)
581 // STA state machines
582 case ASSOC_STATE_MACHINE:
583 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
585 case AUTH_STATE_MACHINE:
586 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
588 case AUTH_RSP_STATE_MACHINE:
589 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
591 case SYNC_STATE_MACHINE:
592 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
594 case MLME_CNTL_STATE_MACHINE:
595 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
597 case WPA_PSK_STATE_MACHINE:
598 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
600 case AIRONET_STATE_MACHINE:
601 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
603 case ACTION_STATE_MACHINE:
604 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
611 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
616 Elem->Occupied = FALSE;
621 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
625 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
626 pAd->Mlme.bRunning = FALSE;
627 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
631 ==========================================================================
633 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
635 Adapter - NIC Adapter pointer
637 The MLME task will no longer work properly
641 ==========================================================================
644 IN PRTMP_ADAPTER pAd)
648 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
650 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
652 // disable BEACON generation and other BEACON related hardware timers
653 AsicDisableSync(pAd);
656 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
658 // Cancel pending timers
659 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
660 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
661 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
662 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
663 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
664 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
665 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
667 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
668 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
672 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
673 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
677 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
680 RTMPSetLED(pAd, LED_HALT);
681 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
684 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
686 MlmeQueueDestroy(&pAd->Mlme.Queue);
687 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
689 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
692 VOID MlmeResetRalinkCounters(
693 IN PRTMP_ADAPTER pAd)
695 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
696 // clear all OneSecxxx counters.
697 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
698 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
699 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
700 pAd->RalinkCounters.OneSecRxOkCnt = 0;
701 pAd->RalinkCounters.OneSecTxFailCount = 0;
702 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
703 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
704 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
706 // TODO: for debug only. to be removed
707 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
708 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
709 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
710 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
711 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
712 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
713 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
714 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
715 pAd->RalinkCounters.OneSecTxDoneCount = 0;
716 pAd->RalinkCounters.OneSecRxCount = 0;
717 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
718 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
723 unsigned long rx_AMSDU;
724 unsigned long rx_Total;
727 ==========================================================================
729 This routine is executed periodically to -
730 1. Decide if it's a right time to turn on PwrMgmt bit of all
732 2. Calculate ChannelQuality based on statistics of the last
733 period, so that TX rate won't toggling very frequently between a
734 successful TX and a failed TX.
735 3. If the calculated ChannelQuality indicated current connection not
736 healthy, then a ROAMing attempt is tried here.
738 IRQL = DISPATCH_LEVEL
740 ==========================================================================
742 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
743 VOID MlmePeriodicExec(
744 IN PVOID SystemSpecific1,
745 IN PVOID FunctionContext,
746 IN PVOID SystemSpecific2,
747 IN PVOID SystemSpecific3)
750 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
753 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
754 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
755 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
756 if(pAd->StaCfg.WepStatus<2)
758 pAd->StaCfg.WpaSupplicantUP = 0;
762 pAd->StaCfg.WpaSupplicantUP = 1;
765 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
767 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
768 // Move code to here, because following code will return when radio is off
769 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
770 (pAd->StaCfg.bHardwareRadio == TRUE) &&
771 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
772 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
773 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
777 // Read GPIO pin2 as Hardware controlled radio state
778 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
781 pAd->StaCfg.bHwRadio = TRUE;
785 pAd->StaCfg.bHwRadio = FALSE;
787 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
789 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
790 if (pAd->StaCfg.bRadio == TRUE)
793 // Update extra information
794 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
799 // Update extra information
800 pAd->ExtraInfo = HW_RADIO_OFF;
806 // Do nothing if the driver is starting halt state.
807 // This might happen when timer already been fired before cancel timer with mlmehalt
808 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
809 fRTMP_ADAPTER_RADIO_OFF |
810 fRTMP_ADAPTER_RADIO_MEASUREMENT |
811 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
814 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
816 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
818 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
819 pAd->SameRxByteCount++;
822 pAd->SameRxByteCount = 0;
824 // If after BBP, still not work...need to check to reset PBF&MAC.
825 if (pAd->SameRxByteCount == 702)
827 pAd->SameRxByteCount = 0;
832 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
833 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
835 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
837 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
838 pAd->SameRxByteCount = 700;
843 // Update lastReceiveByteCount.
844 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
846 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
848 pAd->CheckDmaBusyCount = 0;
849 AsicResetFromDMABusy(pAd);
853 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
855 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
857 // Do nothing if monitor mode is on
861 if (pAd->Mlme.PeriodicRound & 0x1)
863 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
864 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
865 (STA_TGN_WIFI_ON(pAd)) &&
866 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
869 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
870 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
872 else if ((STA_TGN_WIFI_ON(pAd)) &&
873 ((pAd->MACVersion & 0xffff) == 0x0101))
875 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
876 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
881 pAd->bUpdateBcnCntDone = FALSE;
883 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
884 pAd->Mlme.PeriodicRound ++;
886 // execute every 500ms
887 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
889 // perform dynamic tx rate switching based on past TX history
890 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
892 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
894 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
895 MlmeDynamicTxRateSwitching(pAd);
899 // Normal 1 second Mlme PeriodicExec.
900 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
902 pAd->Mlme.OneSecPeriodicRound ++;
912 // Media status changed, report to NDIS
913 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
915 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
916 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
918 pAd->IndicateMediaState = NdisMediaStateConnected;
919 RTMP_IndicateMediaState(pAd);
924 pAd->IndicateMediaState = NdisMediaStateDisconnected;
925 RTMP_IndicateMediaState(pAd);
929 NdisGetSystemUpTime(&pAd->Mlme.Now32);
931 // add the most up-to-date h/w raw counters into software variable, so that
932 // the dynamic tuning mechanism below are based on most up-to-date information
933 NICUpdateRawCounters(pAd);
936 #ifdef DOT11_N_SUPPORT
937 // Need statistics after read counter. So put after NICUpdateRawCounters
938 ORIBATimerTimeout(pAd);
939 #endif // DOT11_N_SUPPORT //
942 // The time period for checking antenna is according to traffic
943 if (pAd->Mlme.bEnableAutoAntennaCheck)
945 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
946 pAd->RalinkCounters.OneSecTxRetryOkCount +
947 pAd->RalinkCounters.OneSecTxFailCount;
951 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
953 AsicEvaluateRxAnt(pAd);
958 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
960 AsicEvaluateRxAnt(pAd);
965 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
966 STAMlmePeriodicExec(pAd);
968 MlmeResetRalinkCounters(pAd);
970 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
972 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
974 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
975 // and sending CTS-to-self over and over.
976 // Software Patch Solution:
977 // 1. Polling debug state register 0x10F4 every one second.
978 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
979 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
983 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
984 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
986 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
988 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
990 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
995 RT28XX_MLME_HANDLER(pAd);
999 pAd->bUpdateBcnCntDone = FALSE;
1002 VOID STAMlmePeriodicExec(
1007 #ifdef WPA_SUPPLICANT_SUPPORT
1008 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1009 #endif // WPA_SUPPLICANT_SUPPORT //
1011 // WPA MIC error should block association attempt for 60 seconds
1012 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1013 pAd->StaCfg.bBlockAssoc = FALSE;
1017 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1018 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1019 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1020 if(pAd->StaCfg.WepStatus<2)
1022 pAd->StaCfg.WpaSupplicantUP = 0;
1026 pAd->StaCfg.WpaSupplicantUP = 1;
1029 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1031 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1033 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1035 pAd->PreMediaState = pAd->IndicateMediaState;
1038 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1039 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1040 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1041 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1042 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1043 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1045 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1050 AsicStaBbpTuning(pAd);
1052 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1053 pAd->RalinkCounters.OneSecTxRetryOkCount +
1054 pAd->RalinkCounters.OneSecTxFailCount;
1056 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1058 // update channel quality for Roaming and UI LinkQuality display
1059 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1062 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1063 // Radio is currently in noisy environment
1064 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1065 AsicAdjustTxPower(pAd);
1069 // Is PSM bit consistent with user power management policy?
1070 // This is the only place that will set PSM bit ON.
1071 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1072 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1074 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1076 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1077 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1078 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1080 RTMPSetAGCInitValue(pAd, BW_20);
1081 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1085 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1087 // When APSD is enabled, the period changes as 20 sec
1088 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1089 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1093 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1094 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1096 if (pAd->CommonCfg.bWmmCapable)
1097 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1099 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1104 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1106 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1107 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1108 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1110 // Lost AP, send disconnect & link down event
1111 LinkDown(pAd, FALSE);
1113 #ifdef WPA_SUPPLICANT_SUPPORT
1114 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1115 if (pAd->StaCfg.WpaSupplicantUP)
1117 union iwreq_data wrqu;
1118 //send disassociate event to wpa_supplicant
1119 memset(&wrqu, 0, sizeof(wrqu));
1120 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1121 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1123 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1124 #endif // WPA_SUPPLICANT_SUPPORT //
1126 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1128 union iwreq_data wrqu;
1129 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1130 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1132 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1134 MlmeAutoReconnectLastSSID(pAd);
1136 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1138 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1139 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1140 MlmeAutoReconnectLastSSID(pAd);
1143 // Add auto seamless roaming
1144 if (pAd->StaCfg.bFastRoaming)
1146 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1148 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));
1150 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1152 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1156 else if (ADHOC_ON(pAd))
1158 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1159 // the "TX BEACON competition" for the entire past 1 sec.
1160 // So that even when ASIC's BEACONgen engine been blocked
1161 // by peer's BEACON due to slower system clock, this STA still can send out
1162 // minimum BEACON to tell the peer I'm alive.
1163 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1164 // EnqueueBeaconFrame(pAd); // software send BEACON
1166 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1167 // restore outgoing BEACON to support B/G-mixed mode
1168 if ((pAd->CommonCfg.Channel <= 14) &&
1169 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1170 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1171 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1173 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1174 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1175 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1176 MlmeUpdateTxRates(pAd, FALSE, 0);
1177 MakeIbssBeacon(pAd); // re-build BEACON frame
1178 AsicEnableIbssSync(pAd); // copy to on-chip memory
1179 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1182 #ifdef DOT11_N_SUPPORT
1183 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1185 if ((pAd->StaCfg.AdhocBGJoined) &&
1186 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1188 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1189 pAd->StaCfg.AdhocBGJoined = FALSE;
1192 if ((pAd->StaCfg.Adhoc20NJoined) &&
1193 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1195 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1196 pAd->StaCfg.Adhoc20NJoined = FALSE;
1199 #endif // DOT11_N_SUPPORT //
1202 if ((pAd->CommonCfg.Channel > 14)
1203 && (pAd->CommonCfg.bIEEE80211H == 1)
1204 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1206 RadarDetectPeriodic(pAd);
1209 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1210 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1212 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1213 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1215 MLME_START_REQ_STRUCT StartReq;
1217 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1218 LinkDown(pAd, FALSE);
1220 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1221 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1222 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1225 else // no INFRA nor ADHOC connection
1228 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1229 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1230 goto SKIP_AUTO_SCAN_CONN;
1232 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1234 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1235 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1236 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1238 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1240 MLME_SCAN_REQ_STRUCT ScanReq;
1242 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1244 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1245 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1246 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1247 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1248 // Reset Missed scan number
1249 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1251 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1252 MlmeAutoReconnectLastSSID(pAd);
1254 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1256 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1259 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1263 MlmeAutoReconnectLastSSID(pAd);
1269 SKIP_AUTO_SCAN_CONN:
1271 #ifdef DOT11_N_SUPPORT
1272 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1274 pAd->MacTab.fAnyBASession = TRUE;
1275 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1277 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1279 pAd->MacTab.fAnyBASession = FALSE;
1280 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1282 #endif // DOT11_N_SUPPORT //
1289 IN PVOID SystemSpecific1,
1290 IN PVOID FunctionContext,
1291 IN PVOID SystemSpecific2,
1292 IN PVOID SystemSpecific3)
1295 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1297 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1298 RTMP_IndicateMediaState(pAd);
1299 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1302 // IRQL = DISPATCH_LEVEL
1304 IN PRTMP_ADAPTER pAd)
1306 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1307 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1309 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1311 MLME_CNTL_STATE_MACHINE,
1312 OID_802_11_BSSID_LIST_SCAN,
1315 RT28XX_MLME_HANDLER(pAd);
1319 // IRQL = DISPATCH_LEVEL
1320 VOID MlmeAutoReconnectLastSSID(
1321 IN PRTMP_ADAPTER pAd)
1325 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1326 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1327 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1329 NDIS_802_11_SSID OidSsid;
1330 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1331 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1333 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1335 MLME_CNTL_STATE_MACHINE,
1337 sizeof(NDIS_802_11_SSID),
1339 RT28XX_MLME_HANDLER(pAd);
1344 ==========================================================================
1345 Validate SSID for connection try and rescan purpose
1346 Valid SSID will have visible chars only.
1347 The valid length is from 0 to 32.
1348 IRQL = DISPATCH_LEVEL
1349 ==========================================================================
1351 BOOLEAN MlmeValidateSSID(
1357 if (SsidLen > MAX_LEN_OF_SSID)
1360 // Check each character value
1361 for (index = 0; index < SsidLen; index++)
1363 if (pSsid[index] < 0x20)
1371 VOID MlmeSelectTxRateTable(
1372 IN PRTMP_ADAPTER pAd,
1373 IN PMAC_TABLE_ENTRY pEntry,
1375 IN PUCHAR pTableSize,
1376 IN PUCHAR pInitTxRateIdx)
1380 // decide the rate table for tuning
1381 if (pAd->CommonCfg.TxRateTableSize > 0)
1383 *ppTable = RateSwitchTable;
1384 *pTableSize = RateSwitchTable[0];
1385 *pInitTxRateIdx = RateSwitchTable[1];
1390 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1392 #ifdef DOT11_N_SUPPORT
1393 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1394 !pAd->StaCfg.AdhocBOnlyJoined &&
1395 !pAd->StaCfg.AdhocBGJoined &&
1396 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1397 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1399 *ppTable = RateSwitchTable11N1S;
1400 *pTableSize = RateSwitchTable11N1S[0];
1401 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1404 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1405 !pAd->StaCfg.AdhocBOnlyJoined &&
1406 !pAd->StaCfg.AdhocBGJoined &&
1407 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1408 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1409 (pAd->Antenna.field.TxPath == 2))
1411 if (pAd->LatchRfRegs.Channel <= 14)
1413 *ppTable = RateSwitchTable11N2S;
1414 *pTableSize = RateSwitchTable11N2S[0];
1415 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1419 *ppTable = RateSwitchTable11N2SForABand;
1420 *pTableSize = RateSwitchTable11N2SForABand[0];
1421 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1426 #endif // DOT11_N_SUPPORT //
1427 if (pAd->CommonCfg.PhyMode == PHY_11B)
1429 *ppTable = RateSwitchTable11B;
1430 *pTableSize = RateSwitchTable11B[0];
1431 *pInitTxRateIdx = RateSwitchTable11B[1];
1434 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1436 // USe B Table when Only b-only Station in my IBSS .
1437 *ppTable = RateSwitchTable11B;
1438 *pTableSize = RateSwitchTable11B[0];
1439 *pInitTxRateIdx = RateSwitchTable11B[1];
1442 else if (pAd->LatchRfRegs.Channel <= 14)
1444 *ppTable = RateSwitchTable11BG;
1445 *pTableSize = RateSwitchTable11BG[0];
1446 *pInitTxRateIdx = RateSwitchTable11BG[1];
1451 *ppTable = RateSwitchTable11G;
1452 *pTableSize = RateSwitchTable11G[0];
1453 *pInitTxRateIdx = RateSwitchTable11G[1];
1459 #ifdef DOT11_N_SUPPORT
1460 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1461 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1463 *ppTable = RateSwitchTable11BGN1S;
1464 *pTableSize = RateSwitchTable11BGN1S[0];
1465 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1470 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1471 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1473 if (pAd->LatchRfRegs.Channel <= 14)
1475 *ppTable = RateSwitchTable11BGN2S;
1476 *pTableSize = RateSwitchTable11BGN2S[0];
1477 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1482 *ppTable = RateSwitchTable11BGN2SForABand;
1483 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1484 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1490 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1492 *ppTable = RateSwitchTable11N1S;
1493 *pTableSize = RateSwitchTable11N1S[0];
1494 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1499 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1501 if (pAd->LatchRfRegs.Channel <= 14)
1503 *ppTable = RateSwitchTable11N2S;
1504 *pTableSize = RateSwitchTable11N2S[0];
1505 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1509 *ppTable = RateSwitchTable11N2SForABand;
1510 *pTableSize = RateSwitchTable11N2SForABand[0];
1511 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1516 #endif // DOT11_N_SUPPORT //
1517 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1518 if ((pEntry->RateLen == 4)
1519 #ifdef DOT11_N_SUPPORT
1520 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1521 #endif // DOT11_N_SUPPORT //
1524 *ppTable = RateSwitchTable11B;
1525 *pTableSize = RateSwitchTable11B[0];
1526 *pInitTxRateIdx = RateSwitchTable11B[1];
1531 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1532 if ((pEntry->RateLen > 8)
1533 #ifdef DOT11_N_SUPPORT
1534 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1535 #endif // DOT11_N_SUPPORT //
1538 *ppTable = RateSwitchTable11BG;
1539 *pTableSize = RateSwitchTable11BG[0];
1540 *pInitTxRateIdx = RateSwitchTable11BG[1];
1545 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1546 if ((pEntry->RateLen == 8)
1547 #ifdef DOT11_N_SUPPORT
1548 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1549 #endif // DOT11_N_SUPPORT //
1552 *ppTable = RateSwitchTable11G;
1553 *pTableSize = RateSwitchTable11G[0];
1554 *pInitTxRateIdx = RateSwitchTable11G[1];
1558 #ifdef DOT11_N_SUPPORT
1559 #endif // DOT11_N_SUPPORT //
1561 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1563 #ifdef DOT11_N_SUPPORT
1564 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1565 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1566 #endif // DOT11_N_SUPPORT //
1568 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1570 *ppTable = RateSwitchTable11B;
1571 *pTableSize = RateSwitchTable11B[0];
1572 *pInitTxRateIdx = RateSwitchTable11B[1];
1574 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1576 *ppTable = RateSwitchTable11G;
1577 *pTableSize = RateSwitchTable11G[0];
1578 *pInitTxRateIdx = RateSwitchTable11G[1];
1583 *ppTable = RateSwitchTable11BG;
1584 *pTableSize = RateSwitchTable11BG[0];
1585 *pInitTxRateIdx = RateSwitchTable11BG[1];
1589 #ifdef DOT11_N_SUPPORT
1590 if (pAd->LatchRfRegs.Channel <= 14)
1592 if (pAd->CommonCfg.TxStream == 1)
1594 *ppTable = RateSwitchTable11N1S;
1595 *pTableSize = RateSwitchTable11N1S[0];
1596 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1597 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1601 *ppTable = RateSwitchTable11N2S;
1602 *pTableSize = RateSwitchTable11N2S[0];
1603 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1604 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1609 if (pAd->CommonCfg.TxStream == 1)
1611 *ppTable = RateSwitchTable11N1S;
1612 *pTableSize = RateSwitchTable11N1S[0];
1613 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1614 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1618 *ppTable = RateSwitchTable11N2SForABand;
1619 *pTableSize = RateSwitchTable11N2SForABand[0];
1620 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1621 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1624 #endif // DOT11_N_SUPPORT //
1625 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1626 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1632 ==========================================================================
1634 This routine checks if there're other APs out there capable for
1635 roaming. Caller should call this routine only when Link up in INFRA mode
1636 and channel quality is below CQI_GOOD_THRESHOLD.
1638 IRQL = DISPATCH_LEVEL
1641 ==========================================================================
1643 VOID MlmeCheckForRoaming(
1644 IN PRTMP_ADAPTER pAd,
1648 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1651 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1652 // put all roaming candidates into RoamTab, and sort in RSSI order
1653 BssTableInit(pRoamTab);
1654 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1656 pBss = &pAd->ScanTab.BssEntry[i];
1658 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1659 continue; // AP disappear
1660 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1661 continue; // RSSI too weak. forget it.
1662 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1663 continue; // skip current AP
1664 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1665 continue; // only AP with stronger RSSI is eligible for roaming
1667 // AP passing all above rules is put into roaming candidate table
1668 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1669 pRoamTab->BssNr += 1;
1672 if (pRoamTab->BssNr > 0)
1674 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1675 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1677 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1678 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1679 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1680 RT28XX_MLME_HANDLER(pAd);
1683 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1687 ==========================================================================
1689 This routine checks if there're other APs out there capable for
1690 roaming. Caller should call this routine only when link up in INFRA mode
1691 and channel quality is below CQI_GOOD_THRESHOLD.
1693 IRQL = DISPATCH_LEVEL
1696 ==========================================================================
1698 VOID MlmeCheckForFastRoaming(
1699 IN PRTMP_ADAPTER pAd,
1703 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1706 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1707 // put all roaming candidates into RoamTab, and sort in RSSI order
1708 BssTableInit(pRoamTab);
1709 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1711 pBss = &pAd->ScanTab.BssEntry[i];
1713 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1714 continue; // RSSI too weak. forget it.
1715 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1716 continue; // skip current AP
1717 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1718 continue; // skip different SSID
1719 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1720 continue; // skip AP without better RSSI
1722 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));
1723 // AP passing all above rules is put into roaming candidate table
1724 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1725 pRoamTab->BssNr += 1;
1728 if (pRoamTab->BssNr > 0)
1730 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1731 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1733 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1734 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1735 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1736 RT28XX_MLME_HANDLER(pAd);
1739 // Maybe site survey required
1742 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1744 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1745 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1746 pAd->StaCfg.ScanCnt = 2;
1747 pAd->StaCfg.LastScanTime = Now;
1752 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1756 ==========================================================================
1758 This routine calculates TxPER, RxPER of the past N-sec period. And
1759 according to the calculation result, ChannelQuality is calculated here
1760 to decide if current AP is still doing the job.
1762 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1764 StaCfg.ChannelQuality - 0..100
1766 IRQL = DISPATCH_LEVEL
1768 NOTE: This routine decide channle quality based on RX CRC error ratio.
1769 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1770 is performed right before this routine, so that this routine can decide
1771 channel quality based on the most up-to-date information
1772 ==========================================================================
1774 VOID MlmeCalculateChannelQuality(
1775 IN PRTMP_ADAPTER pAd,
1778 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1782 ULONG BeaconLostTime = BEACON_LOST_TIME;
1784 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1787 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1789 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1790 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1798 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1799 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1803 // calculate RX PER - don't take RxPER into consideration if too few sample
1805 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1809 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1812 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1814 if (INFRA_ON(pAd) &&
1815 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1816 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1818 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1819 pAd->Mlme.ChannelQuality = 0;
1826 else if (MaxRssi < -90)
1829 NorRssi = (MaxRssi + 90) * 2;
1831 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1832 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1833 TX_WEIGHTING * (100 - TxPRR) +
1834 RX_WEIGHTING* (100 - RxPER)) / 100;
1835 if (pAd->Mlme.ChannelQuality >= 100)
1836 pAd->Mlme.ChannelQuality = 100;
1842 IN PRTMP_ADAPTER pAd,
1843 IN PMAC_TABLE_ENTRY pEntry,
1844 IN PRTMP_TX_RATE_SWITCH pTxRate)
1846 UCHAR MaxMode = MODE_OFDM;
1848 #ifdef DOT11_N_SUPPORT
1849 MaxMode = MODE_HTGREENFIELD;
1851 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1852 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1854 #endif // DOT11_N_SUPPORT //
1855 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1857 if (pTxRate->CurrMCS < MCS_AUTO)
1858 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1860 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1861 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1865 // If peer adhoc is b-only mode, we can't send 11g rate.
1866 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1867 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1870 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1872 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1873 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1874 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1876 // Patch speed error in status page
1877 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1881 if (pTxRate->Mode <= MaxMode)
1882 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1884 #ifdef DOT11_N_SUPPORT
1885 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1886 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1888 #endif // DOT11_N_SUPPORT //
1889 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1891 #ifdef DOT11_N_SUPPORT
1892 // Reexam each bandwidth's SGI support.
1893 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1895 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1896 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1897 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1898 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1901 // Turn RTS/CTS rate to 6Mbps.
1902 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1904 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1905 if (pAd->MacTab.fAnyBASession)
1907 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1911 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1914 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1916 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1917 if (pAd->MacTab.fAnyBASession)
1919 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1923 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1926 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1928 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1931 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1933 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1935 #endif // DOT11_N_SUPPORT //
1937 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1938 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1939 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1940 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1941 #ifdef DOT11_N_SUPPORT
1942 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1943 pAd->WIFItestbed.bGreenField)
1944 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1945 #endif // DOT11_N_SUPPORT //
1948 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1952 ==========================================================================
1954 This routine calculates the acumulated TxPER of eaxh TxRate. And
1955 according to the calculation result, change CommonCfg.TxRate which
1956 is the stable TX Rate we expect the Radio situation could sustained.
1958 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1962 IRQL = DISPATCH_LEVEL
1965 call this routine every second
1966 ==========================================================================
1968 VOID MlmeDynamicTxRateSwitching(
1969 IN PRTMP_ADAPTER pAd)
1971 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1972 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1973 ULONG TxErrorRatio = 0;
1974 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1975 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1977 UCHAR TableSize = 0;
1978 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1979 CHAR Rssi, RssiOffset = 0;
1980 TX_STA_CNT1_STRUC StaTx1;
1981 TX_STA_CNT0_STRUC TxStaCnt0;
1982 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1983 MAC_TABLE_ENTRY *pEntry;
1985 /*if (pAd->Antenna.field.RxPath > 1)
1986 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
1988 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
1991 // walk through MAC table, see if need to change AP's TX rate toward each entry
1993 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1995 pEntry = &pAd->MacTab.Content[i];
1997 // check if this entry need to switch rate automatically
1998 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2001 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2003 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2005 // Update statistic counter
2006 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2007 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2008 pAd->bUpdateBcnCntDone = TRUE;
2009 TxRetransmit = StaTx1.field.TxRetransmit;
2010 TxSuccess = StaTx1.field.TxSuccess;
2011 TxFailCount = TxStaCnt0.field.TxFailCount;
2012 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2014 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2015 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2016 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2017 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2018 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2019 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2021 // if no traffic in the past 1-sec period, don't change TX rate,
2022 // but clear all bad history. because the bad history may affect the next
2023 // Chariot throughput test
2024 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2025 pAd->RalinkCounters.OneSecTxRetryOkCount +
2026 pAd->RalinkCounters.OneSecTxFailCount;
2029 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2033 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2035 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2036 pEntry->OneSecTxRetryOkCount +
2037 pEntry->OneSecTxFailCount;
2040 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2043 CurrRateIdx = pEntry->CurrTxRateIndex;
2045 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2047 if (CurrRateIdx >= TableSize)
2049 CurrRateIdx = TableSize - 1;
2052 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2053 // So need to sync here.
2054 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2055 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2056 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2060 // Need to sync Real Tx rate and our record.
2061 // Then return for next DRS.
2062 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2063 pEntry->CurrTxRateIndex = InitTxRateIdx;
2064 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2066 // reset all OneSecTx counters
2067 RESET_ONE_SEC_TX_CNT(pEntry);
2071 // decide the next upgrade rate and downgrade rate, if any
2072 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2074 UpRateIdx = CurrRateIdx + 1;
2075 DownRateIdx = CurrRateIdx -1;
2077 else if (CurrRateIdx == 0)
2079 UpRateIdx = CurrRateIdx + 1;
2080 DownRateIdx = CurrRateIdx;
2082 else if (CurrRateIdx == (TableSize - 1))
2084 UpRateIdx = CurrRateIdx;
2085 DownRateIdx = CurrRateIdx - 1;
2088 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2090 #ifdef DOT11_N_SUPPORT
2091 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2093 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2094 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2097 #endif // DOT11_N_SUPPORT //
2099 TrainUp = pCurrTxRate->TrainUp;
2100 TrainDown = pCurrTxRate->TrainDown;
2103 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2106 // Keep the last time TxRateChangeAction status.
2108 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2113 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2114 // (criteria copied from RT2500 for Netopia case)
2116 if (TxTotalCnt <= 15)
2120 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2121 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2122 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2123 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2125 // check the existence and index of each needed MCS
2126 while (idx < pTable[0])
2128 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2130 if (pCurrTxRate->CurrMCS == MCS_0)
2134 else if (pCurrTxRate->CurrMCS == MCS_1)
2138 else if (pCurrTxRate->CurrMCS == MCS_2)
2142 else if (pCurrTxRate->CurrMCS == MCS_3)
2146 else if (pCurrTxRate->CurrMCS == MCS_4)
2150 else if (pCurrTxRate->CurrMCS == MCS_5)
2154 else if (pCurrTxRate->CurrMCS == MCS_6)
2158 //else if (pCurrTxRate->CurrMCS == MCS_7)
2159 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2163 else if (pCurrTxRate->CurrMCS == MCS_12)
2167 else if (pCurrTxRate->CurrMCS == MCS_13)
2171 else if (pCurrTxRate->CurrMCS == MCS_14)
2175 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2176 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
2180 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2184 else if (pCurrTxRate->CurrMCS == MCS_21)
2188 else if (pCurrTxRate->CurrMCS == MCS_22)
2192 else if (pCurrTxRate->CurrMCS == MCS_23)
2199 if (pAd->LatchRfRegs.Channel <= 14)
2201 if (pAd->NicConfig2.field.ExternalLNAForG)
2212 if (pAd->NicConfig2.field.ExternalLNAForA)
2221 #ifdef DOT11_N_SUPPORT
2223 if ((pTable == RateSwitchTable11BGN3S) ||
2224 (pTable == RateSwitchTable11N3S) ||
2225 (pTable == RateSwitchTable))
2226 {// N mode with 3 stream // 3*3
2227 if (MCS23 && (Rssi >= -70))
2229 else if (MCS22 && (Rssi >= -72))
2231 else if (MCS21 && (Rssi >= -76))
2233 else if (MCS20 && (Rssi >= -78))
2235 else if (MCS4 && (Rssi >= -82))
2237 else if (MCS3 && (Rssi >= -84))
2239 else if (MCS2 && (Rssi >= -86))
2241 else if (MCS1 && (Rssi >= -88))
2246 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2247 {// N mode with 2 stream
2248 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2250 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2252 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2254 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2256 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2258 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2260 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2262 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2267 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2268 {// N mode with 1 stream
2269 if (MCS7 && (Rssi > (-72+RssiOffset)))
2271 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2273 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2275 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2277 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2279 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2281 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2287 #endif // DOT11_N_SUPPORT //
2289 if (MCS7 && (Rssi > -70))
2291 else if (MCS6 && (Rssi > -74))
2293 else if (MCS5 && (Rssi > -78))
2295 else if (MCS4 && (Rssi > -82))
2297 else if (MCS4 == 0) // for B-only mode
2299 else if (MCS3 && (Rssi > -85))
2301 else if (MCS2 && (Rssi > -87))
2303 else if (MCS1 && (Rssi > -90))
2310 pEntry->CurrTxRateIndex = TxRateIdx;
2311 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2312 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2315 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2316 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2317 pEntry->fLastSecAccordingRSSI = TRUE;
2318 // reset all OneSecTx counters
2319 RESET_ONE_SEC_TX_CNT(pEntry);
2324 if (pEntry->fLastSecAccordingRSSI == TRUE)
2326 pEntry->fLastSecAccordingRSSI = FALSE;
2327 pEntry->LastSecTxRateChangeAction = 0;
2328 // reset all OneSecTx counters
2329 RESET_ONE_SEC_TX_CNT(pEntry);
2336 BOOLEAN bTrainUpDown = FALSE;
2338 pEntry->CurrTxRateStableTime ++;
2340 // downgrade TX quality if PER >= Rate-Down threshold
2341 if (TxErrorRatio >= TrainDown)
2343 bTrainUpDown = TRUE;
2344 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2346 // upgrade TX quality if PER <= Rate-Up threshold
2347 else if (TxErrorRatio <= TrainUp)
2349 bTrainUpDown = TRUE;
2350 bUpgradeQuality = TRUE;
2351 if (pEntry->TxQuality[CurrRateIdx])
2352 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2354 if (pEntry->TxRateUpPenalty)
2355 pEntry->TxRateUpPenalty --;
2356 else if (pEntry->TxQuality[UpRateIdx])
2357 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2360 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2364 // perform DRS - consider TxRate Down first, then rate up.
2365 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2367 pEntry->CurrTxRateIndex = DownRateIdx;
2369 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2371 pEntry->CurrTxRateIndex = UpRateIdx;
2376 // if rate-up happen, clear all bad history of all TX rates
2377 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2379 pEntry->CurrTxRateStableTime = 0;
2380 pEntry->TxRateUpPenalty = 0;
2381 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2382 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2383 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2386 // For TxRate fast train up
2388 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2390 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2392 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2394 bTxRateChanged = TRUE;
2396 // if rate-down happen, only clear DownRate's bad history
2397 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2399 pEntry->CurrTxRateStableTime = 0;
2400 pEntry->TxRateUpPenalty = 0; // no penalty
2401 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2402 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2403 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2406 // For TxRate fast train down
2408 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2410 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2412 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2414 bTxRateChanged = TRUE;
2418 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2419 bTxRateChanged = FALSE;
2422 pEntry->LastTxOkCount = TxSuccess;
2424 // reset all OneSecTx counters
2425 RESET_ONE_SEC_TX_CNT(pEntry);
2427 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2428 if (bTxRateChanged && pNextTxRate)
2430 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2436 ========================================================================
2437 Routine Description:
2438 Station side, Auto TxRate faster train up timer call back function.
2441 SystemSpecific1 - Not used.
2442 FunctionContext - Pointer to our Adapter context.
2443 SystemSpecific2 - Not used.
2444 SystemSpecific3 - Not used.
2449 ========================================================================
2451 VOID StaQuickResponeForRateUpExec(
2452 IN PVOID SystemSpecific1,
2453 IN PVOID FunctionContext,
2454 IN PVOID SystemSpecific2,
2455 IN PVOID SystemSpecific3)
2457 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2458 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2460 ULONG TxErrorRatio = 0;
2461 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2462 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2464 UCHAR TableSize = 0;
2465 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2466 TX_STA_CNT1_STRUC StaTx1;
2467 TX_STA_CNT0_STRUC TxStaCnt0;
2469 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2470 MAC_TABLE_ENTRY *pEntry;
2473 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2476 // walk through MAC table, see if need to change AP's TX rate toward each entry
2478 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2480 pEntry = &pAd->MacTab.Content[i];
2482 // check if this entry need to switch rate automatically
2483 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2486 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2487 if (pAd->Antenna.field.TxPath > 1)
2488 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2490 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2492 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2494 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2496 // decide the next upgrade rate and downgrade rate, if any
2497 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2499 UpRateIdx = CurrRateIdx + 1;
2500 DownRateIdx = CurrRateIdx -1;
2502 else if (CurrRateIdx == 0)
2504 UpRateIdx = CurrRateIdx + 1;
2505 DownRateIdx = CurrRateIdx;
2507 else if (CurrRateIdx == (TableSize - 1))
2509 UpRateIdx = CurrRateIdx;
2510 DownRateIdx = CurrRateIdx - 1;
2513 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2515 #ifdef DOT11_N_SUPPORT
2516 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2518 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2519 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2522 #endif // DOT11_N_SUPPORT //
2524 TrainUp = pCurrTxRate->TrainUp;
2525 TrainDown = pCurrTxRate->TrainDown;
2528 if (pAd->MacTab.Size == 1)
2530 // Update statistic counter
2531 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2532 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2534 TxRetransmit = StaTx1.field.TxRetransmit;
2535 TxSuccess = StaTx1.field.TxSuccess;
2536 TxFailCount = TxStaCnt0.field.TxFailCount;
2537 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2539 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2540 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2541 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2542 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2543 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2544 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2547 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2551 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2552 pEntry->OneSecTxRetryOkCount +
2553 pEntry->OneSecTxFailCount;
2556 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2561 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2562 // (criteria copied from RT2500 for Netopia case)
2564 if (TxTotalCnt <= 12)
2566 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2567 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2569 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2571 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2572 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2574 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2576 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2579 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2585 ULONG OneSecTxNoRetryOKRationCount;
2587 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2592 // downgrade TX quality if PER >= Rate-Down threshold
2593 if (TxErrorRatio >= TrainDown)
2595 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2598 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2600 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2602 // perform DRS - consider TxRate Down first, then rate up.
2603 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2605 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2607 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2608 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2613 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2615 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2619 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2621 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2626 // if rate-up happen, clear all bad history of all TX rates
2627 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2629 pAd->DrsCounters.TxRateUpPenalty = 0;
2630 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2631 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2633 // if rate-down happen, only clear DownRate's bad history
2634 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2636 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2638 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2639 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2640 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2644 bTxRateChanged = FALSE;
2647 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2648 if (bTxRateChanged && pNextTxRate)
2650 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2656 ==========================================================================
2658 This routine is executed periodically inside MlmePeriodicExec() after
2659 association with an AP.
2660 It checks if StaCfg.Psm is consistent with user policy (recorded in
2661 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2662 there're some conditions to consider:
2663 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2664 the time when Mibss==TRUE
2665 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2666 if outgoing traffic available in TxRing or MgmtRing.
2668 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2670 IRQL = DISPATCH_LEVEL
2672 ==========================================================================
2674 VOID MlmeCheckPsmChange(
2675 IN PRTMP_ADAPTER pAd,
2681 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2682 // 2. user wants either MAX_PSP or FAST_PSP
2683 // 3. but current psm is not in PWR_SAVE
2684 // 4. CNTL state machine is not doing SCANning
2685 // 5. no TX SUCCESS event for the past 1-sec period
2686 #ifdef NDIS51_MINIPORT
2687 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2688 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2691 PowerMode = pAd->StaCfg.WindowsPowerMode;
2693 if (INFRA_ON(pAd) &&
2694 (PowerMode != Ndis802_11PowerModeCAM) &&
2695 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2696 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2698 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2699 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2700 MlmeSetPsmBit(pAd, PWR_SAVE);
2701 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2703 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2707 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2712 // IRQL = PASSIVE_LEVEL
2713 // IRQL = DISPATCH_LEVEL
2715 IN PRTMP_ADAPTER pAd,
2718 AUTO_RSP_CFG_STRUC csr4;
2720 pAd->StaCfg.Psm = psm;
2721 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2722 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2723 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2724 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2727 // IRQL = DISPATCH_LEVEL
2728 VOID MlmeSetTxPreamble(
2729 IN PRTMP_ADAPTER pAd,
2730 IN USHORT TxPreamble)
2732 AUTO_RSP_CFG_STRUC csr4;
2735 // Always use Long preamble before verifiation short preamble functionality works well.
2736 // Todo: remove the following line if short preamble functionality works
2738 //TxPreamble = Rt802_11PreambleLong;
2740 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2741 if (TxPreamble == Rt802_11PreambleLong)
2743 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2744 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2745 csr4.field.AutoResponderPreamble = 0;
2749 // NOTE: 1Mbps should always use long preamble
2750 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2751 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2752 csr4.field.AutoResponderPreamble = 1;
2755 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2759 ==========================================================================
2761 Update basic rate bitmap
2762 ==========================================================================
2765 VOID UpdateBasicRateBitmap(
2766 IN PRTMP_ADAPTER pAdapter)
2769 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2770 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2771 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2772 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2773 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2776 /* if A mode, always use fix BasicRateBitMap */
2777 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2778 if (pAdapter->CommonCfg.Channel > 14)
2779 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2782 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2784 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2788 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2794 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2796 if (bitmap & (1 << i))
2798 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2800 if (sup_p[j] == rate[i])
2805 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2807 if (ext_p[j] == rate[i])
2813 } /* End of UpdateBasicRateBitmap */
2815 // IRQL = PASSIVE_LEVEL
2816 // IRQL = DISPATCH_LEVEL
2817 // bLinkUp is to identify the inital link speed.
2818 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2819 VOID MlmeUpdateTxRates(
2820 IN PRTMP_ADAPTER pAd,
2825 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2826 UCHAR MinSupport = RATE_54;
2827 ULONG BasicRateBitmap = 0;
2828 UCHAR CurrBasicRate = RATE_1;
2829 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2830 PHTTRANSMIT_SETTING pHtPhy = NULL;
2831 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2832 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2833 BOOLEAN *auto_rate_cur_p;
2834 UCHAR HtMcs = MCS_AUTO;
2836 // find max desired rate
2837 UpdateBasicRateBitmap(pAd);
2840 auto_rate_cur_p = NULL;
2841 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2843 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2845 case 2: Rate = RATE_1; num++; break;
2846 case 4: Rate = RATE_2; num++; break;
2847 case 11: Rate = RATE_5_5; num++; break;
2848 case 22: Rate = RATE_11; num++; break;
2849 case 12: Rate = RATE_6; num++; break;
2850 case 18: Rate = RATE_9; num++; break;
2851 case 24: Rate = RATE_12; num++; break;
2852 case 36: Rate = RATE_18; num++; break;
2853 case 48: Rate = RATE_24; num++; break;
2854 case 72: Rate = RATE_36; num++; break;
2855 case 96: Rate = RATE_48; num++; break;
2856 case 108: Rate = RATE_54; num++; break;
2857 //default: Rate = RATE_1; break;
2859 if (MaxDesire < Rate) MaxDesire = Rate;
2862 //===========================================================================
2863 //===========================================================================
2864 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2866 pHtPhy = &pAd->StaCfg.HTPhyMode;
2867 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2868 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2870 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2871 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2873 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2874 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2875 (MaxDesire > RATE_11))
2877 MaxDesire = RATE_11;
2881 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2882 pMinHtPhy->word = 0;
2883 pMaxHtPhy->word = 0;
2886 // Auto rate switching is enabled only if more than one DESIRED RATES are
2887 // specified; otherwise disabled
2890 *auto_rate_cur_p = FALSE;
2894 *auto_rate_cur_p = TRUE;
2898 if (HtMcs != MCS_AUTO)
2900 *auto_rate_cur_p = FALSE;
2904 *auto_rate_cur_p = TRUE;
2908 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2910 pSupRate = &pAd->StaActive.SupRate[0];
2911 pExtRate = &pAd->StaActive.ExtRate[0];
2912 SupRateLen = pAd->StaActive.SupRateLen;
2913 ExtRateLen = pAd->StaActive.ExtRateLen;
2917 pSupRate = &pAd->CommonCfg.SupRate[0];
2918 pExtRate = &pAd->CommonCfg.ExtRate[0];
2919 SupRateLen = pAd->CommonCfg.SupRateLen;
2920 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2923 // find max supported rate
2924 for (i=0; i<SupRateLen; i++)
2926 switch (pSupRate[i] & 0x7f)
2928 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2929 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2930 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2931 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2932 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2933 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2934 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2935 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2936 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2937 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2938 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2939 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2940 default: Rate = RATE_1; break;
2942 if (MaxSupport < Rate) MaxSupport = Rate;
2944 if (MinSupport > Rate) MinSupport = Rate;
2947 for (i=0; i<ExtRateLen; i++)
2949 switch (pExtRate[i] & 0x7f)
2951 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2952 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2953 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2954 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2955 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2956 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2957 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2958 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2959 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2960 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2961 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2962 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2963 default: Rate = RATE_1; break;
2965 if (MaxSupport < Rate) MaxSupport = Rate;
2967 if (MinSupport > Rate) MinSupport = Rate;
2970 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2972 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2973 // the DURATION field of outgoing uniicast DATA/MGMT frame
2974 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2976 if (BasicRateBitmap & (0x01 << i))
2977 CurrBasicRate = (UCHAR)i;
2978 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2981 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2982 // max tx rate = min {max desire rate, max supported rate}
2983 if (MaxSupport < MaxDesire)
2984 pAd->CommonCfg.MaxTxRate = MaxSupport;
2986 pAd->CommonCfg.MaxTxRate = MaxDesire;
2988 pAd->CommonCfg.MinTxRate = MinSupport;
2989 if (*auto_rate_cur_p)
2993 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2994 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2996 if (bLinkUp == TRUE)
2997 pAd->CommonCfg.TxRate = RATE_24;
2999 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3002 pAd->CommonCfg.TxRate = RATE_11;
3004 pAd->CommonCfg.TxRate = RATE_24;
3006 // should never exceed MaxTxRate (consider 11B-only mode)
3007 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3008 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3010 pAd->CommonCfg.TxRateIndex = 0;
3014 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3015 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3016 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3018 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3019 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3020 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3021 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3024 if (pAd->CommonCfg.TxRate <= RATE_11)
3026 pMaxHtPhy->field.MODE = MODE_CCK;
3027 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3028 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3032 pMaxHtPhy->field.MODE = MODE_OFDM;
3033 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3034 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3035 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3037 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3040 pHtPhy->word = (pMaxHtPhy->word);
3041 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3043 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3044 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3045 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3049 switch (pAd->CommonCfg.PhyMode)
3051 case PHY_11BG_MIXED:
3053 #ifdef DOT11_N_SUPPORT
3054 case PHY_11BGN_MIXED:
3055 #endif // DOT11_N_SUPPORT //
3056 pAd->CommonCfg.MlmeRate = RATE_1;
3057 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3058 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3059 pAd->CommonCfg.RtsRate = RATE_11;
3063 #ifdef DOT11_N_SUPPORT
3064 case PHY_11AGN_MIXED:
3065 case PHY_11GN_MIXED:
3067 case PHY_11AN_MIXED:
3069 #endif // DOT11_N_SUPPORT //
3070 pAd->CommonCfg.MlmeRate = RATE_6;
3071 pAd->CommonCfg.RtsRate = RATE_6;
3072 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3073 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3075 case PHY_11ABG_MIXED:
3076 #ifdef DOT11_N_SUPPORT
3077 case PHY_11ABGN_MIXED:
3078 #endif // DOT11_N_SUPPORT //
3079 if (pAd->CommonCfg.Channel <= 14)
3081 pAd->CommonCfg.MlmeRate = RATE_1;
3082 pAd->CommonCfg.RtsRate = RATE_1;
3083 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3084 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3088 pAd->CommonCfg.MlmeRate = RATE_6;
3089 pAd->CommonCfg.RtsRate = RATE_6;
3090 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3091 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3095 pAd->CommonCfg.MlmeRate = RATE_6;
3096 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3097 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3098 pAd->CommonCfg.RtsRate = RATE_1;
3102 // Keep Basic Mlme Rate.
3104 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3105 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3106 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3108 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3109 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3112 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3113 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3114 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3115 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3116 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3117 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3118 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 ));
3121 #ifdef DOT11_N_SUPPORT
3123 ==========================================================================
3125 This function update HT Rate setting.
3126 Input Wcid value is valid for 2 case :
3127 1. it's used for Station in infra mode that copy AP rate to Mactable.
3128 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3130 IRQL = DISPATCH_LEVEL
3132 ==========================================================================
3134 VOID MlmeUpdateHtTxRates(
3135 IN PRTMP_ADAPTER pAd,
3138 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3140 RT_HT_CAPABILITY *pRtHtCap = NULL;
3141 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3144 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3145 PHTTRANSMIT_SETTING pHtPhy = NULL;
3146 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3147 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3148 BOOLEAN *auto_rate_cur_p;
3150 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3152 auto_rate_cur_p = NULL;
3154 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3156 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3157 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3158 pHtPhy = &pAd->StaCfg.HTPhyMode;
3159 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3160 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3162 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3165 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3167 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3170 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3171 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3172 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3173 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3174 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3175 pMaxHtPhy->field.STBC = STBC_USE;
3177 pMaxHtPhy->field.STBC = STBC_NONE;
3181 if (pDesireHtPhy->bHtEnable == FALSE)
3184 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3185 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3186 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3187 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3188 pMaxHtPhy->field.STBC = STBC_USE;
3190 pMaxHtPhy->field.STBC = STBC_NONE;
3193 // Decide MAX ht rate.
3194 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3195 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3197 pMaxHtPhy->field.MODE = MODE_HTMIX;
3199 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3200 pMaxHtPhy->field.BW = BW_40;
3202 pMaxHtPhy->field.BW = BW_20;
3204 if (pMaxHtPhy->field.BW == BW_20)
3205 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3207 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3209 for (i=23; i>=0; i--) // 3*3
3212 bitmask = (1<<(i-(j*8)));
3214 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3216 pMaxHtPhy->field.MCS = i;
3224 // Copy MIN ht rate. rt2860???
3225 pMinHtPhy->field.BW = BW_20;
3226 pMinHtPhy->field.MCS = 0;
3227 pMinHtPhy->field.STBC = 0;
3228 pMinHtPhy->field.ShortGI = 0;
3229 //If STA assigns fixed rate. update to fixed here.
3230 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3232 if (pDesireHtPhy->MCSSet[4] != 0)
3234 pMaxHtPhy->field.MCS = 32;
3235 pMinHtPhy->field.MCS = 32;
3236 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3239 for (i=23; (CHAR)i >= 0; i--) // 3*3
3242 bitmask = (1<<(i-(j*8)));
3243 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3245 pMaxHtPhy->field.MCS = i;
3246 pMinHtPhy->field.MCS = i;
3255 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3256 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3257 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3258 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3259 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3261 // use default now. rt2860
3262 if (pDesireHtPhy->MCSSet[0] != 0xff)
3263 *auto_rate_cur_p = FALSE;
3265 *auto_rate_cur_p = TRUE;
3267 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3268 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3269 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3270 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3272 #endif // DOT11_N_SUPPORT //
3274 // IRQL = DISPATCH_LEVEL
3276 IN PRTMP_ADAPTER pAd)
3278 RT28XX_MLME_RADIO_OFF(pAd);
3281 // IRQL = DISPATCH_LEVEL
3283 IN PRTMP_ADAPTER pAd)
3285 RT28XX_MLME_RADIO_ON(pAd);
3288 // ===========================================================================================
3290 // ===========================================================================================
3293 /*! \brief initialize BSS table
3294 * \param p_tab pointer to the table
3299 IRQL = PASSIVE_LEVEL
3300 IRQL = DISPATCH_LEVEL
3309 Tab->BssOverlapNr = 0;
3310 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3312 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3313 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3317 #ifdef DOT11_N_SUPPORT
3319 IN PRTMP_ADAPTER pAd,
3324 Tab->numAsOriginator = 0;
3325 Tab->numAsRecipient = 0;
3326 NdisAllocateSpinLock(&pAd->BATabLock);
3327 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3329 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3330 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3332 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3334 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3337 #endif // DOT11_N_SUPPORT //
3339 /*! \brief search the BSS table by SSID
3340 * \param p_tab pointer to the bss table
3341 * \param ssid SSID string
3342 * \return index of the table, BSS_NOT_FOUND if not in the table
3345 * \note search by sequential search
3347 IRQL = DISPATCH_LEVEL
3350 ULONG BssTableSearch(
3357 for (i = 0; i < Tab->BssNr; i++)
3360 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3361 // We should distinguish this case.
3363 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3364 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3365 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3370 return (ULONG)BSS_NOT_FOUND;
3373 ULONG BssSsidTableSearch(
3382 for (i = 0; i < Tab->BssNr; i++)
3385 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3386 // We should distinguish this case.
3388 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3389 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3390 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3391 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3396 return (ULONG)BSS_NOT_FOUND;
3399 ULONG BssTableSearchWithSSID(
3408 for (i = 0; i < Tab->BssNr; i++)
3410 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3411 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3412 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3413 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3414 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3415 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3420 return (ULONG)BSS_NOT_FOUND;
3423 // IRQL = DISPATCH_LEVEL
3424 VOID BssTableDeleteEntry(
3425 IN OUT BSS_TABLE *Tab,
3431 for (i = 0; i < Tab->BssNr; i++)
3433 if ((Tab->BssEntry[i].Channel == Channel) &&
3434 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3436 for (j = i; j < Tab->BssNr - 1; j++)
3438 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3440 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3447 #ifdef DOT11_N_SUPPORT
3449 ========================================================================
3450 Routine Description:
3451 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3454 // IRQL = DISPATCH_LEVEL
3455 ========================================================================
3457 VOID BATableDeleteORIEntry(
3458 IN OUT PRTMP_ADAPTER pAd,
3459 IN BA_ORI_ENTRY *pBAORIEntry)
3462 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3464 NdisAcquireSpinLock(&pAd->BATabLock);
3465 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3467 pAd->BATable.numAsOriginator -= 1;
3468 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3469 // Erase Bitmap flag.
3471 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3472 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3473 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3474 pBAORIEntry->Token = 1;
3475 // Not clear Sequence here.
3476 NdisReleaseSpinLock(&pAd->BATabLock);
3479 #endif // DOT11_N_SUPPORT //
3487 IRQL = DISPATCH_LEVEL
3491 IN PRTMP_ADAPTER pAd,
3492 OUT BSS_ENTRY *pBss,
3497 IN USHORT BeaconPeriod,
3498 IN PCF_PARM pCfParm,
3500 IN USHORT CapabilityInfo,
3502 IN UCHAR SupRateLen,
3504 IN UCHAR ExtRateLen,
3505 IN HT_CAPABILITY_IE *pHtCapability,
3506 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3507 IN UCHAR HtCapabilityLen,
3508 IN UCHAR AddHtInfoLen,
3509 IN UCHAR NewExtChanOffset,
3512 IN LARGE_INTEGER TimeStamp,
3514 IN PEDCA_PARM pEdcaParm,
3515 IN PQOS_CAPABILITY_PARM pQosCapability,
3516 IN PQBSS_LOAD_PARM pQbssLoad,
3517 IN USHORT LengthVIE,
3518 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3520 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3521 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3525 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3526 // Or send beacon /probe response with SSID len matching real SSID length,
3527 // but SSID is all zero. such as "00-00-00-00" with length 4.
3528 // We have to prevent this case overwrite correct table
3529 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3531 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3532 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3533 pBss->SsidLen = SsidLen;
3539 pBss->BssType = BssType;
3540 pBss->BeaconPeriod = BeaconPeriod;
3541 if (BssType == BSS_INFRA)
3543 if (pCfParm->bValid)
3545 pBss->CfpCount = pCfParm->CfpCount;
3546 pBss->CfpPeriod = pCfParm->CfpPeriod;
3547 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3548 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3553 pBss->AtimWin = AtimWin;
3556 pBss->CapabilityInfo = CapabilityInfo;
3557 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3558 // Combine with AuthMode, they will decide the connection methods.
3559 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3560 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3561 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3562 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3564 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3565 pBss->SupRateLen = SupRateLen;
3566 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3567 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3568 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3569 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3570 pBss->NewExtChanOffset = NewExtChanOffset;
3571 pBss->ExtRateLen = ExtRateLen;
3572 pBss->Channel = Channel;
3573 pBss->CentralChannel = Channel;
3575 // Update CkipFlag. if not exists, the value is 0x0
3576 pBss->CkipFlag = CkipFlag;
3578 // New for microsoft Fixed IEs
3579 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3580 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3581 pBss->FixIEs.Capabilities = CapabilityInfo;
3583 // New for microsoft Variable IEs
3586 pBss->VarIELen = LengthVIE;
3587 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3594 pBss->AddHtInfoLen = 0;
3595 pBss->HtCapabilityLen = 0;
3596 #ifdef DOT11_N_SUPPORT
3597 if (HtCapabilityLen> 0)
3599 pBss->HtCapabilityLen = HtCapabilityLen;
3600 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3601 if (AddHtInfoLen > 0)
3603 pBss->AddHtInfoLen = AddHtInfoLen;
3604 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3606 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3608 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3610 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3612 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3616 #endif // DOT11_N_SUPPORT //
3618 BssCipherParse(pBss);
3622 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3624 pBss->EdcaParm.bValid = FALSE;
3626 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3628 pBss->QosCapability.bValid = FALSE;
3630 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3632 pBss->QbssLoad.bValid = FALSE;
3634 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3640 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3641 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3643 pEid = (PEID_STRUCT) pVIE;
3645 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3650 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3652 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3654 pBss->WpaIE.IELen = 0;
3657 pBss->WpaIE.IELen = pEid->Len + 2;
3658 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3662 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3664 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3666 pBss->RsnIE.IELen = 0;
3669 pBss->RsnIE.IELen = pEid->Len + 2;
3670 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3674 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3675 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3681 * \brief insert an entry into the bss table
3682 * \param p_tab The BSS table
3683 * \param Bssid BSSID
3685 * \param ssid_len Length of SSID
3687 * \param beacon_period
3694 * \param channel_idx
3698 * \note If SSID is identical, the old entry will be replaced by the new one
3700 IRQL = DISPATCH_LEVEL
3703 ULONG BssTableSetEntry(
3704 IN PRTMP_ADAPTER pAd,
3710 IN USHORT BeaconPeriod,
3713 IN USHORT CapabilityInfo,
3715 IN UCHAR SupRateLen,
3717 IN UCHAR ExtRateLen,
3718 IN HT_CAPABILITY_IE *pHtCapability,
3719 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3720 IN UCHAR HtCapabilityLen,
3721 IN UCHAR AddHtInfoLen,
3722 IN UCHAR NewExtChanOffset,
3725 IN LARGE_INTEGER TimeStamp,
3727 IN PEDCA_PARM pEdcaParm,
3728 IN PQOS_CAPABILITY_PARM pQosCapability,
3729 IN PQBSS_LOAD_PARM pQbssLoad,
3730 IN USHORT LengthVIE,
3731 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3735 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3736 if (Idx == BSS_NOT_FOUND)
3738 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3741 // It may happen when BSS Table was full.
3742 // The desired AP will not be added into BSS Table
3743 // In this case, if we found the desired AP then overwrite BSS Table.
3745 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3747 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3748 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3750 Idx = Tab->BssOverlapNr;
3751 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3752 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3753 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3754 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3760 return BSS_NOT_FOUND;
3764 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3765 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3766 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3771 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3772 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3773 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3779 // IRQL = DISPATCH_LEVEL
3780 VOID BssTableSsidSort(
3781 IN PRTMP_ADAPTER pAd,
3782 OUT BSS_TABLE *OutTab,
3787 BssTableInit(OutTab);
3789 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3791 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3792 BOOLEAN bIsHiddenApIncluded = FALSE;
3794 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3795 (pAd->MlmeAux.Channel > 14) &&
3796 RadarChannelCheck(pAd, pInBss->Channel))
3800 bIsHiddenApIncluded = TRUE;
3803 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3804 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3806 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3807 #ifdef DOT11_N_SUPPORT
3808 // 2.4G/5G N only mode
3809 if ((pInBss->HtCapabilityLen == 0) &&
3810 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3812 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3815 #endif // DOT11_N_SUPPORT //
3818 // Check the Authmode first
3819 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3821 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3822 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3826 // Check cipher suite, AP must have more secured cipher than station setting
3827 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3829 // If it's not mixed mode, we should only let BSS pass with the same encryption
3830 if (pInBss->WPA.bMixMode == FALSE)
3831 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3834 // check group cipher
3835 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3836 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3837 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3840 // check pairwise cipher, skip if none matched
3841 // If profile set to AES, let it pass without question.
3842 // If profile set to TKIP, we must find one mateched
3843 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3844 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3845 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3848 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3850 // If it's not mixed mode, we should only let BSS pass with the same encryption
3851 if (pInBss->WPA2.bMixMode == FALSE)
3852 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3855 // check group cipher
3856 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3857 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3858 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3861 // check pairwise cipher, skip if none matched
3862 // If profile set to AES, let it pass without question.
3863 // If profile set to TKIP, we must find one mateched
3864 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3865 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3866 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3870 // Bss Type matched, SSID matched.
3871 // We will check wepstatus for qualification Bss
3872 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3874 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3876 // For the SESv2 case, we will not qualify WepStatus.
3882 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3883 // It definitely will fail. So, skip it.
3884 // CCX also require not even try to connect it!!
3888 #ifdef DOT11_N_SUPPORT
3889 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3890 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3891 if ((pInBss->CentralChannel != pInBss->Channel) &&
3892 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3894 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3896 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3898 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3902 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3908 #endif // DOT11_N_SUPPORT //
3910 // copy matching BSS from InTab to OutTab
3911 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3915 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3917 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3920 #ifdef DOT11_N_SUPPORT
3921 // 2.4G/5G N only mode
3922 if ((pInBss->HtCapabilityLen == 0) &&
3923 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3925 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3928 #endif // DOT11_N_SUPPORT //
3931 // Check the Authmode first
3932 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3934 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3935 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3939 // Check cipher suite, AP must have more secured cipher than station setting
3940 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3942 // If it's not mixed mode, we should only let BSS pass with the same encryption
3943 if (pInBss->WPA.bMixMode == FALSE)
3944 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3947 // check group cipher
3948 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3951 // check pairwise cipher, skip if none matched
3952 // If profile set to AES, let it pass without question.
3953 // If profile set to TKIP, we must find one mateched
3954 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3955 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3956 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3959 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3961 // If it's not mixed mode, we should only let BSS pass with the same encryption
3962 if (pInBss->WPA2.bMixMode == FALSE)
3963 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3966 // check group cipher
3967 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3970 // check pairwise cipher, skip if none matched
3971 // If profile set to AES, let it pass without question.
3972 // If profile set to TKIP, we must find one mateched
3973 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3974 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3975 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3979 // Bss Type matched, SSID matched.
3980 // We will check wepstatus for qualification Bss
3981 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3984 #ifdef DOT11_N_SUPPORT
3985 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3986 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3987 if ((pInBss->CentralChannel != pInBss->Channel) &&
3988 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3990 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3992 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3994 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3997 #endif // DOT11_N_SUPPORT //
3999 // copy matching BSS from InTab to OutTab
4000 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4005 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4009 BssTableSortByRssi(OutTab);
4013 // IRQL = DISPATCH_LEVEL
4014 VOID BssTableSortByRssi(
4015 IN OUT BSS_TABLE *OutTab)
4020 for (i = 0; i < OutTab->BssNr - 1; i++)
4022 for (j = i+1; j < OutTab->BssNr; j++)
4024 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4026 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4027 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4028 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4034 VOID BssCipherParse(
4035 IN OUT PBSS_ENTRY pBss)
4039 PRSN_IE_HEADER_STRUCT pRsnHeader;
4040 PCIPHER_SUITE_STRUCT pCipher;
4041 PAKM_SUITE_STRUCT pAKM;
4044 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4047 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4051 pBss->WepStatus = Ndis802_11WEPEnabled;
4055 pBss->WepStatus = Ndis802_11WEPDisabled;
4057 // Set default to disable & open authentication before parsing variable IE
4058 pBss->AuthMode = Ndis802_11AuthModeOpen;
4059 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4062 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4063 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4064 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4065 pBss->WPA.RsnCapability = 0;
4066 pBss->WPA.bMixMode = FALSE;
4068 // Init WPA2 setting
4069 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4070 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4071 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4072 pBss->WPA2.RsnCapability = 0;
4073 pBss->WPA2.bMixMode = FALSE;
4076 Length = (INT) pBss->VarIELen;
4080 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4081 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4082 pEid = (PEID_STRUCT) pTmp;
4086 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4087 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4093 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4094 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4095 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4096 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4099 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4100 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4101 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4104 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4105 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4106 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4112 // if Cisco IE_WPA, break
4115 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4120 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4122 // if unsupported vendor specific IE
4125 // Skip OUI, version, and multicast suite
4126 // This part should be improved in the future when AP supported multiple cipher suite.
4127 // For now, it's OK since almost all APs have fixed cipher suite supported.
4128 // pTmp = (PUCHAR) pEid->Octet;
4131 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4139 // Parse group cipher
4143 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4146 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4149 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4152 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4157 // number of unicast suite
4160 // skip all unicast cipher suites
4161 //Count = *(PUSHORT) pTmp;
4162 Count = (pTmp[1]<<8) + pTmp[0];
4163 pTmp += sizeof(USHORT);
4165 // Parsing all unicast cipher suite
4170 TmpCipher = Ndis802_11WEPDisabled;
4174 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4175 TmpCipher = Ndis802_11Encryption1Enabled;
4178 TmpCipher = Ndis802_11Encryption2Enabled;
4181 TmpCipher = Ndis802_11Encryption3Enabled;
4186 if (TmpCipher > pBss->WPA.PairCipher)
4188 // Move the lower cipher suite to PairCipherAux
4189 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4190 pBss->WPA.PairCipher = TmpCipher;
4194 pBss->WPA.PairCipherAux = TmpCipher;
4200 // 4. get AKM suite counts
4201 //Count = *(PUSHORT) pTmp;
4202 Count = (pTmp[1]<<8) + pTmp[0];
4203 pTmp += sizeof(USHORT);
4209 // Set AP support WPA mode
4210 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4211 pBss->AuthMode = Ndis802_11AuthModeWPA;
4213 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4216 // Set AP support WPA mode
4217 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4218 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4220 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4227 // Fixed for WPA-None
4228 if (pBss->BssType == BSS_ADHOC)
4230 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4231 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4232 pBss->WepStatus = pBss->WPA.GroupCipher;
4233 // Patched bugs for old driver
4234 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4235 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4238 pBss->WepStatus = pBss->WPA.PairCipher;
4240 // Check the Pair & Group, if different, turn on mixed mode flag
4241 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4242 pBss->WPA.bMixMode = TRUE;
4247 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4249 // 0. Version must be 1
4250 if (le2cpu16(pRsnHeader->Version) != 1)
4252 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4254 // 1. Check group cipher
4255 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4256 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4259 // Parse group cipher
4260 switch (pCipher->Type)
4263 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4266 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4269 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4272 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4277 // set to correct offset for next parsing
4278 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4280 // 2. Get pairwise cipher counts
4281 //Count = *(PUSHORT) pTmp;
4282 Count = (pTmp[1]<<8) + pTmp[0];
4283 pTmp += sizeof(USHORT);
4285 // 3. Get pairwise cipher
4286 // Parsing all unicast cipher suite
4290 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4291 TmpCipher = Ndis802_11WEPDisabled;
4292 switch (pCipher->Type)
4295 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4296 TmpCipher = Ndis802_11Encryption1Enabled;
4299 TmpCipher = Ndis802_11Encryption2Enabled;
4302 TmpCipher = Ndis802_11Encryption3Enabled;
4307 if (TmpCipher > pBss->WPA2.PairCipher)
4309 // Move the lower cipher suite to PairCipherAux
4310 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4311 pBss->WPA2.PairCipher = TmpCipher;
4315 pBss->WPA2.PairCipherAux = TmpCipher;
4317 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4321 // 4. get AKM suite counts
4322 //Count = *(PUSHORT) pTmp;
4323 Count = (pTmp[1]<<8) + pTmp[0];
4324 pTmp += sizeof(USHORT);
4326 // 5. Get AKM ciphers
4327 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4328 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4334 // Set AP support WPA mode
4335 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4336 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4338 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4341 // Set AP support WPA mode
4342 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4343 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4345 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4350 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4352 // Fixed for WPA-None
4353 if (pBss->BssType == BSS_ADHOC)
4355 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4356 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4357 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4358 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4359 pBss->WepStatus = pBss->WPA.GroupCipher;
4360 // Patched bugs for old driver
4361 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4362 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4364 pBss->WepStatus = pBss->WPA2.PairCipher;
4366 // 6. Get RSN capability
4367 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4368 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4369 pTmp += sizeof(USHORT);
4371 // Check the Pair & Group, if different, turn on mixed mode flag
4372 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4373 pBss->WPA2.bMixMode = TRUE;
4379 Length -= (pEid->Len + 2);
4383 // ===========================================================================================
4385 // ===========================================================================================
4387 /*! \brief generates a random mac address value for IBSS BSSID
4388 * \param Addr the bssid location
4393 VOID MacAddrRandomBssid(
4394 IN PRTMP_ADAPTER pAd,
4399 for (i = 0; i < MAC_ADDR_LEN; i++)
4401 pAddr[i] = RandomByte(pAd);
4404 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4407 /*! \brief init the management mac frame header
4408 * \param p_hdr mac header
4409 * \param subtype subtype of the frame
4410 * \param p_ds destination address, don't care if it is a broadcast address
4412 * \pre the station has the following information in the pAd->StaCfg
4416 * \note this function initializes the following field
4418 IRQL = PASSIVE_LEVEL
4419 IRQL = DISPATCH_LEVEL
4422 VOID MgtMacHeaderInit(
4423 IN PRTMP_ADAPTER pAd,
4424 IN OUT PHEADER_802_11 pHdr80211,
4430 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4432 pHdr80211->FC.Type = BTYPE_MGMT;
4433 pHdr80211->FC.SubType = SubType;
4434 pHdr80211->FC.ToDs = ToDs;
4435 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4437 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4438 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4440 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4443 // ===========================================================================================
4445 // ===========================================================================================
4447 /*!***************************************************************************
4448 * This routine build an outgoing frame, and fill all information specified
4449 * in argument list to the frame body. The actual frame size is the summation
4452 * Buffer - pointer to a pre-allocated memory segment
4453 * args - a list of <int arg_size, arg> pairs.
4454 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4455 * function will FAIL!!!
4457 * Size of the buffer
4459 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4461 IRQL = PASSIVE_LEVEL
4462 IRQL = DISPATCH_LEVEL
4464 ****************************************************************************/
4465 ULONG MakeOutgoingFrame(
4467 OUT ULONG *FrameLen, ...)
4474 // calculates the total length
4476 va_start(Args, FrameLen);
4479 leng = va_arg(Args, int);
4480 if (leng == END_OF_ARGS)
4484 p = va_arg(Args, PVOID);
4485 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4486 TotLeng = TotLeng + leng;
4489 va_end(Args); /* clean up */
4490 *FrameLen = TotLeng;
4494 // ===========================================================================================
4496 // ===========================================================================================
4498 /*! \brief Initialize The MLME Queue, used by MLME Functions
4499 * \param *Queue The MLME Queue
4500 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4503 * \note Because this is done only once (at the init stage), no need to be locked
4505 IRQL = PASSIVE_LEVEL
4508 NDIS_STATUS MlmeQueueInit(
4509 IN MLME_QUEUE *Queue)
4513 NdisAllocateSpinLock(&Queue->Lock);
4519 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4521 Queue->Entry[i].Occupied = FALSE;
4522 Queue->Entry[i].MsgLen = 0;
4523 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4526 return NDIS_STATUS_SUCCESS;
4529 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4530 * \param *Queue The MLME Queue
4531 * \param Machine The State Machine Id
4532 * \param MsgType The Message Type
4533 * \param MsgLen The Message length
4534 * \param *Msg The message pointer
4535 * \return TRUE if enqueue is successful, FALSE if the queue is full
4538 * \note The message has to be initialized
4540 IRQL = PASSIVE_LEVEL
4541 IRQL = DISPATCH_LEVEL
4544 BOOLEAN MlmeEnqueue(
4545 IN PRTMP_ADAPTER pAd,
4552 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4554 // Do nothing if the driver is starting halt state.
4555 // This might happen when timer already been fired before cancel timer with mlmehalt
4556 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4559 // First check the size, it MUST not exceed the mlme queue size
4560 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4562 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4566 if (MlmeQueueFull(Queue))
4571 NdisAcquireSpinLock(&(Queue->Lock));
4575 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4580 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4581 Queue->Entry[Tail].Occupied = TRUE;
4582 Queue->Entry[Tail].Machine = Machine;
4583 Queue->Entry[Tail].MsgType = MsgType;
4584 Queue->Entry[Tail].MsgLen = MsgLen;
4588 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4591 NdisReleaseSpinLock(&(Queue->Lock));
4595 /*! \brief This function is used when Recv gets a MLME message
4596 * \param *Queue The MLME Queue
4597 * \param TimeStampHigh The upper 32 bit of timestamp
4598 * \param TimeStampLow The lower 32 bit of timestamp
4599 * \param Rssi The receiving RSSI strength
4600 * \param MsgLen The length of the message
4601 * \param *Msg The message pointer
4602 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4606 IRQL = DISPATCH_LEVEL
4609 BOOLEAN MlmeEnqueueForRecv(
4610 IN PRTMP_ADAPTER pAd,
4612 IN ULONG TimeStampHigh,
4613 IN ULONG TimeStampLow,
4622 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4624 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4626 // Do nothing if the driver is starting halt state.
4627 // This might happen when timer already been fired before cancel timer with mlmehalt
4628 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4630 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4634 // First check the size, it MUST not exceed the mlme queue size
4635 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4637 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4641 if (MlmeQueueFull(Queue))
4646 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4648 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4650 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4655 // OK, we got all the informations, it is time to put things into queue
4656 NdisAcquireSpinLock(&(Queue->Lock));
4660 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4664 Queue->Entry[Tail].Occupied = TRUE;
4665 Queue->Entry[Tail].Machine = Machine;
4666 Queue->Entry[Tail].MsgType = MsgType;
4667 Queue->Entry[Tail].MsgLen = MsgLen;
4668 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4669 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4670 Queue->Entry[Tail].Rssi0 = Rssi0;
4671 Queue->Entry[Tail].Rssi1 = Rssi1;
4672 Queue->Entry[Tail].Rssi2 = Rssi2;
4673 Queue->Entry[Tail].Signal = Signal;
4674 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4676 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4680 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4683 NdisReleaseSpinLock(&(Queue->Lock));
4685 RT28XX_MLME_HANDLER(pAd);
4691 /*! \brief Dequeue a message from the MLME Queue
4692 * \param *Queue The MLME Queue
4693 * \param *Elem The message dequeued from MLME Queue
4694 * \return TRUE if the Elem contains something, FALSE otherwise
4698 IRQL = DISPATCH_LEVEL
4701 BOOLEAN MlmeDequeue(
4702 IN MLME_QUEUE *Queue,
4703 OUT MLME_QUEUE_ELEM **Elem)
4705 NdisAcquireSpinLock(&(Queue->Lock));
4706 *Elem = &(Queue->Entry[Queue->Head]);
4709 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4713 NdisReleaseSpinLock(&(Queue->Lock));
4717 // IRQL = DISPATCH_LEVEL
4718 VOID MlmeRestartStateMachine(
4719 IN PRTMP_ADAPTER pAd)
4721 MLME_QUEUE_ELEM *Elem = NULL;
4724 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4726 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4727 if(pAd->Mlme.bRunning)
4729 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4734 pAd->Mlme.bRunning = TRUE;
4736 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4738 // Remove all Mlme queues elements
4739 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4741 //From message type, determine which state machine I should drive
4742 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4744 // free MLME element
4745 Elem->Occupied = FALSE;
4750 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4754 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4756 // Cancel all timer events
4757 // Be careful to cancel new added timer
4758 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4759 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4760 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4761 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4762 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4763 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4766 // Change back to original channel in case of doing scan
4767 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4768 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4770 // Resume MSDU which is turned off durning scan
4771 RTMPResumeMsduTransmission(pAd);
4773 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4775 // Set all state machines back IDLE
4776 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4777 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4778 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4779 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4780 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4781 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4784 // Remove running state
4785 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4786 pAd->Mlme.bRunning = FALSE;
4787 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4790 /*! \brief test if the MLME Queue is empty
4791 * \param *Queue The MLME Queue
4792 * \return TRUE if the Queue is empty, FALSE otherwise
4796 IRQL = DISPATCH_LEVEL
4799 BOOLEAN MlmeQueueEmpty(
4800 IN MLME_QUEUE *Queue)
4804 NdisAcquireSpinLock(&(Queue->Lock));
4805 Ans = (Queue->Num == 0);
4806 NdisReleaseSpinLock(&(Queue->Lock));
4811 /*! \brief test if the MLME Queue is full
4812 * \param *Queue The MLME Queue
4813 * \return TRUE if the Queue is empty, FALSE otherwise
4817 IRQL = PASSIVE_LEVEL
4818 IRQL = DISPATCH_LEVEL
4821 BOOLEAN MlmeQueueFull(
4822 IN MLME_QUEUE *Queue)
4826 NdisAcquireSpinLock(&(Queue->Lock));
4827 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4828 NdisReleaseSpinLock(&(Queue->Lock));
4833 /*! \brief The destructor of MLME Queue
4838 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4840 IRQL = PASSIVE_LEVEL
4843 VOID MlmeQueueDestroy(
4844 IN MLME_QUEUE *pQueue)
4846 NdisAcquireSpinLock(&(pQueue->Lock));
4850 NdisReleaseSpinLock(&(pQueue->Lock));
4851 NdisFreeSpinLock(&(pQueue->Lock));
4854 /*! \brief To substitute the message type if the message is coming from external
4855 * \param pFrame The frame received
4856 * \param *Machine The state machine
4857 * \param *MsgType the message type for the state machine
4858 * \return TRUE if the substitution is successful, FALSE otherwise
4862 IRQL = DISPATCH_LEVEL
4865 BOOLEAN MsgTypeSubst(
4866 IN PRTMP_ADAPTER pAd,
4867 IN PFRAME_802_11 pFrame,
4875 // Pointer to start of data frames including SNAP header
4876 pData = (PUCHAR) pFrame + LENGTH_802_11;
4878 // The only data type will pass to this function is EAPOL frame
4879 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4881 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4883 // Cisco Aironet SNAP header
4884 *Machine = AIRONET_STATE_MACHINE;
4885 *MsgType = MT2_AIRONET_MSG;
4889 *Machine = WPA_PSK_STATE_MACHINE;
4890 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4891 return(WpaMsgTypeSubst(EAPType, MsgType));
4895 switch (pFrame->Hdr.FC.SubType)
4897 case SUBTYPE_ASSOC_REQ:
4898 *Machine = ASSOC_STATE_MACHINE;
4899 *MsgType = MT2_PEER_ASSOC_REQ;
4901 case SUBTYPE_ASSOC_RSP:
4902 *Machine = ASSOC_STATE_MACHINE;
4903 *MsgType = MT2_PEER_ASSOC_RSP;
4905 case SUBTYPE_REASSOC_REQ:
4906 *Machine = ASSOC_STATE_MACHINE;
4907 *MsgType = MT2_PEER_REASSOC_REQ;
4909 case SUBTYPE_REASSOC_RSP:
4910 *Machine = ASSOC_STATE_MACHINE;
4911 *MsgType = MT2_PEER_REASSOC_RSP;
4913 case SUBTYPE_PROBE_REQ:
4914 *Machine = SYNC_STATE_MACHINE;
4915 *MsgType = MT2_PEER_PROBE_REQ;
4917 case SUBTYPE_PROBE_RSP:
4918 *Machine = SYNC_STATE_MACHINE;
4919 *MsgType = MT2_PEER_PROBE_RSP;
4921 case SUBTYPE_BEACON:
4922 *Machine = SYNC_STATE_MACHINE;
4923 *MsgType = MT2_PEER_BEACON;
4926 *Machine = SYNC_STATE_MACHINE;
4927 *MsgType = MT2_PEER_ATIM;
4929 case SUBTYPE_DISASSOC:
4930 *Machine = ASSOC_STATE_MACHINE;
4931 *MsgType = MT2_PEER_DISASSOC_REQ;
4934 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4935 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4936 if (Seq == 1 || Seq == 3)
4938 *Machine = AUTH_RSP_STATE_MACHINE;
4939 *MsgType = MT2_PEER_AUTH_ODD;
4941 else if (Seq == 2 || Seq == 4)
4943 *Machine = AUTH_STATE_MACHINE;
4944 *MsgType = MT2_PEER_AUTH_EVEN;
4951 case SUBTYPE_DEAUTH:
4952 *Machine = AUTH_RSP_STATE_MACHINE;
4953 *MsgType = MT2_PEER_DEAUTH;
4955 case SUBTYPE_ACTION:
4956 *Machine = ACTION_STATE_MACHINE;
4957 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4958 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4960 *MsgType = MT2_ACT_INVALID;
4964 *MsgType = (pFrame->Octet[0]&0x7F);
4975 // ===========================================================================================
4977 // ===========================================================================================
4979 /*! \brief Initialize the state machine.
4980 * \param *S pointer to the state machine
4981 * \param Trans State machine transition function
4982 * \param StNr number of states
4983 * \param MsgNr number of messages
4984 * \param DefFunc default function, when there is invalid state/message combination
4985 * \param InitState initial state of the state machine
4986 * \param Base StateMachine base, internal use only
4987 * \pre p_sm should be a legal pointer
4990 IRQL = PASSIVE_LEVEL
4993 VOID StateMachineInit(
4994 IN STATE_MACHINE *S,
4995 IN STATE_MACHINE_FUNC Trans[],
4998 IN STATE_MACHINE_FUNC DefFunc,
5004 // set number of states and messages
5009 S->TransFunc = Trans;
5011 // init all state transition to default function
5012 for (i = 0; i < StNr; i++)
5014 for (j = 0; j < MsgNr; j++)
5016 S->TransFunc[i * MsgNr + j] = DefFunc;
5020 // set the starting state
5021 S->CurrState = InitState;
5024 /*! \brief This function fills in the function pointer into the cell in the state machine
5025 * \param *S pointer to the state machine
5027 * \param Msg incoming message
5028 * \param f the function to be executed when (state, message) combination occurs at the state machine
5029 * \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
5032 IRQL = PASSIVE_LEVEL
5035 VOID StateMachineSetAction(
5036 IN STATE_MACHINE *S,
5039 IN STATE_MACHINE_FUNC Func)
5043 MsgIdx = Msg - S->Base;
5045 if (St < S->NrState && MsgIdx < S->NrMsg)
5047 // boundary checking before setting the action
5048 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5052 /*! \brief This function does the state transition
5053 * \param *Adapter the NIC adapter pointer
5054 * \param *S the state machine
5055 * \param *Elem the message to be executed
5058 IRQL = DISPATCH_LEVEL
5061 VOID StateMachinePerformAction(
5062 IN PRTMP_ADAPTER pAd,
5063 IN STATE_MACHINE *S,
5064 IN MLME_QUEUE_ELEM *Elem)
5066 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5070 ==========================================================================
5072 The drop function, when machine executes this, the message is simply
5073 ignored. This function does nothing, the message is freed in
5074 StateMachinePerformAction()
5075 ==========================================================================
5078 IN PRTMP_ADAPTER pAd,
5079 IN MLME_QUEUE_ELEM *Elem)
5083 // ===========================================================================================
5085 // ===========================================================================================
5088 ==========================================================================
5091 IRQL = PASSIVE_LEVEL
5093 ==========================================================================
5096 IN PRTMP_ADAPTER pAd,
5100 pAd->Mlme.ShiftReg = 1;
5102 pAd->Mlme.ShiftReg = Seed;
5106 ==========================================================================
5108 ==========================================================================
5111 IN PRTMP_ADAPTER pAd)
5118 if (pAd->Mlme.ShiftReg == 0)
5119 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5121 for (i = 0; i < 8; i++)
5123 if (pAd->Mlme.ShiftReg & 0x00000001)
5125 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5130 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5133 R = (R << 1) | Result;
5139 VOID AsicUpdateAutoFallBackTable(
5140 IN PRTMP_ADAPTER pAd,
5141 IN PUCHAR pRateTable)
5144 HT_FBK_CFG0_STRUC HtCfg0;
5145 HT_FBK_CFG1_STRUC HtCfg1;
5146 LG_FBK_CFG0_STRUC LgCfg0;
5147 LG_FBK_CFG1_STRUC LgCfg1;
5148 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5150 // set to initial value
5151 HtCfg0.word = 0x65432100;
5152 HtCfg1.word = 0xedcba988;
5153 LgCfg0.word = 0xedcba988;
5154 LgCfg1.word = 0x00002100;
5156 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5157 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5159 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5160 switch (pCurrTxRate->Mode)
5166 switch(pCurrTxRate->CurrMCS)
5169 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5172 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5175 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5178 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5181 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5184 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5187 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5190 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5195 #ifdef DOT11_N_SUPPORT
5199 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5201 switch(pCurrTxRate->CurrMCS)
5204 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5207 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5210 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5213 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5216 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5219 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5222 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5225 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5228 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5231 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5234 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5237 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5240 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5243 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5246 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5249 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5252 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5257 #endif // DOT11_N_SUPPORT //
5260 pNextTxRate = pCurrTxRate;
5263 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5264 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5265 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5266 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5270 ========================================================================
5272 Routine Description:
5273 Set MAC register value according operation mode.
5274 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5275 If MM or GF mask is not set, those passing argument doesn't not take effect.
5277 Operation mode meaning:
5278 = 0 : Pure HT, no preotection.
5279 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5280 = 0x10: No Transmission in 40M is protected.
5281 = 0x11: Transmission in both 40M and 20M shall be protected
5283 we should choose not to use GF. But still set correct ASIC registers.
5284 ========================================================================
5286 VOID AsicUpdateProtect(
5287 IN PRTMP_ADAPTER pAd,
5288 IN USHORT OperationMode,
5290 IN BOOLEAN bDisableBGProtect,
5291 IN BOOLEAN bNonGFExist)
5293 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5299 #ifdef DOT11_N_SUPPORT
5300 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5305 if (pAd->BATable.numAsOriginator)
5308 // enable the RTS/CTS to avoid channel collision
5310 SetMask = ALLN_SETPROTECT;
5313 #endif // DOT11_N_SUPPORT //
5315 // Config ASIC RTS threshold register
5316 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5317 MacReg &= 0xFF0000FF;
5319 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5321 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5323 #ifdef DOT11_N_SUPPORT
5324 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5325 #endif // DOT11_N_SUPPORT //
5326 (pAd->CommonCfg.bAggregationCapable == TRUE))
5327 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5329 MacReg |= (0x1000 << 8);
5333 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5337 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5339 // Initial common protection settings
5340 RTMPZeroMemory(Protect, sizeof(Protect));
5343 ProtCfg.field.TxopAllowGF40 = 1;
5344 ProtCfg.field.TxopAllowGF20 = 1;
5345 ProtCfg.field.TxopAllowMM40 = 1;
5346 ProtCfg.field.TxopAllowMM20 = 1;
5347 ProtCfg.field.TxopAllowOfdm = 1;
5348 ProtCfg.field.TxopAllowCck = 1;
5349 ProtCfg.field.RTSThEn = 1;
5350 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5352 // update PHY mode and rate
5353 if (pAd->CommonCfg.Channel > 14)
5354 ProtCfg.field.ProtectRate = 0x4000;
5355 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5357 // Handle legacy(B/G) protection
5358 if (bDisableBGProtect)
5360 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5361 ProtCfg.field.ProtectCtrl = 0;
5362 Protect[0] = ProtCfg.word;
5363 Protect[1] = ProtCfg.word;
5367 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5368 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5369 Protect[0] = ProtCfg.word;
5370 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5371 Protect[1] = ProtCfg.word;
5374 #ifdef DOT11_N_SUPPORT
5375 // Decide HT frame protection.
5376 if ((SetMask & ALLN_SETPROTECT) != 0)
5378 switch(OperationMode)
5382 // 1.All STAs in the BSS are 20/40 MHz HT
5383 // 2. in ai 20/40MHz BSS
5384 // 3. all STAs are 20MHz in a 20MHz BSS
5385 // Pure HT. no protection.
5389 // PROT_TXOP(25:20) -- 010111
5390 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5391 // PROT_CTRL(17:16) -- 00 (None)
5392 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5393 Protect[2] = 0x01744004;
5397 // PROT_TXOP(25:20) -- 111111
5398 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5399 // PROT_CTRL(17:16) -- 00 (None)
5400 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5401 Protect[3] = 0x03f44084;
5405 // PROT_TXOP(25:20) -- 010111
5406 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5407 // PROT_CTRL(17:16) -- 00 (None)
5408 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5409 Protect[4] = 0x01744004;
5413 // PROT_TXOP(25:20) -- 111111
5414 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5415 // PROT_CTRL(17:16) -- 00 (None)
5416 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5417 Protect[5] = 0x03f44084;
5421 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5422 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5423 Protect[4] = 0x01754004;
5424 Protect[5] = 0x03f54084;
5426 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5430 // This is "HT non-member protection mode."
5431 // If there may be non-HT STAs my BSS
5432 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5433 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5434 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5436 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5437 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5439 //Assign Protection method for 20&40 MHz packets
5440 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5441 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5442 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5443 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5444 Protect[2] = ProtCfg.word;
5445 Protect[3] = ProtCfg4.word;
5446 Protect[4] = ProtCfg.word;
5447 Protect[5] = ProtCfg4.word;
5448 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5452 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5453 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5454 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5456 //Assign Protection method for 40MHz packets
5457 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5458 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5459 Protect[2] = ProtCfg.word;
5460 Protect[3] = ProtCfg4.word;
5463 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5464 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5466 Protect[4] = ProtCfg.word;
5467 Protect[5] = ProtCfg4.word;
5469 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5473 // HT mixed mode. PROTECT ALL!
5475 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5476 ProtCfg4.word = 0x03f44084;
5477 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5478 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5480 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5481 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5483 //Assign Protection method for 20&40 MHz packets
5484 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5485 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5486 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5487 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5488 Protect[2] = ProtCfg.word;
5489 Protect[3] = ProtCfg4.word;
5490 Protect[4] = ProtCfg.word;
5491 Protect[5] = ProtCfg4.word;
5492 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5496 // Special on for Atheros problem n chip.
5497 Protect[2] = 0x01754004;
5498 Protect[3] = 0x03f54084;
5499 Protect[4] = 0x01754004;
5500 Protect[5] = 0x03f54084;
5501 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5505 #endif // DOT11_N_SUPPORT //
5507 offset = CCK_PROT_CFG;
5508 for (i = 0;i < 6;i++)
5510 if ((SetMask & (1<< i)))
5512 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5518 ==========================================================================
5521 IRQL = PASSIVE_LEVEL
5522 IRQL = DISPATCH_LEVEL
5524 ==========================================================================
5526 VOID AsicSwitchChannel(
5527 IN PRTMP_ADAPTER pAd,
5531 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5532 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5534 UINT32 Value = 0; //BbpReg, Value;
5535 RTMP_RF_REGS *RFRegTable;
5537 // Search Tx power value
5538 for (index = 0; index < pAd->ChannelListNum; index++)
5540 if (Channel == pAd->ChannelList[index].Channel)
5542 TxPwer = pAd->ChannelList[index].Power;
5543 TxPwer2 = pAd->ChannelList[index].Power2;
5548 if (index == MAX_NUM_OF_CHANNELS)
5550 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5554 RFRegTable = RF2850RegTable;
5556 switch (pAd->RfIcType)
5563 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5565 if (Channel == RFRegTable[index].Channel)
5567 R2 = RFRegTable[index].R2;
5568 if (pAd->Antenna.field.TxPath == 1)
5570 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5573 if (pAd->Antenna.field.RxPath == 2)
5575 R2 |= 0x40; // write 1 to off Rxpath.
5577 else if (pAd->Antenna.field.RxPath == 1)
5579 R2 |= 0x20040; // write 1 to off RxPath
5584 // initialize R3, R4
5585 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5586 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5588 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5590 if ((TxPwer >= -7) && (TxPwer < 0))
5592 TxPwer = (7+TxPwer);
5593 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5594 R3 |= (TxPwer << 10);
5595 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5599 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5600 R3 |= (TxPwer << 10) | (1 << 9);
5604 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5606 TxPwer2 = (7+TxPwer2);
5607 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5608 R4 |= (TxPwer2 << 7);
5609 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5613 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5614 R4 |= (TxPwer2 << 7) | (1 << 6);
5619 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5620 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5623 // Based on BBP current mode before changing RF channel.
5624 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5630 pAd->LatchRfRegs.Channel = Channel;
5631 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5632 pAd->LatchRfRegs.R2 = R2;
5633 pAd->LatchRfRegs.R3 = R3;
5634 pAd->LatchRfRegs.R4 = R4;
5636 // Set RF value 1's set R3[bit2] = [0]
5637 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5638 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5639 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5640 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5644 // Set RF value 2's set R3[bit2] = [1]
5645 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5646 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5647 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5648 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5652 // Set RF value 3's set R3[bit2] = [0]
5653 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5654 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5655 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5656 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5668 // Change BBP setting during siwtch from a->g, g->a
5671 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5673 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5674 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5675 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5676 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.
5677 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5679 // Rx High power VGA offset for LNA select
5680 if (pAd->NicConfig2.field.ExternalLNAForG)
5682 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5683 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5687 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5688 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5691 // 5G band selection PIN, bit1 and bit2 are complement
5692 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5695 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5697 // Turn off unused PA or LNA when only 1T or 1R
5698 if (pAd->Antenna.field.TxPath == 1)
5700 TxPinCfg &= 0xFFFFFFF3;
5702 if (pAd->Antenna.field.RxPath == 1)
5704 TxPinCfg &= 0xFFFFF3FF;
5707 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5711 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5713 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5714 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5715 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5716 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.
5717 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5719 // Rx High power VGA offset for LNA select
5720 if (pAd->NicConfig2.field.ExternalLNAForA)
5722 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5726 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5729 // 5G band selection PIN, bit1 and bit2 are complement
5730 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5733 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5735 // Turn off unused PA or LNA when only 1T or 1R
5736 if (pAd->Antenna.field.TxPath == 1)
5738 TxPinCfg &= 0xFFFFFFF3;
5740 if (pAd->Antenna.field.RxPath == 1)
5742 TxPinCfg &= 0xFFFFF3FF;
5745 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5748 // R66 should be set according to Channel and use 20MHz when scanning
5749 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5751 RTMPSetAGCInitValue(pAd, BW_20);
5753 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5756 // On 11A, We should delay and wait RF/BBP to be stable
5757 // and the appropriate time should be 1000 micro seconds
5758 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5760 RTMPusecDelay(1000);
5762 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",
5765 (R3 & 0x00003e00) >> 9,
5766 (R4 & 0x000007c0) >> 6,
5767 pAd->Antenna.field.TxPath,
5768 pAd->LatchRfRegs.R1,
5769 pAd->LatchRfRegs.R2,
5770 pAd->LatchRfRegs.R3,
5771 pAd->LatchRfRegs.R4));
5775 ==========================================================================
5777 This function is required for 2421 only, and should not be used during
5778 site survey. It's only required after NIC decided to stay at a channel
5779 for a longer period.
5780 When this function is called, it's always after AsicSwitchChannel().
5782 IRQL = PASSIVE_LEVEL
5783 IRQL = DISPATCH_LEVEL
5785 ==========================================================================
5787 VOID AsicLockChannel(
5788 IN PRTMP_ADAPTER pAd,
5794 ==========================================================================
5797 IRQL = PASSIVE_LEVEL
5798 IRQL = DISPATCH_LEVEL
5800 ==========================================================================
5802 VOID AsicAntennaSelect(
5803 IN PRTMP_ADAPTER pAd,
5809 ========================================================================
5811 Routine Description:
5812 Antenna miscellaneous setting.
5815 pAd Pointer to our adapter
5816 BandState Indicate current Band State.
5821 IRQL <= DISPATCH_LEVEL
5824 1.) Frame End type control
5825 only valid for G only (RF_2527 & RF_2529)
5826 0: means DPDT, set BBP R4 bit 5 to 1
5827 1: means SPDT, set BBP R4 bit 5 to 0
5830 ========================================================================
5832 VOID AsicAntennaSetting(
5833 IN PRTMP_ADAPTER pAd,
5834 IN ABGBAND_STATE BandState)
5838 VOID AsicRfTuningExec(
5839 IN PVOID SystemSpecific1,
5840 IN PVOID FunctionContext,
5841 IN PVOID SystemSpecific2,
5842 IN PVOID SystemSpecific3)
5847 ==========================================================================
5849 Gives CCK TX rate 2 more dB TX power.
5850 This routine works only in LINK UP in INFRASTRUCTURE mode.
5852 calculate desired Tx power in RF R3.Tx0~5, should consider -
5853 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5854 1. TxPowerPercentage
5855 2. auto calibration based on TSSI feedback
5856 3. extra 2 db for CCK
5857 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5859 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5860 it should be called AFTER MlmeDynamicTxRatSwitching()
5861 ==========================================================================
5863 VOID AsicAdjustTxPower(
5864 IN PRTMP_ADAPTER pAd)
5868 BOOLEAN bAutoTxAgc = FALSE;
5869 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5870 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5871 PCHAR pTxAgcCompensate;
5875 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5876 || (pAd->bPCIclkOff == TRUE)
5877 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
5878 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
5881 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5883 if (pAd->CommonCfg.CentralChannel > 14)
5885 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5886 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5887 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5888 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5889 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5893 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5894 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5895 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5896 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5897 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5902 if (pAd->CommonCfg.Channel > 14)
5904 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5905 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5906 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5907 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5908 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5912 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5913 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5914 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5915 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5916 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5920 // TX power compensation for temperature variation based on TSSI. try every 4 second
5921 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5923 if (pAd->CommonCfg.Channel <= 14)
5926 bAutoTxAgc = pAd->bAutoTxAgcG;
5927 TssiRef = pAd->TssiRefG;
5928 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5929 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5930 TxAgcStep = pAd->TxAgcStepG;
5931 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5936 bAutoTxAgc = pAd->bAutoTxAgcA;
5937 TssiRef = pAd->TssiRefA;
5938 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
5939 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
5940 TxAgcStep = pAd->TxAgcStepA;
5941 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5946 /* BbpR1 is unsigned char */
5947 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
5949 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
5950 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
5951 /* step value is defined in pAd->TxAgcStepG for tx power value */
5953 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
5954 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
5955 above value are examined in mass factory production */
5956 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
5958 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
5959 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
5960 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
5962 if (BbpR49 > pTssiMinusBoundary[1])
5964 // Reading is larger than the reference value
5965 // check for how large we need to decrease the Tx power
5966 for (idx = 1; idx < 5; idx++)
5968 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
5971 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
5972 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
5974 DeltaPwr += (*pTxAgcCompensate);
5975 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
5976 BbpR49, TssiRef, TxAgcStep, idx-1));
5978 else if (BbpR49 < pTssiPlusBoundary[1])
5980 // Reading is smaller than the reference value
5981 // check for how large we need to increase the Tx power
5982 for (idx = 1; idx < 5; idx++)
5984 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
5987 // The index is the step we should increase, idx = 0 means there is nothing to compensate
5988 *pTxAgcCompensate = TxAgcStep * (idx-1);
5989 DeltaPwr += (*pTxAgcCompensate);
5990 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5991 BbpR49, TssiRef, TxAgcStep, idx-1));
5995 *pTxAgcCompensate = 0;
5996 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5997 BbpR49, TssiRef, TxAgcStep, 0));
6003 if (pAd->CommonCfg.Channel <= 14)
6005 bAutoTxAgc = pAd->bAutoTxAgcG;
6006 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6010 bAutoTxAgc = pAd->bAutoTxAgcA;
6011 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6015 DeltaPwr += (*pTxAgcCompensate);
6018 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6021 /* calculate delta power based on the percentage specified from UI */
6022 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6023 // We lower TX power here according to the percentage specified from UI
6024 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6026 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6028 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6032 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6036 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6040 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6045 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6050 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6052 /* reset different new tx power for different TX rate */
6055 if (TxPwr[i] != 0xffffffff)
6059 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6061 if ((Value + DeltaPwr) < 0)
6063 Value = 0; /* min */
6065 else if ((Value + DeltaPwr) > 0xF)
6067 Value = 0xF; /* max */
6071 Value += DeltaPwr; /* temperature compensation */
6074 /* fill new value to CSR offset */
6075 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6078 /* write tx power value to CSR */
6079 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6080 TX power for OFDM 6M/9M
6081 TX power for CCK5.5M/11M
6082 TX power for CCK1M/2M */
6083 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6084 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6091 ==========================================================================
6093 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6094 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6095 the wakeup timer timeout. Driver has to issue a separate command to wake
6098 IRQL = DISPATCH_LEVEL
6100 ==========================================================================
6102 VOID AsicSleepThenAutoWakeup(
6103 IN PRTMP_ADAPTER pAd,
6104 IN USHORT TbttNumToNextWakeUp)
6106 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6110 ==========================================================================
6112 AsicForceWakeup() is used whenever manual wakeup is required
6113 AsicForceSleep() should only be used when not in INFRA BSS. When
6114 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6115 ==========================================================================
6117 VOID AsicForceSleep(
6118 IN PRTMP_ADAPTER pAd)
6124 ==========================================================================
6126 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6129 IRQL = PASSIVE_LEVEL
6130 IRQL = DISPATCH_LEVEL
6131 ==========================================================================
6133 VOID AsicForceWakeup(
6134 IN PRTMP_ADAPTER pAd,
6137 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6138 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6142 ==========================================================================
6146 IRQL = DISPATCH_LEVEL
6148 ==========================================================================
6151 IN PRTMP_ADAPTER pAd,
6155 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6156 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6158 Addr4 = (ULONG)(pBssid[0]) |
6159 (ULONG)(pBssid[1] << 8) |
6160 (ULONG)(pBssid[2] << 16) |
6161 (ULONG)(pBssid[3] << 24);
6162 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6165 // always one BSSID in STA mode
6166 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6168 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6171 VOID AsicSetMcastWC(
6172 IN PRTMP_ADAPTER pAd)
6174 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6177 pEntry->Sst = SST_ASSOC;
6178 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6179 pEntry->PsMode = PWR_ACTIVE;
6180 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6181 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6185 ==========================================================================
6188 IRQL = DISPATCH_LEVEL
6190 ==========================================================================
6192 VOID AsicDelWcidTab(
6193 IN PRTMP_ADAPTER pAd,
6196 ULONG Addr0 = 0x0, Addr1 = 0x0;
6199 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6200 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6201 RTMP_IO_WRITE32(pAd, offset, Addr0);
6203 RTMP_IO_WRITE32(pAd, offset, Addr1);
6207 ==========================================================================
6210 IRQL = DISPATCH_LEVEL
6212 ==========================================================================
6215 IN PRTMP_ADAPTER pAd)
6217 TX_LINK_CFG_STRUC TxLinkCfg;
6220 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6221 TxLinkCfg.field.TxRDGEn = 1;
6222 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6224 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6227 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6229 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6233 ==========================================================================
6236 IRQL = DISPATCH_LEVEL
6238 ==========================================================================
6240 VOID AsicDisableRDG(
6241 IN PRTMP_ADAPTER pAd)
6243 TX_LINK_CFG_STRUC TxLinkCfg;
6247 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6248 TxLinkCfg.field.TxRDGEn = 0;
6249 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6251 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6254 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6255 #ifdef DOT11_N_SUPPORT
6256 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6257 #endif // DOT11_N_SUPPORT //
6260 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6261 if (pAd->CommonCfg.bEnableTxBurst)
6264 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6268 ==========================================================================
6271 IRQL = PASSIVE_LEVEL
6272 IRQL = DISPATCH_LEVEL
6274 ==========================================================================
6276 VOID AsicDisableSync(
6277 IN PRTMP_ADAPTER pAd)
6279 BCN_TIME_CFG_STRUC csr;
6281 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6283 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6284 // that NIC will never wakes up because TSF stops and no more
6286 pAd->TbttTickCount = 0;
6287 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6288 csr.field.bBeaconGen = 0;
6289 csr.field.bTBTTEnable = 0;
6290 csr.field.TsfSyncMode = 0;
6291 csr.field.bTsfTicking = 0;
6292 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6297 ==========================================================================
6300 IRQL = DISPATCH_LEVEL
6302 ==========================================================================
6304 VOID AsicEnableBssSync(
6305 IN PRTMP_ADAPTER pAd)
6307 BCN_TIME_CFG_STRUC csr;
6309 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6311 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6313 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6315 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6316 csr.field.bTsfTicking = 1;
6317 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6318 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6319 csr.field.bTBTTEnable = 1;
6322 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6326 ==========================================================================
6329 BEACON frame in shared memory should be built ok before this routine
6330 can be called. Otherwise, a garbage frame maybe transmitted out every
6333 IRQL = DISPATCH_LEVEL
6335 ==========================================================================
6337 VOID AsicEnableIbssSync(
6338 IN PRTMP_ADAPTER pAd)
6340 BCN_TIME_CFG_STRUC csr9;
6344 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6346 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6347 csr9.field.bBeaconGen = 0;
6348 csr9.field.bTBTTEnable = 0;
6349 csr9.field.bTsfTicking = 0;
6350 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6352 // move BEACON TXD and frame content to on-chip memory
6353 ptr = (PUCHAR)&pAd->BeaconTxWI;
6354 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6356 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6357 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6361 // start right after the 16-byte TXWI field
6362 ptr = pAd->BeaconBuf;
6363 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6365 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6366 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6370 // start sending BEACON
6371 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6372 csr9.field.bTsfTicking = 1;
6373 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6374 csr9.field.bTBTTEnable = 1;
6375 csr9.field.bBeaconGen = 1;
6376 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6380 ==========================================================================
6383 IRQL = PASSIVE_LEVEL
6384 IRQL = DISPATCH_LEVEL
6386 ==========================================================================
6388 VOID AsicSetEdcaParm(
6389 IN PRTMP_ADAPTER pAd,
6390 IN PEDCA_PARM pEdcaParm)
6392 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6393 AC_TXOP_CSR0_STRUC csr0;
6394 AC_TXOP_CSR1_STRUC csr1;
6395 AIFSN_CSR_STRUC AifsnCsr;
6396 CWMIN_CSR_STRUC CwminCsr;
6397 CWMAX_CSR_STRUC CwmaxCsr;
6404 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6406 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6407 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6408 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6410 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6411 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6414 //========================================================
6415 // MAC Register has a copy .
6416 //========================================================
6417 if( pAd->CommonCfg.bEnableTxBurst )
6419 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6420 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6423 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6424 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6425 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6426 Ac0Cfg.field.Aifsn = 2;
6427 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6429 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6430 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6431 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6432 Ac1Cfg.field.Aifsn = 2;
6433 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6435 if (pAd->CommonCfg.PhyMode == PHY_11B)
6437 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6438 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6442 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6443 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6445 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6446 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6447 Ac2Cfg.field.Aifsn = 2;
6448 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6449 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6450 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6451 Ac3Cfg.field.Aifsn = 2;
6452 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6454 //========================================================
6455 // DMA Register has a copy too.
6456 //========================================================
6457 csr0.field.Ac0Txop = 0; // QID_AC_BE
6458 csr0.field.Ac1Txop = 0; // QID_AC_BK
6459 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6460 if (pAd->CommonCfg.PhyMode == PHY_11B)
6462 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6463 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6467 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6468 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6470 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6473 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6474 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6475 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6476 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6477 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6480 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6481 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6482 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6483 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6484 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6486 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6488 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6492 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6493 //========================================================
6494 // MAC Register has a copy.
6495 //========================================================
6497 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6498 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6500 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6502 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6503 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6504 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6505 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6507 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6508 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6509 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6510 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6512 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6513 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6514 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6515 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6517 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6519 // Tuning for Wi-Fi WMM S06
6520 if (pAd->CommonCfg.bWiFiTest &&
6521 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6522 Ac2Cfg.field.Aifsn -= 1;
6524 // Tuning for TGn Wi-Fi 5.2.32
6525 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6526 if (STA_TGN_WIFI_ON(pAd) &&
6527 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6529 Ac0Cfg.field.Aifsn = 3;
6530 Ac2Cfg.field.AcTxop = 5;
6534 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6535 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6536 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6537 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6540 if (pAd->CommonCfg.bWiFiTest)
6542 if (Ac3Cfg.field.AcTxop == 102)
6544 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6545 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6546 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6547 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6548 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6551 //#endif // WIFI_TEST //
6553 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6554 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6555 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6556 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6559 //========================================================
6560 // DMA Register has a copy too.
6561 //========================================================
6562 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6563 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6564 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6566 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6567 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6568 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6571 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6572 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6573 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6575 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6576 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6578 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6581 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6582 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6583 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6584 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6585 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6588 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6589 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6590 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6592 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6594 // Tuning for Wi-Fi WMM S06
6595 if (pAd->CommonCfg.bWiFiTest &&
6596 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6597 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6599 // Tuning for TGn Wi-Fi 5.2.32
6600 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6601 if (STA_TGN_WIFI_ON(pAd) &&
6602 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6604 AifsnCsr.field.Aifsn0 = 3;
6605 AifsnCsr.field.Aifsn2 = 7;
6609 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6610 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6612 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6614 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6617 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6618 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6619 pEdcaParm->Aifsn[0],
6620 pEdcaParm->Cwmin[0],
6621 pEdcaParm->Cwmax[0],
6622 pEdcaParm->Txop[0]<<5,
6623 pEdcaParm->bACM[0]));
6624 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6625 pEdcaParm->Aifsn[1],
6626 pEdcaParm->Cwmin[1],
6627 pEdcaParm->Cwmax[1],
6628 pEdcaParm->Txop[1]<<5,
6629 pEdcaParm->bACM[1]));
6630 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6631 pEdcaParm->Aifsn[2],
6632 pEdcaParm->Cwmin[2],
6633 pEdcaParm->Cwmax[2],
6634 pEdcaParm->Txop[2]<<5,
6635 pEdcaParm->bACM[2]));
6636 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6637 pEdcaParm->Aifsn[3],
6638 pEdcaParm->Cwmin[3],
6639 pEdcaParm->Cwmax[3],
6640 pEdcaParm->Txop[3]<<5,
6641 pEdcaParm->bACM[3]));
6647 ==========================================================================
6650 IRQL = PASSIVE_LEVEL
6651 IRQL = DISPATCH_LEVEL
6653 ==========================================================================
6655 VOID AsicSetSlotTime(
6656 IN PRTMP_ADAPTER pAd,
6657 IN BOOLEAN bUseShortSlotTime)
6660 UINT32 RegValue = 0;
6662 if (pAd->CommonCfg.Channel > 14)
6663 bUseShortSlotTime = TRUE;
6665 if (bUseShortSlotTime)
6666 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6668 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6670 SlotTime = (bUseShortSlotTime)? 9 : 20;
6672 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6674 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6675 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6676 #ifdef DOT11_N_SUPPORT
6677 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6678 #endif // DOT11_N_SUPPORT //
6681 // In this case, we will think it is doing Wi-Fi test
6682 // And we will not set to short slot when bEnableTxBurst is TRUE.
6684 else if (pAd->CommonCfg.bEnableTxBurst)
6689 // For some reasons, always set it to short slot time.
6691 // ToDo: Should consider capability with 11B
6693 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6695 if (pAd->StaCfg.BssType == BSS_ADHOC)
6699 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6700 RegValue = RegValue & 0xFFFFFF00;
6702 RegValue |= SlotTime;
6704 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6708 ========================================================================
6710 Add Shared key information into ASIC.
6711 Update shared key, TxMic and RxMic to Asic Shared key table
6712 Update its cipherAlg to Asic Shared key Mode.
6715 ========================================================================
6717 VOID AsicAddSharedKeyEntry(
6718 IN PRTMP_ADAPTER pAd,
6726 ULONG offset; //, csr0;
6727 SHAREDKEY_MODE_STRUC csr1;
6730 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6731 //============================================================================================
6733 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6734 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6735 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]));
6738 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6739 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6743 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6744 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6746 //============================================================================================
6748 // fill key material - key + TX MIC + RX MIC
6750 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6751 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6753 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6756 offset += MAX_LEN_OF_SHARE_KEY;
6761 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6770 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6776 // Update cipher algorithm. WSTA always use BSS0
6778 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6779 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6780 if ((BssIndex%2) == 0)
6783 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6784 else if (KeyIdx == 1)
6785 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6786 else if (KeyIdx == 2)
6787 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6789 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6794 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6795 else if (KeyIdx == 1)
6796 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6797 else if (KeyIdx == 2)
6798 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6800 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6802 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6803 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6807 // IRQL = DISPATCH_LEVEL
6808 VOID AsicRemoveSharedKeyEntry(
6809 IN PRTMP_ADAPTER pAd,
6814 SHAREDKEY_MODE_STRUC csr1;
6816 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6818 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6819 if ((BssIndex%2) == 0)
6822 csr1.field.Bss0Key0CipherAlg = 0;
6823 else if (KeyIdx == 1)
6824 csr1.field.Bss0Key1CipherAlg = 0;
6825 else if (KeyIdx == 2)
6826 csr1.field.Bss0Key2CipherAlg = 0;
6828 csr1.field.Bss0Key3CipherAlg = 0;
6833 csr1.field.Bss1Key0CipherAlg = 0;
6834 else if (KeyIdx == 1)
6835 csr1.field.Bss1Key1CipherAlg = 0;
6836 else if (KeyIdx == 2)
6837 csr1.field.Bss1Key2CipherAlg = 0;
6839 csr1.field.Bss1Key3CipherAlg = 0;
6841 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6842 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6843 ASSERT(BssIndex < 4);
6849 VOID AsicUpdateWCIDAttribute(
6850 IN PRTMP_ADAPTER pAd,
6854 IN BOOLEAN bUsePairewiseKeyTable)
6856 ULONG WCIDAttri = 0, offset;
6859 // Update WCID attribute.
6860 // Only TxKey could update WCID attribute.
6862 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6863 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6864 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6867 VOID AsicUpdateWCIDIVEIV(
6868 IN PRTMP_ADAPTER pAd,
6875 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6877 RTMP_IO_WRITE32(pAd, offset, uIV);
6878 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6881 VOID AsicUpdateRxWCIDTable(
6882 IN PRTMP_ADAPTER pAd,
6889 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6890 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6891 RTMP_IO_WRITE32(pAd, offset, Addr);
6892 Addr = pAddr[4] + (pAddr[5] << 8);
6893 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6898 ========================================================================
6900 Routine Description:
6901 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6904 pAd Pointer to our adapter
6905 WCID WCID Entry number.
6906 BssIndex BSSID index, station or none multiple BSSID support
6907 this value should be 0.
6908 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6909 pCipherKey Pointer to Cipher Key.
6910 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6911 otherwise PairewiseKey table
6912 bTxKey This is the transmit key if enabled.
6918 This routine will set the relative key stuff to Asic including WCID attribute,
6919 Cipher Key, Cipher algorithm and IV/EIV.
6921 IV/EIV will be update if this CipherKey is the transmission key because
6922 ASIC will base on IV's KeyID value to select Cipher Key.
6924 If bTxKey sets to FALSE, this is not the TX key, but it could be
6927 For AP mode bTxKey must be always set to TRUE.
6928 ========================================================================
6930 VOID AsicAddKeyEntry(
6931 IN PRTMP_ADAPTER pAd,
6935 IN PCIPHER_KEY pCipherKey,
6936 IN BOOLEAN bUsePairewiseKeyTable,
6941 PUCHAR pKey = pCipherKey->Key;
6942 PUCHAR pTxMic = pCipherKey->TxMic;
6943 PUCHAR pRxMic = pCipherKey->RxMic;
6944 PUCHAR pTxtsc = pCipherKey->TxTsc;
6945 UCHAR CipherAlg = pCipherKey->CipherAlg;
6946 SHAREDKEY_MODE_STRUC csr1;
6949 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
6951 // 1.) decide key table offset
6953 if (bUsePairewiseKeyTable)
6954 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6956 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
6959 // 2.) Set Key to Asic
6961 //for (i = 0; i < KeyLen; i++)
6962 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
6964 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6966 offset += MAX_LEN_OF_PEER_KEY;
6969 // 3.) Set MIC key if available
6973 for (i = 0; i < 8; i++)
6975 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6978 offset += LEN_TKIP_TXMICK;
6982 for (i = 0; i < 8; i++)
6984 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6990 // 4.) Modify IV/EIV if needs
6991 // This will force Asic to use this key ID by setting IV.
6995 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6999 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7000 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7001 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7003 IV4 = (KeyIdx << 6);
7004 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7005 IV4 |= 0x20; // turn on extension bit means EIV existence
7007 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7013 for (i = 0; i < 4; i++)
7015 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7018 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7021 if (!bUsePairewiseKeyTable)
7024 // Only update the shared key security mode
7026 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7027 if ((BssIndex % 2) == 0)
7030 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7031 else if (KeyIdx == 1)
7032 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7033 else if (KeyIdx == 2)
7034 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7036 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7041 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7042 else if (KeyIdx == 1)
7043 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7044 else if (KeyIdx == 2)
7045 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7047 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7049 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7052 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7057 ========================================================================
7059 Add Pair-wise key material into ASIC.
7060 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7063 ========================================================================
7065 VOID AsicAddPairwiseKeyEntry(
7066 IN PRTMP_ADAPTER pAd,
7069 IN CIPHER_KEY *pCipherKey)
7073 PUCHAR pKey = pCipherKey->Key;
7074 PUCHAR pTxMic = pCipherKey->TxMic;
7075 PUCHAR pRxMic = pCipherKey->RxMic;
7077 UCHAR CipherAlg = pCipherKey->CipherAlg;
7081 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7082 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7084 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7086 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7089 RTMP_IO_READ32(pAd, offset + i, &Value);
7092 offset += MAX_LEN_OF_PEER_KEY;
7099 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7107 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7111 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7112 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7113 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]));
7116 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7117 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7121 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7122 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7126 ========================================================================
7128 Remove Pair-wise key material from ASIC.
7131 ========================================================================
7133 VOID AsicRemovePairwiseKeyEntry(
7134 IN PRTMP_ADAPTER pAd,
7141 // re-set the entry's WCID attribute as OPEN-NONE.
7142 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7143 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7144 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7147 BOOLEAN AsicSendCommandToMcu(
7148 IN PRTMP_ADAPTER pAd,
7154 HOST_CMD_CSR_STRUC H2MCmd;
7155 H2M_MAILBOX_STRUC H2MMailbox;
7160 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7161 if (H2MMailbox.field.Owner == 0)
7173 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7175 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7177 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7178 // Reset DMA/CPU ring index
7179 RTMPRingCleanUp(pAd, QID_AC_BK);
7180 RTMPRingCleanUp(pAd, QID_AC_BE);
7181 RTMPRingCleanUp(pAd, QID_AC_VI);
7182 RTMPRingCleanUp(pAd, QID_AC_VO);
7183 RTMPRingCleanUp(pAd, QID_HCCA);
7184 RTMPRingCleanUp(pAd, QID_MGMT);
7185 RTMPRingCleanUp(pAd, QID_RX);
7188 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7190 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7191 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7196 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7197 H2MMailbox.field.CmdToken = Token;
7198 H2MMailbox.field.HighByte = Arg1;
7199 H2MMailbox.field.LowByte = Arg0;
7200 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7203 H2MCmd.field.HostCommand = Command;
7204 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7206 if (Command != 0x80)
7213 BOOLEAN AsicCheckCommanOk(
7214 IN PRTMP_ADAPTER pAd,
7217 UINT32 CmdStatus = 0, CID = 0, i;
7218 UINT32 ThisCIDMask = 0;
7223 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7224 // Find where the command is. Because this is randomly specified by firmware.
7225 if ((CID & CID0MASK) == Command)
7227 ThisCIDMask = CID0MASK;
7230 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7232 ThisCIDMask = CID1MASK;
7235 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7237 ThisCIDMask = CID2MASK;
7240 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7242 ThisCIDMask = CID3MASK;
7250 // Get CommandStatus Value
7251 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7253 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7256 // If Status is 1, the comamnd is success.
7257 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7258 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7260 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7261 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7262 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7265 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7269 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7271 // Clear Command and Status.
7272 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7273 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7279 ========================================================================
7281 Routine Description:
7282 Verify the support rate for different PHY type
7285 pAd Pointer to our adapter
7290 IRQL = PASSIVE_LEVEL
7292 ========================================================================
7294 VOID RTMPCheckRates(
7295 IN PRTMP_ADAPTER pAd,
7296 IN OUT UCHAR SupRate[],
7297 IN OUT UCHAR *SupRateLen)
7299 UCHAR RateIdx, i, j;
7300 UCHAR NewRate[12], NewRateLen;
7304 if (pAd->CommonCfg.PhyMode == PHY_11B)
7309 // Check for support rates exclude basic rate bit
7310 for (i = 0; i < *SupRateLen; i++)
7311 for (j = 0; j < RateIdx; j++)
7312 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7313 NewRate[NewRateLen++] = SupRate[i];
7315 *SupRateLen = NewRateLen;
7316 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7319 #ifdef DOT11_N_SUPPORT
7320 BOOLEAN RTMPCheckChannel(
7321 IN PRTMP_ADAPTER pAd,
7322 IN UCHAR CentralChannel,
7326 UCHAR UpperChannel = 0, LowerChannel = 0;
7327 UCHAR NoEffectChannelinList = 0;
7329 // Find upper and lower channel according to 40MHz current operation.
7330 if (CentralChannel < Channel)
7332 UpperChannel = Channel;
7333 if (CentralChannel > 2)
7334 LowerChannel = CentralChannel - 2;
7338 else if (CentralChannel > Channel)
7340 UpperChannel = CentralChannel + 2;
7341 LowerChannel = Channel;
7344 for (k = 0;k < pAd->ChannelListNum;k++)
7346 if (pAd->ChannelList[k].Channel == UpperChannel)
7348 NoEffectChannelinList ++;
7350 if (pAd->ChannelList[k].Channel == LowerChannel)
7352 NoEffectChannelinList ++;
7356 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7357 if (NoEffectChannelinList == 2)
7364 ========================================================================
7366 Routine Description:
7367 Verify the support rate for HT phy type
7370 pAd Pointer to our adapter
7373 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7375 IRQL = PASSIVE_LEVEL
7377 ========================================================================
7379 BOOLEAN RTMPCheckHt(
7380 IN PRTMP_ADAPTER pAd,
7382 IN HT_CAPABILITY_IE *pHtCapability,
7383 IN ADD_HT_INFO_IE *pAddHtInfo)
7385 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7388 // If use AMSDU, set flag.
7389 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7390 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7391 // Save Peer Capability
7392 if (pHtCapability->HtCapInfo.ShortGIfor20)
7393 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7394 if (pHtCapability->HtCapInfo.ShortGIfor40)
7395 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7396 if (pHtCapability->HtCapInfo.TxSTBC)
7397 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7398 if (pHtCapability->HtCapInfo.RxSTBC)
7399 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7400 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7402 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7405 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7407 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7410 // Will check ChannelWidth for MCSSet[4] below
7411 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7412 switch (pAd->CommonCfg.RxStream)
7415 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7416 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7417 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7418 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7421 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7422 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7423 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7424 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7427 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7428 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7429 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7430 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7434 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7436 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7437 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7438 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7440 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7442 // Send Assoc Req with my HT capability.
7443 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7444 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7445 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7446 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7447 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7448 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7449 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7450 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7451 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7452 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7453 if (pAd->CommonCfg.bRdg)
7455 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7456 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7459 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7460 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7462 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7465 #endif // DOT11_N_SUPPORT //
7468 ========================================================================
7470 Routine Description:
7471 Verify the support rate for different PHY type
7474 pAd Pointer to our adapter
7479 IRQL = PASSIVE_LEVEL
7481 ========================================================================
7483 VOID RTMPUpdateMlmeRate(
7484 IN PRTMP_ADAPTER pAd)
7487 UCHAR ProperMlmeRate; //= RATE_54;
7488 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7489 BOOLEAN bMatch = FALSE;
7491 switch (pAd->CommonCfg.PhyMode)
7494 ProperMlmeRate = RATE_11;
7495 MinimumRate = RATE_1;
7497 case PHY_11BG_MIXED:
7498 #ifdef DOT11_N_SUPPORT
7499 case PHY_11ABGN_MIXED:
7500 case PHY_11BGN_MIXED:
7501 #endif // DOT11_N_SUPPORT //
7502 if ((pAd->MlmeAux.SupRateLen == 4) &&
7503 (pAd->MlmeAux.ExtRateLen == 0))
7505 ProperMlmeRate = RATE_11;
7507 ProperMlmeRate = RATE_24;
7509 if (pAd->MlmeAux.Channel <= 14)
7510 MinimumRate = RATE_1;
7512 MinimumRate = RATE_6;
7515 #ifdef DOT11_N_SUPPORT
7516 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7517 case PHY_11GN_MIXED:
7518 case PHY_11AGN_MIXED:
7519 case PHY_11AN_MIXED:
7521 #endif // DOT11_N_SUPPORT //
7522 ProperMlmeRate = RATE_24;
7523 MinimumRate = RATE_6;
7525 case PHY_11ABG_MIXED:
7526 ProperMlmeRate = RATE_24;
7527 if (pAd->MlmeAux.Channel <= 14)
7528 MinimumRate = RATE_1;
7530 MinimumRate = RATE_6;
7533 ProperMlmeRate = RATE_1;
7534 MinimumRate = RATE_1;
7538 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7540 for (j = 0; j < RateIdx; j++)
7542 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7544 if (j == ProperMlmeRate)
7556 if (bMatch == FALSE)
7558 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7560 for (j = 0; j < RateIdx; j++)
7562 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7564 if (j == ProperMlmeRate)
7577 if (bMatch == FALSE)
7579 ProperMlmeRate = MinimumRate;
7582 pAd->CommonCfg.MlmeRate = MinimumRate;
7583 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7584 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7586 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7587 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7588 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7589 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7593 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7594 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7595 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7596 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7599 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7603 IN PRTMP_ADAPTER pAd,
7610 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7615 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7617 larger = max(Rssi0, Rssi1);
7620 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7622 larger = max(larger, Rssi2);
7632 ========================================================================
7633 Routine Description:
7634 Periodic evaluate antenna link status
7637 pAd - Adapter pointer
7642 ========================================================================
7644 VOID AsicEvaluateRxAnt(
7645 IN PRTMP_ADAPTER pAd)
7649 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7651 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7652 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7653 fRTMP_ADAPTER_RADIO_OFF |
7654 fRTMP_ADAPTER_NIC_NOT_EXIST |
7655 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7658 if (pAd->StaCfg.Psm == PWR_SAVE)
7662 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7664 if(pAd->Antenna.field.RxPath == 3)
7668 else if(pAd->Antenna.field.RxPath == 2)
7672 else if(pAd->Antenna.field.RxPath == 1)
7676 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7678 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7679 pAd->StaCfg.BBPR3 = BBPR3;
7681 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7684 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7685 pAd->RalinkCounters.OneSecTxRetryOkCount +
7686 pAd->RalinkCounters.OneSecTxFailCount;
7688 if (TxTotalCnt > 50)
7690 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7691 pAd->Mlme.bLowThroughput = FALSE;
7695 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7696 pAd->Mlme.bLowThroughput = TRUE;
7702 ========================================================================
7703 Routine Description:
7704 After evaluation, check antenna link status
7707 pAd - Adapter pointer
7712 ========================================================================
7714 VOID AsicRxAntEvalTimeout(
7715 IN PVOID SystemSpecific1,
7716 IN PVOID FunctionContext,
7717 IN PVOID SystemSpecific2,
7718 IN PVOID SystemSpecific3)
7720 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7722 CHAR larger = -127, rssi0, rssi1, rssi2;
7724 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7726 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7727 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7728 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7729 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7732 if (pAd->StaCfg.Psm == PWR_SAVE)
7736 // if the traffic is low, use average rssi as the criteria
7737 if (pAd->Mlme.bLowThroughput == TRUE)
7739 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7740 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7741 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7745 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7746 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7747 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7750 if(pAd->Antenna.field.RxPath == 3)
7752 larger = max(rssi0, rssi1);
7754 if (larger > (rssi2 + 20))
7755 pAd->Mlme.RealRxPath = 2;
7757 pAd->Mlme.RealRxPath = 3;
7759 else if(pAd->Antenna.field.RxPath == 2)
7761 if (rssi0 > (rssi1 + 20))
7762 pAd->Mlme.RealRxPath = 1;
7764 pAd->Mlme.RealRxPath = 2;
7767 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7769 if(pAd->Mlme.RealRxPath == 3)
7773 else if(pAd->Mlme.RealRxPath == 2)
7777 else if(pAd->Mlme.RealRxPath == 1)
7781 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7782 pAd->StaCfg.BBPR3 = BBPR3;
7788 VOID APSDPeriodicExec(
7789 IN PVOID SystemSpecific1,
7790 IN PVOID FunctionContext,
7791 IN PVOID SystemSpecific2,
7792 IN PVOID SystemSpecific3)
7794 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7796 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7799 pAd->CommonCfg.TriggerTimerCount++;
7804 ========================================================================
7805 Routine Description:
7806 Set/reset MAC registers according to bPiggyBack parameter
7809 pAd - Adapter pointer
7810 bPiggyBack - Enable / Disable Piggy-Back
7815 ========================================================================
7817 VOID RTMPSetPiggyBack(
7818 IN PRTMP_ADAPTER pAd,
7819 IN BOOLEAN bPiggyBack)
7821 TX_LINK_CFG_STRUC TxLinkCfg;
7823 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7825 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7826 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7830 ========================================================================
7831 Routine Description:
7832 check if this entry need to switch rate automatically
7842 ========================================================================
7844 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7845 IN PRTMP_ADAPTER pAd,
7846 IN PMAC_TABLE_ENTRY pEntry)
7848 BOOLEAN result = TRUE;
7850 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7852 // only associated STA counts
7853 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7855 result = pAd->StaCfg.bAutoTxRateSwitch;
7865 BOOLEAN RTMPAutoRateSwitchCheck(
7866 IN PRTMP_ADAPTER pAd)
7868 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7870 if (pAd->StaCfg.bAutoTxRateSwitch)
7879 ========================================================================
7880 Routine Description:
7881 check if this entry need to fix tx legacy rate
7891 ========================================================================
7893 UCHAR RTMPStaFixedTxMode(
7894 IN PRTMP_ADAPTER pAd,
7895 IN PMAC_TABLE_ENTRY pEntry)
7897 UCHAR tx_mode = FIXED_TXMODE_HT;
7899 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7901 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7908 ========================================================================
7909 Routine Description:
7910 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
7920 ========================================================================
7922 VOID RTMPUpdateLegacyTxSetting(
7923 UCHAR fixed_tx_mode,
7924 PMAC_TABLE_ENTRY pEntry)
7926 HTTRANSMIT_SETTING TransmitSetting;
7928 if (fixed_tx_mode == FIXED_TXMODE_HT)
7931 TransmitSetting.word = 0;
7933 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
7934 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
7936 if (fixed_tx_mode == FIXED_TXMODE_CCK)
7938 TransmitSetting.field.MODE = MODE_CCK;
7939 // CCK mode allow MCS 0~3
7940 if (TransmitSetting.field.MCS > MCS_3)
7941 TransmitSetting.field.MCS = MCS_3;
7945 TransmitSetting.field.MODE = MODE_OFDM;
7946 // OFDM mode allow MCS 0~7
7947 if (TransmitSetting.field.MCS > MCS_7)
7948 TransmitSetting.field.MCS = MCS_7;
7951 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
7953 pEntry->HTPhyMode.word = TransmitSetting.word;
7954 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
7955 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
7960 ==========================================================================
7962 dynamic tune BBP R66 to find a balance between sensibility and
7965 IRQL = DISPATCH_LEVEL
7967 ==========================================================================
7969 VOID AsicStaBbpTuning(
7970 IN PRTMP_ADAPTER pAd)
7972 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
7975 // 2860C did not support Fase CCA, therefore can't tune
7976 if (pAd->MACVersion == 0x28600100)
7982 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
7985 if ((pAd->OpMode == OPMODE_STA)
7986 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7988 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
7989 && (pAd->bPCIclkOff == FALSE))
7991 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
7994 if (pAd->Antenna.field.RxPath > 1)
7995 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
7997 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
7999 if (pAd->LatchRfRegs.Channel <= 14)
8002 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8004 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8005 if (OrigR66Value != R66)
8007 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8012 R66 = 0x2E + GET_LNA_GAIN(pAd);
8013 if (OrigR66Value != R66)
8015 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8022 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8024 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8026 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8027 if (OrigR66Value != R66)
8029 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8034 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8035 if (OrigR66Value != R66)
8037 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8043 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8045 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8046 if (OrigR66Value != R66)
8048 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8053 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8054 if (OrigR66Value != R66)
8056 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8066 VOID AsicResetFromDMABusy(
8067 IN PRTMP_ADAPTER pAd)
8070 BOOLEAN bCtrl = FALSE;
8072 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8074 // Be sure restore link control value so we can write register.
8075 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8076 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8078 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8079 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8080 RTMPusecDelay(6000);
8081 pAd->bPCIclkOff = FALSE;
8085 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8087 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8089 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8090 // Reset DMA/CPU ring index
8091 RTMPRingCleanUp(pAd, QID_AC_BK);
8092 RTMPRingCleanUp(pAd, QID_AC_BE);
8093 RTMPRingCleanUp(pAd, QID_AC_VI);
8094 RTMPRingCleanUp(pAd, QID_AC_VO);
8095 RTMPRingCleanUp(pAd, QID_HCCA);
8096 RTMPRingCleanUp(pAd, QID_MGMT);
8097 RTMPRingCleanUp(pAd, QID_RX);
8100 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8102 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8104 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8105 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8106 RTMPPCIeLinkCtrlSetting(pAd, 3);
8108 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8109 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8110 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8114 IN PRTMP_ADAPTER pAd)
8116 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8118 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8119 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8120 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8122 // After hard-reset BBP, initialize all BBP values.
8123 NICRestoreBBPValue(pAd);
8124 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8128 IN PRTMP_ADAPTER pAd)
8132 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8133 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8135 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8137 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8139 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8143 IN PRTMP_ADAPTER pAd)
8145 ULONG Value1, Value2;
8148 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8149 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8152 // sum should be equals to 0xff, which is the total buffer size.
8153 if ((Value1 + Value2) < 0xff)
8155 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8156 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8158 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8160 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8162 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8166 VOID RTMPSetAGCInitValue(
8167 IN PRTMP_ADAPTER pAd,
8172 if (pAd->LatchRfRegs.Channel <= 14)
8174 R66 = 0x2E + GET_LNA_GAIN(pAd);
8175 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8179 if (BandWidth == BW_20)
8181 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8182 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8184 #ifdef DOT11_N_SUPPORT
8187 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8188 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8190 #endif // DOT11_N_SUPPORT //
8195 VOID AsicTurnOffRFClk(
8196 IN PRTMP_ADAPTER pAd,
8201 UINT32 R1 = 0, R2 = 0, R3 = 0;
8203 RTMP_RF_REGS *RFRegTable;
8205 RFRegTable = RF2850RegTable;
8207 switch (pAd->RfIcType)
8214 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8216 if (Channel == RFRegTable[index].Channel)
8218 R1 = RFRegTable[index].R1 & 0xffffdfff;
8219 R2 = RFRegTable[index].R2 & 0xfffbffff;
8220 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8222 RTMP_RF_IO_WRITE32(pAd, R1);
8223 RTMP_RF_IO_WRITE32(pAd, R2);
8225 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8226 // Set RF R2 bit18=0, R3 bit[18:19]=0
8227 //if (pAd->StaCfg.bRadio == FALSE)
8230 RTMP_RF_IO_WRITE32(pAd, R3);
8232 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8233 Channel, pAd->RfIcType, R2, R3));
8236 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8237 Channel, pAd->RfIcType, R2));
8249 VOID AsicTurnOnRFClk(
8250 IN PRTMP_ADAPTER pAd,
8255 UINT32 R1 = 0, R2 = 0, R3 = 0;
8257 RTMP_RF_REGS *RFRegTable;
8259 RFRegTable = RF2850RegTable;
8261 switch (pAd->RfIcType)
8268 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8270 if (Channel == RFRegTable[index].Channel)
8272 R3 = pAd->LatchRfRegs.R3;
8275 RTMP_RF_IO_WRITE32(pAd, R3);
8277 R1 = RFRegTable[index].R1;
8278 RTMP_RF_IO_WRITE32(pAd, R1);
8280 R2 = RFRegTable[index].R2;
8281 if (pAd->Antenna.field.TxPath == 1)
8283 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8286 if (pAd->Antenna.field.RxPath == 2)
8288 R2 |= 0x40; // write 1 to off Rxpath.
8290 else if (pAd->Antenna.field.RxPath == 1)
8292 R2 |= 0x20040; // write 1 to off RxPath
8294 RTMP_RF_IO_WRITE32(pAd, R2);
8305 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",