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 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1009 // WPA MIC error should block association attempt for 60 seconds
1010 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1011 pAd->StaCfg.bBlockAssoc = FALSE;
1015 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1016 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1017 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1018 if(pAd->StaCfg.WepStatus<2)
1020 pAd->StaCfg.WpaSupplicantUP = 0;
1024 pAd->StaCfg.WpaSupplicantUP = 1;
1027 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1029 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1031 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1033 pAd->PreMediaState = pAd->IndicateMediaState;
1036 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1037 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1038 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1039 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1040 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1041 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1043 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1048 AsicStaBbpTuning(pAd);
1050 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1051 pAd->RalinkCounters.OneSecTxRetryOkCount +
1052 pAd->RalinkCounters.OneSecTxFailCount;
1054 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1056 // update channel quality for Roaming and UI LinkQuality display
1057 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1060 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1061 // Radio is currently in noisy environment
1062 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1063 AsicAdjustTxPower(pAd);
1067 // Is PSM bit consistent with user power management policy?
1068 // This is the only place that will set PSM bit ON.
1069 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1070 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1072 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1074 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1075 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1076 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1078 RTMPSetAGCInitValue(pAd, BW_20);
1079 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1083 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1085 // When APSD is enabled, the period changes as 20 sec
1086 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1087 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1091 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1092 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1094 if (pAd->CommonCfg.bWmmCapable)
1095 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1097 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1102 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1104 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1105 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1106 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1108 // Lost AP, send disconnect & link down event
1109 LinkDown(pAd, FALSE);
1112 union iwreq_data wrqu;
1113 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1114 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1117 MlmeAutoReconnectLastSSID(pAd);
1119 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1121 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1122 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1123 MlmeAutoReconnectLastSSID(pAd);
1126 // Add auto seamless roaming
1127 if (pAd->StaCfg.bFastRoaming)
1129 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1131 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));
1133 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1135 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1139 else if (ADHOC_ON(pAd))
1141 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1142 // the "TX BEACON competition" for the entire past 1 sec.
1143 // So that even when ASIC's BEACONgen engine been blocked
1144 // by peer's BEACON due to slower system clock, this STA still can send out
1145 // minimum BEACON to tell the peer I'm alive.
1146 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1147 // EnqueueBeaconFrame(pAd); // software send BEACON
1149 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1150 // restore outgoing BEACON to support B/G-mixed mode
1151 if ((pAd->CommonCfg.Channel <= 14) &&
1152 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1153 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1154 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1156 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1157 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1158 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1159 MlmeUpdateTxRates(pAd, FALSE, 0);
1160 MakeIbssBeacon(pAd); // re-build BEACON frame
1161 AsicEnableIbssSync(pAd); // copy to on-chip memory
1162 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1165 #ifdef DOT11_N_SUPPORT
1166 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1168 if ((pAd->StaCfg.AdhocBGJoined) &&
1169 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1171 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1172 pAd->StaCfg.AdhocBGJoined = FALSE;
1175 if ((pAd->StaCfg.Adhoc20NJoined) &&
1176 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1178 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1179 pAd->StaCfg.Adhoc20NJoined = FALSE;
1182 #endif // DOT11_N_SUPPORT //
1185 if ((pAd->CommonCfg.Channel > 14)
1186 && (pAd->CommonCfg.bIEEE80211H == 1)
1187 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1189 RadarDetectPeriodic(pAd);
1192 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1193 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1195 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1196 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1198 MLME_START_REQ_STRUCT StartReq;
1200 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1201 LinkDown(pAd, FALSE);
1203 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1204 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1205 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1208 else // no INFRA nor ADHOC connection
1211 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1212 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1213 goto SKIP_AUTO_SCAN_CONN;
1215 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1217 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1218 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1219 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1221 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1223 MLME_SCAN_REQ_STRUCT ScanReq;
1225 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1227 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1228 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1229 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1230 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1231 // Reset Missed scan number
1232 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1234 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1235 MlmeAutoReconnectLastSSID(pAd);
1237 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1239 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1242 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1246 MlmeAutoReconnectLastSSID(pAd);
1252 SKIP_AUTO_SCAN_CONN:
1254 #ifdef DOT11_N_SUPPORT
1255 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1257 pAd->MacTab.fAnyBASession = TRUE;
1258 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1260 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1262 pAd->MacTab.fAnyBASession = FALSE;
1263 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1265 #endif // DOT11_N_SUPPORT //
1272 IN PVOID SystemSpecific1,
1273 IN PVOID FunctionContext,
1274 IN PVOID SystemSpecific2,
1275 IN PVOID SystemSpecific3)
1278 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1280 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1281 RTMP_IndicateMediaState(pAd);
1282 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1285 // IRQL = DISPATCH_LEVEL
1287 IN PRTMP_ADAPTER pAd)
1289 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1290 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1292 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1294 MLME_CNTL_STATE_MACHINE,
1295 OID_802_11_BSSID_LIST_SCAN,
1298 RT28XX_MLME_HANDLER(pAd);
1302 // IRQL = DISPATCH_LEVEL
1303 VOID MlmeAutoReconnectLastSSID(
1304 IN PRTMP_ADAPTER pAd)
1308 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1309 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1310 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1312 NDIS_802_11_SSID OidSsid;
1313 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1314 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1316 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1318 MLME_CNTL_STATE_MACHINE,
1320 sizeof(NDIS_802_11_SSID),
1322 RT28XX_MLME_HANDLER(pAd);
1327 ==========================================================================
1328 Validate SSID for connection try and rescan purpose
1329 Valid SSID will have visible chars only.
1330 The valid length is from 0 to 32.
1331 IRQL = DISPATCH_LEVEL
1332 ==========================================================================
1334 BOOLEAN MlmeValidateSSID(
1340 if (SsidLen > MAX_LEN_OF_SSID)
1343 // Check each character value
1344 for (index = 0; index < SsidLen; index++)
1346 if (pSsid[index] < 0x20)
1354 VOID MlmeSelectTxRateTable(
1355 IN PRTMP_ADAPTER pAd,
1356 IN PMAC_TABLE_ENTRY pEntry,
1358 IN PUCHAR pTableSize,
1359 IN PUCHAR pInitTxRateIdx)
1363 // decide the rate table for tuning
1364 if (pAd->CommonCfg.TxRateTableSize > 0)
1366 *ppTable = RateSwitchTable;
1367 *pTableSize = RateSwitchTable[0];
1368 *pInitTxRateIdx = RateSwitchTable[1];
1373 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1375 #ifdef DOT11_N_SUPPORT
1376 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1377 !pAd->StaCfg.AdhocBOnlyJoined &&
1378 !pAd->StaCfg.AdhocBGJoined &&
1379 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1380 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1382 *ppTable = RateSwitchTable11N1S;
1383 *pTableSize = RateSwitchTable11N1S[0];
1384 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1387 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1388 !pAd->StaCfg.AdhocBOnlyJoined &&
1389 !pAd->StaCfg.AdhocBGJoined &&
1390 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1391 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1392 (pAd->Antenna.field.TxPath == 2))
1394 if (pAd->LatchRfRegs.Channel <= 14)
1396 *ppTable = RateSwitchTable11N2S;
1397 *pTableSize = RateSwitchTable11N2S[0];
1398 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1402 *ppTable = RateSwitchTable11N2SForABand;
1403 *pTableSize = RateSwitchTable11N2SForABand[0];
1404 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1409 #endif // DOT11_N_SUPPORT //
1410 if (pAd->CommonCfg.PhyMode == PHY_11B)
1412 *ppTable = RateSwitchTable11B;
1413 *pTableSize = RateSwitchTable11B[0];
1414 *pInitTxRateIdx = RateSwitchTable11B[1];
1417 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1419 // USe B Table when Only b-only Station in my IBSS .
1420 *ppTable = RateSwitchTable11B;
1421 *pTableSize = RateSwitchTable11B[0];
1422 *pInitTxRateIdx = RateSwitchTable11B[1];
1425 else if (pAd->LatchRfRegs.Channel <= 14)
1427 *ppTable = RateSwitchTable11BG;
1428 *pTableSize = RateSwitchTable11BG[0];
1429 *pInitTxRateIdx = RateSwitchTable11BG[1];
1434 *ppTable = RateSwitchTable11G;
1435 *pTableSize = RateSwitchTable11G[0];
1436 *pInitTxRateIdx = RateSwitchTable11G[1];
1442 #ifdef DOT11_N_SUPPORT
1443 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1444 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1446 *ppTable = RateSwitchTable11BGN1S;
1447 *pTableSize = RateSwitchTable11BGN1S[0];
1448 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1453 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1454 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1456 if (pAd->LatchRfRegs.Channel <= 14)
1458 *ppTable = RateSwitchTable11BGN2S;
1459 *pTableSize = RateSwitchTable11BGN2S[0];
1460 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1465 *ppTable = RateSwitchTable11BGN2SForABand;
1466 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1467 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1473 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1475 *ppTable = RateSwitchTable11N1S;
1476 *pTableSize = RateSwitchTable11N1S[0];
1477 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1482 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1484 if (pAd->LatchRfRegs.Channel <= 14)
1486 *ppTable = RateSwitchTable11N2S;
1487 *pTableSize = RateSwitchTable11N2S[0];
1488 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1492 *ppTable = RateSwitchTable11N2SForABand;
1493 *pTableSize = RateSwitchTable11N2SForABand[0];
1494 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1499 #endif // DOT11_N_SUPPORT //
1500 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1501 if ((pEntry->RateLen == 4)
1502 #ifdef DOT11_N_SUPPORT
1503 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1504 #endif // DOT11_N_SUPPORT //
1507 *ppTable = RateSwitchTable11B;
1508 *pTableSize = RateSwitchTable11B[0];
1509 *pInitTxRateIdx = RateSwitchTable11B[1];
1514 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1515 if ((pEntry->RateLen > 8)
1516 #ifdef DOT11_N_SUPPORT
1517 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1518 #endif // DOT11_N_SUPPORT //
1521 *ppTable = RateSwitchTable11BG;
1522 *pTableSize = RateSwitchTable11BG[0];
1523 *pInitTxRateIdx = RateSwitchTable11BG[1];
1528 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1529 if ((pEntry->RateLen == 8)
1530 #ifdef DOT11_N_SUPPORT
1531 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1532 #endif // DOT11_N_SUPPORT //
1535 *ppTable = RateSwitchTable11G;
1536 *pTableSize = RateSwitchTable11G[0];
1537 *pInitTxRateIdx = RateSwitchTable11G[1];
1541 #ifdef DOT11_N_SUPPORT
1542 #endif // DOT11_N_SUPPORT //
1544 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1546 #ifdef DOT11_N_SUPPORT
1547 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1548 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1549 #endif // DOT11_N_SUPPORT //
1551 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1553 *ppTable = RateSwitchTable11B;
1554 *pTableSize = RateSwitchTable11B[0];
1555 *pInitTxRateIdx = RateSwitchTable11B[1];
1557 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1559 *ppTable = RateSwitchTable11G;
1560 *pTableSize = RateSwitchTable11G[0];
1561 *pInitTxRateIdx = RateSwitchTable11G[1];
1566 *ppTable = RateSwitchTable11BG;
1567 *pTableSize = RateSwitchTable11BG[0];
1568 *pInitTxRateIdx = RateSwitchTable11BG[1];
1572 #ifdef DOT11_N_SUPPORT
1573 if (pAd->LatchRfRegs.Channel <= 14)
1575 if (pAd->CommonCfg.TxStream == 1)
1577 *ppTable = RateSwitchTable11N1S;
1578 *pTableSize = RateSwitchTable11N1S[0];
1579 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1580 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1584 *ppTable = RateSwitchTable11N2S;
1585 *pTableSize = RateSwitchTable11N2S[0];
1586 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1587 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
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 = RateSwitchTable11N2SForABand;
1602 *pTableSize = RateSwitchTable11N2SForABand[0];
1603 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1604 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1607 #endif // DOT11_N_SUPPORT //
1608 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1609 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1615 ==========================================================================
1617 This routine checks if there're other APs out there capable for
1618 roaming. Caller should call this routine only when Link up in INFRA mode
1619 and channel quality is below CQI_GOOD_THRESHOLD.
1621 IRQL = DISPATCH_LEVEL
1624 ==========================================================================
1626 VOID MlmeCheckForRoaming(
1627 IN PRTMP_ADAPTER pAd,
1631 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1634 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1635 // put all roaming candidates into RoamTab, and sort in RSSI order
1636 BssTableInit(pRoamTab);
1637 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1639 pBss = &pAd->ScanTab.BssEntry[i];
1641 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1642 continue; // AP disappear
1643 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1644 continue; // RSSI too weak. forget it.
1645 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1646 continue; // skip current AP
1647 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1648 continue; // only AP with stronger RSSI is eligible for roaming
1650 // AP passing all above rules is put into roaming candidate table
1651 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1652 pRoamTab->BssNr += 1;
1655 if (pRoamTab->BssNr > 0)
1657 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1658 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1660 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1661 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1662 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1663 RT28XX_MLME_HANDLER(pAd);
1666 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1670 ==========================================================================
1672 This routine checks if there're other APs out there capable for
1673 roaming. Caller should call this routine only when link up in INFRA mode
1674 and channel quality is below CQI_GOOD_THRESHOLD.
1676 IRQL = DISPATCH_LEVEL
1679 ==========================================================================
1681 VOID MlmeCheckForFastRoaming(
1682 IN PRTMP_ADAPTER pAd,
1686 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1689 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1690 // put all roaming candidates into RoamTab, and sort in RSSI order
1691 BssTableInit(pRoamTab);
1692 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1694 pBss = &pAd->ScanTab.BssEntry[i];
1696 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1697 continue; // RSSI too weak. forget it.
1698 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1699 continue; // skip current AP
1700 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1701 continue; // skip different SSID
1702 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1703 continue; // skip AP without better RSSI
1705 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));
1706 // AP passing all above rules is put into roaming candidate table
1707 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1708 pRoamTab->BssNr += 1;
1711 if (pRoamTab->BssNr > 0)
1713 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1714 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1716 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1717 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1718 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1719 RT28XX_MLME_HANDLER(pAd);
1722 // Maybe site survey required
1725 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1727 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1728 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1729 pAd->StaCfg.ScanCnt = 2;
1730 pAd->StaCfg.LastScanTime = Now;
1735 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1739 ==========================================================================
1741 This routine calculates TxPER, RxPER of the past N-sec period. And
1742 according to the calculation result, ChannelQuality is calculated here
1743 to decide if current AP is still doing the job.
1745 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1747 StaCfg.ChannelQuality - 0..100
1749 IRQL = DISPATCH_LEVEL
1751 NOTE: This routine decide channle quality based on RX CRC error ratio.
1752 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1753 is performed right before this routine, so that this routine can decide
1754 channel quality based on the most up-to-date information
1755 ==========================================================================
1757 VOID MlmeCalculateChannelQuality(
1758 IN PRTMP_ADAPTER pAd,
1761 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1765 ULONG BeaconLostTime = BEACON_LOST_TIME;
1767 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1770 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1772 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1773 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1781 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1782 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1786 // calculate RX PER - don't take RxPER into consideration if too few sample
1788 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1792 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1795 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1797 if (INFRA_ON(pAd) &&
1798 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1799 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1801 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1802 pAd->Mlme.ChannelQuality = 0;
1809 else if (MaxRssi < -90)
1812 NorRssi = (MaxRssi + 90) * 2;
1814 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1815 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1816 TX_WEIGHTING * (100 - TxPRR) +
1817 RX_WEIGHTING* (100 - RxPER)) / 100;
1818 if (pAd->Mlme.ChannelQuality >= 100)
1819 pAd->Mlme.ChannelQuality = 100;
1825 IN PRTMP_ADAPTER pAd,
1826 IN PMAC_TABLE_ENTRY pEntry,
1827 IN PRTMP_TX_RATE_SWITCH pTxRate)
1829 UCHAR MaxMode = MODE_OFDM;
1831 #ifdef DOT11_N_SUPPORT
1832 MaxMode = MODE_HTGREENFIELD;
1834 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1835 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1837 #endif // DOT11_N_SUPPORT //
1838 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1840 if (pTxRate->CurrMCS < MCS_AUTO)
1841 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1843 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1844 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1848 // If peer adhoc is b-only mode, we can't send 11g rate.
1849 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1850 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1853 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1855 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1856 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1857 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1859 // Patch speed error in status page
1860 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1864 if (pTxRate->Mode <= MaxMode)
1865 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1867 #ifdef DOT11_N_SUPPORT
1868 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1869 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1871 #endif // DOT11_N_SUPPORT //
1872 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1874 #ifdef DOT11_N_SUPPORT
1875 // Reexam each bandwidth's SGI support.
1876 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1878 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1879 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1880 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1881 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1884 // Turn RTS/CTS rate to 6Mbps.
1885 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1887 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1888 if (pAd->MacTab.fAnyBASession)
1890 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1894 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1897 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1899 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1900 if (pAd->MacTab.fAnyBASession)
1902 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1906 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1909 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1911 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1914 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1916 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1918 #endif // DOT11_N_SUPPORT //
1920 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1921 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1922 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1923 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1924 #ifdef DOT11_N_SUPPORT
1925 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1926 pAd->WIFItestbed.bGreenField)
1927 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1928 #endif // DOT11_N_SUPPORT //
1931 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1935 ==========================================================================
1937 This routine calculates the acumulated TxPER of eaxh TxRate. And
1938 according to the calculation result, change CommonCfg.TxRate which
1939 is the stable TX Rate we expect the Radio situation could sustained.
1941 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1945 IRQL = DISPATCH_LEVEL
1948 call this routine every second
1949 ==========================================================================
1951 VOID MlmeDynamicTxRateSwitching(
1952 IN PRTMP_ADAPTER pAd)
1954 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1955 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1956 ULONG TxErrorRatio = 0;
1957 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1958 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1960 UCHAR TableSize = 0;
1961 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1962 CHAR Rssi, RssiOffset = 0;
1963 TX_STA_CNT1_STRUC StaTx1;
1964 TX_STA_CNT0_STRUC TxStaCnt0;
1965 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1966 MAC_TABLE_ENTRY *pEntry;
1968 /*if (pAd->Antenna.field.RxPath > 1)
1969 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
1971 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
1974 // walk through MAC table, see if need to change AP's TX rate toward each entry
1976 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1978 pEntry = &pAd->MacTab.Content[i];
1980 // check if this entry need to switch rate automatically
1981 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1984 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1986 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
1988 // Update statistic counter
1989 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1990 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1991 pAd->bUpdateBcnCntDone = TRUE;
1992 TxRetransmit = StaTx1.field.TxRetransmit;
1993 TxSuccess = StaTx1.field.TxSuccess;
1994 TxFailCount = TxStaCnt0.field.TxFailCount;
1995 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1997 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1998 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1999 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2000 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2001 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2002 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2004 // if no traffic in the past 1-sec period, don't change TX rate,
2005 // but clear all bad history. because the bad history may affect the next
2006 // Chariot throughput test
2007 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2008 pAd->RalinkCounters.OneSecTxRetryOkCount +
2009 pAd->RalinkCounters.OneSecTxFailCount;
2012 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2016 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2018 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2019 pEntry->OneSecTxRetryOkCount +
2020 pEntry->OneSecTxFailCount;
2023 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2026 CurrRateIdx = pEntry->CurrTxRateIndex;
2028 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2030 if (CurrRateIdx >= TableSize)
2032 CurrRateIdx = TableSize - 1;
2035 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2036 // So need to sync here.
2037 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2038 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2039 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2043 // Need to sync Real Tx rate and our record.
2044 // Then return for next DRS.
2045 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2046 pEntry->CurrTxRateIndex = InitTxRateIdx;
2047 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2049 // reset all OneSecTx counters
2050 RESET_ONE_SEC_TX_CNT(pEntry);
2054 // decide the next upgrade rate and downgrade rate, if any
2055 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2057 UpRateIdx = CurrRateIdx + 1;
2058 DownRateIdx = CurrRateIdx -1;
2060 else if (CurrRateIdx == 0)
2062 UpRateIdx = CurrRateIdx + 1;
2063 DownRateIdx = CurrRateIdx;
2065 else if (CurrRateIdx == (TableSize - 1))
2067 UpRateIdx = CurrRateIdx;
2068 DownRateIdx = CurrRateIdx - 1;
2071 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2073 #ifdef DOT11_N_SUPPORT
2074 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2076 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2077 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2080 #endif // DOT11_N_SUPPORT //
2082 TrainUp = pCurrTxRate->TrainUp;
2083 TrainDown = pCurrTxRate->TrainDown;
2086 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2089 // Keep the last time TxRateChangeAction status.
2091 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2096 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2097 // (criteria copied from RT2500 for Netopia case)
2099 if (TxTotalCnt <= 15)
2103 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2104 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2105 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2106 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2108 // check the existence and index of each needed MCS
2109 while (idx < pTable[0])
2111 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2113 if (pCurrTxRate->CurrMCS == MCS_0)
2117 else if (pCurrTxRate->CurrMCS == MCS_1)
2121 else if (pCurrTxRate->CurrMCS == MCS_2)
2125 else if (pCurrTxRate->CurrMCS == MCS_3)
2129 else if (pCurrTxRate->CurrMCS == MCS_4)
2133 else if (pCurrTxRate->CurrMCS == MCS_5)
2137 else if (pCurrTxRate->CurrMCS == MCS_6)
2141 //else if (pCurrTxRate->CurrMCS == MCS_7)
2142 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2146 else if (pCurrTxRate->CurrMCS == MCS_12)
2150 else if (pCurrTxRate->CurrMCS == MCS_13)
2154 else if (pCurrTxRate->CurrMCS == MCS_14)
2158 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2159 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
2163 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2167 else if (pCurrTxRate->CurrMCS == MCS_21)
2171 else if (pCurrTxRate->CurrMCS == MCS_22)
2175 else if (pCurrTxRate->CurrMCS == MCS_23)
2182 if (pAd->LatchRfRegs.Channel <= 14)
2184 if (pAd->NicConfig2.field.ExternalLNAForG)
2195 if (pAd->NicConfig2.field.ExternalLNAForA)
2204 #ifdef DOT11_N_SUPPORT
2206 if ((pTable == RateSwitchTable11BGN3S) ||
2207 (pTable == RateSwitchTable11N3S) ||
2208 (pTable == RateSwitchTable))
2209 {// N mode with 3 stream // 3*3
2210 if (MCS23 && (Rssi >= -70))
2212 else if (MCS22 && (Rssi >= -72))
2214 else if (MCS21 && (Rssi >= -76))
2216 else if (MCS20 && (Rssi >= -78))
2218 else if (MCS4 && (Rssi >= -82))
2220 else if (MCS3 && (Rssi >= -84))
2222 else if (MCS2 && (Rssi >= -86))
2224 else if (MCS1 && (Rssi >= -88))
2229 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2230 {// N mode with 2 stream
2231 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2233 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2235 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2237 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2239 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2241 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2243 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2245 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2250 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2251 {// N mode with 1 stream
2252 if (MCS7 && (Rssi > (-72+RssiOffset)))
2254 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2256 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2258 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2260 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2262 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2264 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2270 #endif // DOT11_N_SUPPORT //
2272 if (MCS7 && (Rssi > -70))
2274 else if (MCS6 && (Rssi > -74))
2276 else if (MCS5 && (Rssi > -78))
2278 else if (MCS4 && (Rssi > -82))
2280 else if (MCS4 == 0) // for B-only mode
2282 else if (MCS3 && (Rssi > -85))
2284 else if (MCS2 && (Rssi > -87))
2286 else if (MCS1 && (Rssi > -90))
2293 pEntry->CurrTxRateIndex = TxRateIdx;
2294 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2295 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2298 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2299 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2300 pEntry->fLastSecAccordingRSSI = TRUE;
2301 // reset all OneSecTx counters
2302 RESET_ONE_SEC_TX_CNT(pEntry);
2307 if (pEntry->fLastSecAccordingRSSI == TRUE)
2309 pEntry->fLastSecAccordingRSSI = FALSE;
2310 pEntry->LastSecTxRateChangeAction = 0;
2311 // reset all OneSecTx counters
2312 RESET_ONE_SEC_TX_CNT(pEntry);
2319 BOOLEAN bTrainUpDown = FALSE;
2321 pEntry->CurrTxRateStableTime ++;
2323 // downgrade TX quality if PER >= Rate-Down threshold
2324 if (TxErrorRatio >= TrainDown)
2326 bTrainUpDown = TRUE;
2327 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2329 // upgrade TX quality if PER <= Rate-Up threshold
2330 else if (TxErrorRatio <= TrainUp)
2332 bTrainUpDown = TRUE;
2333 bUpgradeQuality = TRUE;
2334 if (pEntry->TxQuality[CurrRateIdx])
2335 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2337 if (pEntry->TxRateUpPenalty)
2338 pEntry->TxRateUpPenalty --;
2339 else if (pEntry->TxQuality[UpRateIdx])
2340 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2343 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2347 // perform DRS - consider TxRate Down first, then rate up.
2348 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2350 pEntry->CurrTxRateIndex = DownRateIdx;
2352 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2354 pEntry->CurrTxRateIndex = UpRateIdx;
2359 // if rate-up happen, clear all bad history of all TX rates
2360 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2362 pEntry->CurrTxRateStableTime = 0;
2363 pEntry->TxRateUpPenalty = 0;
2364 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2365 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2366 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2369 // For TxRate fast train up
2371 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2373 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2375 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2377 bTxRateChanged = TRUE;
2379 // if rate-down happen, only clear DownRate's bad history
2380 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2382 pEntry->CurrTxRateStableTime = 0;
2383 pEntry->TxRateUpPenalty = 0; // no penalty
2384 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2385 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2386 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2389 // For TxRate fast train down
2391 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2393 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2395 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2397 bTxRateChanged = TRUE;
2401 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2402 bTxRateChanged = FALSE;
2405 pEntry->LastTxOkCount = TxSuccess;
2407 // reset all OneSecTx counters
2408 RESET_ONE_SEC_TX_CNT(pEntry);
2410 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2411 if (bTxRateChanged && pNextTxRate)
2413 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2419 ========================================================================
2420 Routine Description:
2421 Station side, Auto TxRate faster train up timer call back function.
2424 SystemSpecific1 - Not used.
2425 FunctionContext - Pointer to our Adapter context.
2426 SystemSpecific2 - Not used.
2427 SystemSpecific3 - Not used.
2432 ========================================================================
2434 VOID StaQuickResponeForRateUpExec(
2435 IN PVOID SystemSpecific1,
2436 IN PVOID FunctionContext,
2437 IN PVOID SystemSpecific2,
2438 IN PVOID SystemSpecific3)
2440 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2441 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2443 ULONG TxErrorRatio = 0;
2444 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2445 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2447 UCHAR TableSize = 0;
2448 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2449 TX_STA_CNT1_STRUC StaTx1;
2450 TX_STA_CNT0_STRUC TxStaCnt0;
2452 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2453 MAC_TABLE_ENTRY *pEntry;
2456 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2459 // walk through MAC table, see if need to change AP's TX rate toward each entry
2461 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2463 pEntry = &pAd->MacTab.Content[i];
2465 // check if this entry need to switch rate automatically
2466 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2469 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2470 if (pAd->Antenna.field.TxPath > 1)
2471 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2473 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2475 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2477 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2479 // decide the next upgrade rate and downgrade rate, if any
2480 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2482 UpRateIdx = CurrRateIdx + 1;
2483 DownRateIdx = CurrRateIdx -1;
2485 else if (CurrRateIdx == 0)
2487 UpRateIdx = CurrRateIdx + 1;
2488 DownRateIdx = CurrRateIdx;
2490 else if (CurrRateIdx == (TableSize - 1))
2492 UpRateIdx = CurrRateIdx;
2493 DownRateIdx = CurrRateIdx - 1;
2496 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2498 #ifdef DOT11_N_SUPPORT
2499 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2501 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2502 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2505 #endif // DOT11_N_SUPPORT //
2507 TrainUp = pCurrTxRate->TrainUp;
2508 TrainDown = pCurrTxRate->TrainDown;
2511 if (pAd->MacTab.Size == 1)
2513 // Update statistic counter
2514 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2515 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2517 TxRetransmit = StaTx1.field.TxRetransmit;
2518 TxSuccess = StaTx1.field.TxSuccess;
2519 TxFailCount = TxStaCnt0.field.TxFailCount;
2520 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2522 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2523 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2524 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2525 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2526 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2527 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2530 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2534 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2535 pEntry->OneSecTxRetryOkCount +
2536 pEntry->OneSecTxFailCount;
2539 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2544 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2545 // (criteria copied from RT2500 for Netopia case)
2547 if (TxTotalCnt <= 12)
2549 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2550 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2552 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2554 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2555 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2557 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2559 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2562 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2568 ULONG OneSecTxNoRetryOKRationCount;
2570 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2575 // downgrade TX quality if PER >= Rate-Down threshold
2576 if (TxErrorRatio >= TrainDown)
2578 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2581 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2583 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2585 // perform DRS - consider TxRate Down first, then rate up.
2586 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2588 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2590 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2591 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2596 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2598 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2602 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2604 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2609 // if rate-up happen, clear all bad history of all TX rates
2610 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2612 pAd->DrsCounters.TxRateUpPenalty = 0;
2613 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2614 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2616 // if rate-down happen, only clear DownRate's bad history
2617 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2619 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2621 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2622 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2623 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2627 bTxRateChanged = FALSE;
2630 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2631 if (bTxRateChanged && pNextTxRate)
2633 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2639 ==========================================================================
2641 This routine is executed periodically inside MlmePeriodicExec() after
2642 association with an AP.
2643 It checks if StaCfg.Psm is consistent with user policy (recorded in
2644 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2645 there're some conditions to consider:
2646 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2647 the time when Mibss==TRUE
2648 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2649 if outgoing traffic available in TxRing or MgmtRing.
2651 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2653 IRQL = DISPATCH_LEVEL
2655 ==========================================================================
2657 VOID MlmeCheckPsmChange(
2658 IN PRTMP_ADAPTER pAd,
2664 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2665 // 2. user wants either MAX_PSP or FAST_PSP
2666 // 3. but current psm is not in PWR_SAVE
2667 // 4. CNTL state machine is not doing SCANning
2668 // 5. no TX SUCCESS event for the past 1-sec period
2669 #ifdef NDIS51_MINIPORT
2670 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2671 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2674 PowerMode = pAd->StaCfg.WindowsPowerMode;
2676 if (INFRA_ON(pAd) &&
2677 (PowerMode != Ndis802_11PowerModeCAM) &&
2678 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2679 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2681 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2682 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2683 MlmeSetPsmBit(pAd, PWR_SAVE);
2684 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2686 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2690 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2695 // IRQL = PASSIVE_LEVEL
2696 // IRQL = DISPATCH_LEVEL
2698 IN PRTMP_ADAPTER pAd,
2701 AUTO_RSP_CFG_STRUC csr4;
2703 pAd->StaCfg.Psm = psm;
2704 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2705 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2706 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2707 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2710 // IRQL = DISPATCH_LEVEL
2711 VOID MlmeSetTxPreamble(
2712 IN PRTMP_ADAPTER pAd,
2713 IN USHORT TxPreamble)
2715 AUTO_RSP_CFG_STRUC csr4;
2718 // Always use Long preamble before verifiation short preamble functionality works well.
2719 // Todo: remove the following line if short preamble functionality works
2721 //TxPreamble = Rt802_11PreambleLong;
2723 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2724 if (TxPreamble == Rt802_11PreambleLong)
2726 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2727 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2728 csr4.field.AutoResponderPreamble = 0;
2732 // NOTE: 1Mbps should always use long preamble
2733 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2734 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2735 csr4.field.AutoResponderPreamble = 1;
2738 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2742 ==========================================================================
2744 Update basic rate bitmap
2745 ==========================================================================
2748 VOID UpdateBasicRateBitmap(
2749 IN PRTMP_ADAPTER pAdapter)
2752 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2753 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2754 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2755 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2756 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2759 /* if A mode, always use fix BasicRateBitMap */
2760 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2761 if (pAdapter->CommonCfg.Channel > 14)
2762 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2765 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2767 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2771 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2777 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2779 if (bitmap & (1 << i))
2781 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2783 if (sup_p[j] == rate[i])
2788 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2790 if (ext_p[j] == rate[i])
2796 } /* End of UpdateBasicRateBitmap */
2798 // IRQL = PASSIVE_LEVEL
2799 // IRQL = DISPATCH_LEVEL
2800 // bLinkUp is to identify the inital link speed.
2801 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2802 VOID MlmeUpdateTxRates(
2803 IN PRTMP_ADAPTER pAd,
2808 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2809 UCHAR MinSupport = RATE_54;
2810 ULONG BasicRateBitmap = 0;
2811 UCHAR CurrBasicRate = RATE_1;
2812 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2813 PHTTRANSMIT_SETTING pHtPhy = NULL;
2814 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2815 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2816 BOOLEAN *auto_rate_cur_p;
2817 UCHAR HtMcs = MCS_AUTO;
2819 // find max desired rate
2820 UpdateBasicRateBitmap(pAd);
2823 auto_rate_cur_p = NULL;
2824 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2826 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2828 case 2: Rate = RATE_1; num++; break;
2829 case 4: Rate = RATE_2; num++; break;
2830 case 11: Rate = RATE_5_5; num++; break;
2831 case 22: Rate = RATE_11; num++; break;
2832 case 12: Rate = RATE_6; num++; break;
2833 case 18: Rate = RATE_9; num++; break;
2834 case 24: Rate = RATE_12; num++; break;
2835 case 36: Rate = RATE_18; num++; break;
2836 case 48: Rate = RATE_24; num++; break;
2837 case 72: Rate = RATE_36; num++; break;
2838 case 96: Rate = RATE_48; num++; break;
2839 case 108: Rate = RATE_54; num++; break;
2840 //default: Rate = RATE_1; break;
2842 if (MaxDesire < Rate) MaxDesire = Rate;
2845 //===========================================================================
2846 //===========================================================================
2847 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2849 pHtPhy = &pAd->StaCfg.HTPhyMode;
2850 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2851 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2853 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2854 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2856 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2857 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2858 (MaxDesire > RATE_11))
2860 MaxDesire = RATE_11;
2864 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2865 pMinHtPhy->word = 0;
2866 pMaxHtPhy->word = 0;
2869 // Auto rate switching is enabled only if more than one DESIRED RATES are
2870 // specified; otherwise disabled
2873 *auto_rate_cur_p = FALSE;
2877 *auto_rate_cur_p = TRUE;
2881 if (HtMcs != MCS_AUTO)
2883 *auto_rate_cur_p = FALSE;
2887 *auto_rate_cur_p = TRUE;
2891 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2893 pSupRate = &pAd->StaActive.SupRate[0];
2894 pExtRate = &pAd->StaActive.ExtRate[0];
2895 SupRateLen = pAd->StaActive.SupRateLen;
2896 ExtRateLen = pAd->StaActive.ExtRateLen;
2900 pSupRate = &pAd->CommonCfg.SupRate[0];
2901 pExtRate = &pAd->CommonCfg.ExtRate[0];
2902 SupRateLen = pAd->CommonCfg.SupRateLen;
2903 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2906 // find max supported rate
2907 for (i=0; i<SupRateLen; i++)
2909 switch (pSupRate[i] & 0x7f)
2911 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2912 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2913 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2914 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2915 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2916 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2917 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2918 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2919 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2920 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2921 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2922 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2923 default: Rate = RATE_1; break;
2925 if (MaxSupport < Rate) MaxSupport = Rate;
2927 if (MinSupport > Rate) MinSupport = Rate;
2930 for (i=0; i<ExtRateLen; i++)
2932 switch (pExtRate[i] & 0x7f)
2934 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2935 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2936 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2937 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2938 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2939 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2940 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2941 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2942 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2943 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2944 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2945 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2946 default: Rate = RATE_1; break;
2948 if (MaxSupport < Rate) MaxSupport = Rate;
2950 if (MinSupport > Rate) MinSupport = Rate;
2953 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2955 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2956 // the DURATION field of outgoing uniicast DATA/MGMT frame
2957 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2959 if (BasicRateBitmap & (0x01 << i))
2960 CurrBasicRate = (UCHAR)i;
2961 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2964 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2965 // max tx rate = min {max desire rate, max supported rate}
2966 if (MaxSupport < MaxDesire)
2967 pAd->CommonCfg.MaxTxRate = MaxSupport;
2969 pAd->CommonCfg.MaxTxRate = MaxDesire;
2971 pAd->CommonCfg.MinTxRate = MinSupport;
2972 if (*auto_rate_cur_p)
2976 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2977 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2979 if (bLinkUp == TRUE)
2980 pAd->CommonCfg.TxRate = RATE_24;
2982 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2985 pAd->CommonCfg.TxRate = RATE_11;
2987 pAd->CommonCfg.TxRate = RATE_24;
2989 // should never exceed MaxTxRate (consider 11B-only mode)
2990 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2991 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2993 pAd->CommonCfg.TxRateIndex = 0;
2997 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2998 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2999 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3001 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3002 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3003 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3004 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3007 if (pAd->CommonCfg.TxRate <= RATE_11)
3009 pMaxHtPhy->field.MODE = MODE_CCK;
3010 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3011 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3015 pMaxHtPhy->field.MODE = MODE_OFDM;
3016 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3017 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3018 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3020 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3023 pHtPhy->word = (pMaxHtPhy->word);
3024 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3026 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3027 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3028 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3032 switch (pAd->CommonCfg.PhyMode)
3034 case PHY_11BG_MIXED:
3036 #ifdef DOT11_N_SUPPORT
3037 case PHY_11BGN_MIXED:
3038 #endif // DOT11_N_SUPPORT //
3039 pAd->CommonCfg.MlmeRate = RATE_1;
3040 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3041 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3042 pAd->CommonCfg.RtsRate = RATE_11;
3046 #ifdef DOT11_N_SUPPORT
3047 case PHY_11AGN_MIXED:
3048 case PHY_11GN_MIXED:
3050 case PHY_11AN_MIXED:
3052 #endif // DOT11_N_SUPPORT //
3053 pAd->CommonCfg.MlmeRate = RATE_6;
3054 pAd->CommonCfg.RtsRate = RATE_6;
3055 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3056 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3058 case PHY_11ABG_MIXED:
3059 #ifdef DOT11_N_SUPPORT
3060 case PHY_11ABGN_MIXED:
3061 #endif // DOT11_N_SUPPORT //
3062 if (pAd->CommonCfg.Channel <= 14)
3064 pAd->CommonCfg.MlmeRate = RATE_1;
3065 pAd->CommonCfg.RtsRate = RATE_1;
3066 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3067 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3071 pAd->CommonCfg.MlmeRate = RATE_6;
3072 pAd->CommonCfg.RtsRate = RATE_6;
3073 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3074 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3078 pAd->CommonCfg.MlmeRate = RATE_6;
3079 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3080 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3081 pAd->CommonCfg.RtsRate = RATE_1;
3085 // Keep Basic Mlme Rate.
3087 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3088 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3089 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3091 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3092 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3095 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3096 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3097 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3098 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3099 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3100 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3101 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 ));
3104 #ifdef DOT11_N_SUPPORT
3106 ==========================================================================
3108 This function update HT Rate setting.
3109 Input Wcid value is valid for 2 case :
3110 1. it's used for Station in infra mode that copy AP rate to Mactable.
3111 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3113 IRQL = DISPATCH_LEVEL
3115 ==========================================================================
3117 VOID MlmeUpdateHtTxRates(
3118 IN PRTMP_ADAPTER pAd,
3121 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3123 RT_HT_CAPABILITY *pRtHtCap = NULL;
3124 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3127 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3128 PHTTRANSMIT_SETTING pHtPhy = NULL;
3129 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3130 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3131 BOOLEAN *auto_rate_cur_p;
3133 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3135 auto_rate_cur_p = NULL;
3137 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3139 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3140 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3141 pHtPhy = &pAd->StaCfg.HTPhyMode;
3142 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3143 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3145 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3148 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3150 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3153 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3154 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3155 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3156 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3157 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3158 pMaxHtPhy->field.STBC = STBC_USE;
3160 pMaxHtPhy->field.STBC = STBC_NONE;
3164 if (pDesireHtPhy->bHtEnable == FALSE)
3167 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3168 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3169 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3170 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3171 pMaxHtPhy->field.STBC = STBC_USE;
3173 pMaxHtPhy->field.STBC = STBC_NONE;
3176 // Decide MAX ht rate.
3177 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3178 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3180 pMaxHtPhy->field.MODE = MODE_HTMIX;
3182 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3183 pMaxHtPhy->field.BW = BW_40;
3185 pMaxHtPhy->field.BW = BW_20;
3187 if (pMaxHtPhy->field.BW == BW_20)
3188 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3190 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3192 for (i=23; i>=0; i--) // 3*3
3195 bitmask = (1<<(i-(j*8)));
3197 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3199 pMaxHtPhy->field.MCS = i;
3207 // Copy MIN ht rate. rt2860???
3208 pMinHtPhy->field.BW = BW_20;
3209 pMinHtPhy->field.MCS = 0;
3210 pMinHtPhy->field.STBC = 0;
3211 pMinHtPhy->field.ShortGI = 0;
3212 //If STA assigns fixed rate. update to fixed here.
3213 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3215 if (pDesireHtPhy->MCSSet[4] != 0)
3217 pMaxHtPhy->field.MCS = 32;
3218 pMinHtPhy->field.MCS = 32;
3219 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3222 for (i=23; (CHAR)i >= 0; i--) // 3*3
3225 bitmask = (1<<(i-(j*8)));
3226 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3228 pMaxHtPhy->field.MCS = i;
3229 pMinHtPhy->field.MCS = i;
3238 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3239 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3240 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3241 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3242 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3244 // use default now. rt2860
3245 if (pDesireHtPhy->MCSSet[0] != 0xff)
3246 *auto_rate_cur_p = FALSE;
3248 *auto_rate_cur_p = TRUE;
3250 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3251 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3252 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3253 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3255 #endif // DOT11_N_SUPPORT //
3257 // IRQL = DISPATCH_LEVEL
3259 IN PRTMP_ADAPTER pAd)
3261 RT28XX_MLME_RADIO_OFF(pAd);
3264 // IRQL = DISPATCH_LEVEL
3266 IN PRTMP_ADAPTER pAd)
3268 RT28XX_MLME_RADIO_ON(pAd);
3271 // ===========================================================================================
3273 // ===========================================================================================
3276 /*! \brief initialize BSS table
3277 * \param p_tab pointer to the table
3282 IRQL = PASSIVE_LEVEL
3283 IRQL = DISPATCH_LEVEL
3292 Tab->BssOverlapNr = 0;
3293 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3295 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3296 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3300 #ifdef DOT11_N_SUPPORT
3302 IN PRTMP_ADAPTER pAd,
3307 Tab->numAsOriginator = 0;
3308 Tab->numAsRecipient = 0;
3309 NdisAllocateSpinLock(&pAd->BATabLock);
3310 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3312 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3313 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3315 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3317 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3320 #endif // DOT11_N_SUPPORT //
3322 /*! \brief search the BSS table by SSID
3323 * \param p_tab pointer to the bss table
3324 * \param ssid SSID string
3325 * \return index of the table, BSS_NOT_FOUND if not in the table
3328 * \note search by sequential search
3330 IRQL = DISPATCH_LEVEL
3333 ULONG BssTableSearch(
3340 for (i = 0; i < Tab->BssNr; i++)
3343 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3344 // We should distinguish this case.
3346 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3347 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3348 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3353 return (ULONG)BSS_NOT_FOUND;
3356 ULONG BssSsidTableSearch(
3365 for (i = 0; i < Tab->BssNr; i++)
3368 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3369 // We should distinguish this case.
3371 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3372 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3373 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3374 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3379 return (ULONG)BSS_NOT_FOUND;
3382 ULONG BssTableSearchWithSSID(
3391 for (i = 0; i < Tab->BssNr; i++)
3393 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3394 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3395 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3396 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3397 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3398 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3403 return (ULONG)BSS_NOT_FOUND;
3406 // IRQL = DISPATCH_LEVEL
3407 VOID BssTableDeleteEntry(
3408 IN OUT BSS_TABLE *Tab,
3414 for (i = 0; i < Tab->BssNr; i++)
3416 if ((Tab->BssEntry[i].Channel == Channel) &&
3417 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3419 for (j = i; j < Tab->BssNr - 1; j++)
3421 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3423 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3430 #ifdef DOT11_N_SUPPORT
3432 ========================================================================
3433 Routine Description:
3434 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3437 // IRQL = DISPATCH_LEVEL
3438 ========================================================================
3440 VOID BATableDeleteORIEntry(
3441 IN OUT PRTMP_ADAPTER pAd,
3442 IN BA_ORI_ENTRY *pBAORIEntry)
3445 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3447 NdisAcquireSpinLock(&pAd->BATabLock);
3448 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3450 pAd->BATable.numAsOriginator -= 1;
3451 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3452 // Erase Bitmap flag.
3454 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3455 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3456 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3457 pBAORIEntry->Token = 1;
3458 // Not clear Sequence here.
3459 NdisReleaseSpinLock(&pAd->BATabLock);
3462 #endif // DOT11_N_SUPPORT //
3470 IRQL = DISPATCH_LEVEL
3474 IN PRTMP_ADAPTER pAd,
3475 OUT BSS_ENTRY *pBss,
3480 IN USHORT BeaconPeriod,
3481 IN PCF_PARM pCfParm,
3483 IN USHORT CapabilityInfo,
3485 IN UCHAR SupRateLen,
3487 IN UCHAR ExtRateLen,
3488 IN HT_CAPABILITY_IE *pHtCapability,
3489 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3490 IN UCHAR HtCapabilityLen,
3491 IN UCHAR AddHtInfoLen,
3492 IN UCHAR NewExtChanOffset,
3495 IN LARGE_INTEGER TimeStamp,
3497 IN PEDCA_PARM pEdcaParm,
3498 IN PQOS_CAPABILITY_PARM pQosCapability,
3499 IN PQBSS_LOAD_PARM pQbssLoad,
3500 IN USHORT LengthVIE,
3501 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3503 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3504 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3508 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3509 // Or send beacon /probe response with SSID len matching real SSID length,
3510 // but SSID is all zero. such as "00-00-00-00" with length 4.
3511 // We have to prevent this case overwrite correct table
3512 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3514 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3515 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3516 pBss->SsidLen = SsidLen;
3522 pBss->BssType = BssType;
3523 pBss->BeaconPeriod = BeaconPeriod;
3524 if (BssType == BSS_INFRA)
3526 if (pCfParm->bValid)
3528 pBss->CfpCount = pCfParm->CfpCount;
3529 pBss->CfpPeriod = pCfParm->CfpPeriod;
3530 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3531 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3536 pBss->AtimWin = AtimWin;
3539 pBss->CapabilityInfo = CapabilityInfo;
3540 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3541 // Combine with AuthMode, they will decide the connection methods.
3542 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3543 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3544 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3545 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3547 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3548 pBss->SupRateLen = SupRateLen;
3549 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3550 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3551 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3552 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3553 pBss->NewExtChanOffset = NewExtChanOffset;
3554 pBss->ExtRateLen = ExtRateLen;
3555 pBss->Channel = Channel;
3556 pBss->CentralChannel = Channel;
3558 // Update CkipFlag. if not exists, the value is 0x0
3559 pBss->CkipFlag = CkipFlag;
3561 // New for microsoft Fixed IEs
3562 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3563 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3564 pBss->FixIEs.Capabilities = CapabilityInfo;
3566 // New for microsoft Variable IEs
3569 pBss->VarIELen = LengthVIE;
3570 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3577 pBss->AddHtInfoLen = 0;
3578 pBss->HtCapabilityLen = 0;
3579 #ifdef DOT11_N_SUPPORT
3580 if (HtCapabilityLen> 0)
3582 pBss->HtCapabilityLen = HtCapabilityLen;
3583 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3584 if (AddHtInfoLen > 0)
3586 pBss->AddHtInfoLen = AddHtInfoLen;
3587 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3589 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3591 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3593 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3595 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3599 #endif // DOT11_N_SUPPORT //
3601 BssCipherParse(pBss);
3605 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3607 pBss->EdcaParm.bValid = FALSE;
3609 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3611 pBss->QosCapability.bValid = FALSE;
3613 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3615 pBss->QbssLoad.bValid = FALSE;
3617 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3623 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3624 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3626 pEid = (PEID_STRUCT) pVIE;
3628 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3633 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3635 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3637 pBss->WpaIE.IELen = 0;
3640 pBss->WpaIE.IELen = pEid->Len + 2;
3641 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3645 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3647 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3649 pBss->RsnIE.IELen = 0;
3652 pBss->RsnIE.IELen = pEid->Len + 2;
3653 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3657 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3658 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3664 * \brief insert an entry into the bss table
3665 * \param p_tab The BSS table
3666 * \param Bssid BSSID
3668 * \param ssid_len Length of SSID
3670 * \param beacon_period
3677 * \param channel_idx
3681 * \note If SSID is identical, the old entry will be replaced by the new one
3683 IRQL = DISPATCH_LEVEL
3686 ULONG BssTableSetEntry(
3687 IN PRTMP_ADAPTER pAd,
3693 IN USHORT BeaconPeriod,
3696 IN USHORT CapabilityInfo,
3698 IN UCHAR SupRateLen,
3700 IN UCHAR ExtRateLen,
3701 IN HT_CAPABILITY_IE *pHtCapability,
3702 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3703 IN UCHAR HtCapabilityLen,
3704 IN UCHAR AddHtInfoLen,
3705 IN UCHAR NewExtChanOffset,
3708 IN LARGE_INTEGER TimeStamp,
3710 IN PEDCA_PARM pEdcaParm,
3711 IN PQOS_CAPABILITY_PARM pQosCapability,
3712 IN PQBSS_LOAD_PARM pQbssLoad,
3713 IN USHORT LengthVIE,
3714 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3718 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3719 if (Idx == BSS_NOT_FOUND)
3721 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3724 // It may happen when BSS Table was full.
3725 // The desired AP will not be added into BSS Table
3726 // In this case, if we found the desired AP then overwrite BSS Table.
3728 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3730 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3731 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3733 Idx = Tab->BssOverlapNr;
3734 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3735 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3736 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3737 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3743 return BSS_NOT_FOUND;
3747 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3748 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3749 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3754 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3755 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3756 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3762 // IRQL = DISPATCH_LEVEL
3763 VOID BssTableSsidSort(
3764 IN PRTMP_ADAPTER pAd,
3765 OUT BSS_TABLE *OutTab,
3770 BssTableInit(OutTab);
3772 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3774 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3775 BOOLEAN bIsHiddenApIncluded = FALSE;
3777 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3778 (pAd->MlmeAux.Channel > 14) &&
3779 RadarChannelCheck(pAd, pInBss->Channel))
3783 bIsHiddenApIncluded = TRUE;
3786 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3787 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3789 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3790 #ifdef DOT11_N_SUPPORT
3791 // 2.4G/5G N only mode
3792 if ((pInBss->HtCapabilityLen == 0) &&
3793 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3795 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3798 #endif // DOT11_N_SUPPORT //
3801 // Check the Authmode first
3802 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3804 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3805 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3809 // Check cipher suite, AP must have more secured cipher than station setting
3810 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3812 // If it's not mixed mode, we should only let BSS pass with the same encryption
3813 if (pInBss->WPA.bMixMode == FALSE)
3814 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3817 // check group cipher
3818 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3819 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3820 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3823 // check pairwise cipher, skip if none matched
3824 // If profile set to AES, let it pass without question.
3825 // If profile set to TKIP, we must find one mateched
3826 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3827 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3828 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3831 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3833 // If it's not mixed mode, we should only let BSS pass with the same encryption
3834 if (pInBss->WPA2.bMixMode == FALSE)
3835 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3838 // check group cipher
3839 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3840 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3841 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3844 // check pairwise cipher, skip if none matched
3845 // If profile set to AES, let it pass without question.
3846 // If profile set to TKIP, we must find one mateched
3847 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3848 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3849 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3853 // Bss Type matched, SSID matched.
3854 // We will check wepstatus for qualification Bss
3855 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3857 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3859 // For the SESv2 case, we will not qualify WepStatus.
3865 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3866 // It definitely will fail. So, skip it.
3867 // CCX also require not even try to connect it!!
3871 #ifdef DOT11_N_SUPPORT
3872 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3873 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3874 if ((pInBss->CentralChannel != pInBss->Channel) &&
3875 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3877 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3879 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3881 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3885 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3891 #endif // DOT11_N_SUPPORT //
3893 // copy matching BSS from InTab to OutTab
3894 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3898 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3900 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3903 #ifdef DOT11_N_SUPPORT
3904 // 2.4G/5G N only mode
3905 if ((pInBss->HtCapabilityLen == 0) &&
3906 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3908 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3911 #endif // DOT11_N_SUPPORT //
3914 // Check the Authmode first
3915 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3917 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3918 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3922 // Check cipher suite, AP must have more secured cipher than station setting
3923 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3925 // If it's not mixed mode, we should only let BSS pass with the same encryption
3926 if (pInBss->WPA.bMixMode == FALSE)
3927 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3930 // check group cipher
3931 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3934 // check pairwise cipher, skip if none matched
3935 // If profile set to AES, let it pass without question.
3936 // If profile set to TKIP, we must find one mateched
3937 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3938 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3939 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3942 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3944 // If it's not mixed mode, we should only let BSS pass with the same encryption
3945 if (pInBss->WPA2.bMixMode == FALSE)
3946 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3949 // check group cipher
3950 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3953 // check pairwise cipher, skip if none matched
3954 // If profile set to AES, let it pass without question.
3955 // If profile set to TKIP, we must find one mateched
3956 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3957 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3958 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3962 // Bss Type matched, SSID matched.
3963 // We will check wepstatus for qualification Bss
3964 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3967 #ifdef DOT11_N_SUPPORT
3968 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3969 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3970 if ((pInBss->CentralChannel != pInBss->Channel) &&
3971 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3973 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3975 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3977 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3980 #endif // DOT11_N_SUPPORT //
3982 // copy matching BSS from InTab to OutTab
3983 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3988 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3992 BssTableSortByRssi(OutTab);
3996 // IRQL = DISPATCH_LEVEL
3997 VOID BssTableSortByRssi(
3998 IN OUT BSS_TABLE *OutTab)
4003 for (i = 0; i < OutTab->BssNr - 1; i++)
4005 for (j = i+1; j < OutTab->BssNr; j++)
4007 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4009 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4010 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4011 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4017 VOID BssCipherParse(
4018 IN OUT PBSS_ENTRY pBss)
4022 PRSN_IE_HEADER_STRUCT pRsnHeader;
4023 PCIPHER_SUITE_STRUCT pCipher;
4024 PAKM_SUITE_STRUCT pAKM;
4027 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4030 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4034 pBss->WepStatus = Ndis802_11WEPEnabled;
4038 pBss->WepStatus = Ndis802_11WEPDisabled;
4040 // Set default to disable & open authentication before parsing variable IE
4041 pBss->AuthMode = Ndis802_11AuthModeOpen;
4042 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4045 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4046 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4047 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4048 pBss->WPA.RsnCapability = 0;
4049 pBss->WPA.bMixMode = FALSE;
4051 // Init WPA2 setting
4052 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4053 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4054 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4055 pBss->WPA2.RsnCapability = 0;
4056 pBss->WPA2.bMixMode = FALSE;
4059 Length = (INT) pBss->VarIELen;
4063 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4064 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4065 pEid = (PEID_STRUCT) pTmp;
4069 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4070 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4076 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4077 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4078 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4079 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4082 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4083 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4084 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4087 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4088 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4089 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4095 // if Cisco IE_WPA, break
4098 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4103 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4105 // if unsupported vendor specific IE
4108 // Skip OUI, version, and multicast suite
4109 // This part should be improved in the future when AP supported multiple cipher suite.
4110 // For now, it's OK since almost all APs have fixed cipher suite supported.
4111 // pTmp = (PUCHAR) pEid->Octet;
4114 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4122 // Parse group cipher
4126 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4129 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4132 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4135 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4140 // number of unicast suite
4143 // skip all unicast cipher suites
4144 //Count = *(PUSHORT) pTmp;
4145 Count = (pTmp[1]<<8) + pTmp[0];
4146 pTmp += sizeof(USHORT);
4148 // Parsing all unicast cipher suite
4153 TmpCipher = Ndis802_11WEPDisabled;
4157 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4158 TmpCipher = Ndis802_11Encryption1Enabled;
4161 TmpCipher = Ndis802_11Encryption2Enabled;
4164 TmpCipher = Ndis802_11Encryption3Enabled;
4169 if (TmpCipher > pBss->WPA.PairCipher)
4171 // Move the lower cipher suite to PairCipherAux
4172 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4173 pBss->WPA.PairCipher = TmpCipher;
4177 pBss->WPA.PairCipherAux = TmpCipher;
4183 // 4. get AKM suite counts
4184 //Count = *(PUSHORT) pTmp;
4185 Count = (pTmp[1]<<8) + pTmp[0];
4186 pTmp += sizeof(USHORT);
4192 // Set AP support WPA mode
4193 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4194 pBss->AuthMode = Ndis802_11AuthModeWPA;
4196 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4199 // Set AP support WPA mode
4200 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4201 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4203 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4210 // Fixed for WPA-None
4211 if (pBss->BssType == BSS_ADHOC)
4213 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4214 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4215 pBss->WepStatus = pBss->WPA.GroupCipher;
4216 // Patched bugs for old driver
4217 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4218 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4221 pBss->WepStatus = pBss->WPA.PairCipher;
4223 // Check the Pair & Group, if different, turn on mixed mode flag
4224 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4225 pBss->WPA.bMixMode = TRUE;
4230 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4232 // 0. Version must be 1
4233 if (le2cpu16(pRsnHeader->Version) != 1)
4235 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4237 // 1. Check group cipher
4238 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4239 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4242 // Parse group cipher
4243 switch (pCipher->Type)
4246 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4249 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4252 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4255 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4260 // set to correct offset for next parsing
4261 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4263 // 2. Get pairwise cipher counts
4264 //Count = *(PUSHORT) pTmp;
4265 Count = (pTmp[1]<<8) + pTmp[0];
4266 pTmp += sizeof(USHORT);
4268 // 3. Get pairwise cipher
4269 // Parsing all unicast cipher suite
4273 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4274 TmpCipher = Ndis802_11WEPDisabled;
4275 switch (pCipher->Type)
4278 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4279 TmpCipher = Ndis802_11Encryption1Enabled;
4282 TmpCipher = Ndis802_11Encryption2Enabled;
4285 TmpCipher = Ndis802_11Encryption3Enabled;
4290 if (TmpCipher > pBss->WPA2.PairCipher)
4292 // Move the lower cipher suite to PairCipherAux
4293 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4294 pBss->WPA2.PairCipher = TmpCipher;
4298 pBss->WPA2.PairCipherAux = TmpCipher;
4300 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4304 // 4. get AKM suite counts
4305 //Count = *(PUSHORT) pTmp;
4306 Count = (pTmp[1]<<8) + pTmp[0];
4307 pTmp += sizeof(USHORT);
4309 // 5. Get AKM ciphers
4310 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4311 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4317 // Set AP support WPA mode
4318 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4319 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4321 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4324 // Set AP support WPA mode
4325 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4326 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4328 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4333 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4335 // Fixed for WPA-None
4336 if (pBss->BssType == BSS_ADHOC)
4338 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4339 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4340 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4341 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4342 pBss->WepStatus = pBss->WPA.GroupCipher;
4343 // Patched bugs for old driver
4344 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4345 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4347 pBss->WepStatus = pBss->WPA2.PairCipher;
4349 // 6. Get RSN capability
4350 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4351 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4352 pTmp += sizeof(USHORT);
4354 // Check the Pair & Group, if different, turn on mixed mode flag
4355 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4356 pBss->WPA2.bMixMode = TRUE;
4362 Length -= (pEid->Len + 2);
4366 // ===========================================================================================
4368 // ===========================================================================================
4370 /*! \brief generates a random mac address value for IBSS BSSID
4371 * \param Addr the bssid location
4376 VOID MacAddrRandomBssid(
4377 IN PRTMP_ADAPTER pAd,
4382 for (i = 0; i < MAC_ADDR_LEN; i++)
4384 pAddr[i] = RandomByte(pAd);
4387 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4390 /*! \brief init the management mac frame header
4391 * \param p_hdr mac header
4392 * \param subtype subtype of the frame
4393 * \param p_ds destination address, don't care if it is a broadcast address
4395 * \pre the station has the following information in the pAd->StaCfg
4399 * \note this function initializes the following field
4401 IRQL = PASSIVE_LEVEL
4402 IRQL = DISPATCH_LEVEL
4405 VOID MgtMacHeaderInit(
4406 IN PRTMP_ADAPTER pAd,
4407 IN OUT PHEADER_802_11 pHdr80211,
4413 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4415 pHdr80211->FC.Type = BTYPE_MGMT;
4416 pHdr80211->FC.SubType = SubType;
4417 pHdr80211->FC.ToDs = ToDs;
4418 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4420 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4421 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4423 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4426 // ===========================================================================================
4428 // ===========================================================================================
4430 /*!***************************************************************************
4431 * This routine build an outgoing frame, and fill all information specified
4432 * in argument list to the frame body. The actual frame size is the summation
4435 * Buffer - pointer to a pre-allocated memory segment
4436 * args - a list of <int arg_size, arg> pairs.
4437 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4438 * function will FAIL!!!
4440 * Size of the buffer
4442 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4444 IRQL = PASSIVE_LEVEL
4445 IRQL = DISPATCH_LEVEL
4447 ****************************************************************************/
4448 ULONG MakeOutgoingFrame(
4450 OUT ULONG *FrameLen, ...)
4457 // calculates the total length
4459 va_start(Args, FrameLen);
4462 leng = va_arg(Args, int);
4463 if (leng == END_OF_ARGS)
4467 p = va_arg(Args, PVOID);
4468 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4469 TotLeng = TotLeng + leng;
4472 va_end(Args); /* clean up */
4473 *FrameLen = TotLeng;
4477 // ===========================================================================================
4479 // ===========================================================================================
4481 /*! \brief Initialize The MLME Queue, used by MLME Functions
4482 * \param *Queue The MLME Queue
4483 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4486 * \note Because this is done only once (at the init stage), no need to be locked
4488 IRQL = PASSIVE_LEVEL
4491 NDIS_STATUS MlmeQueueInit(
4492 IN MLME_QUEUE *Queue)
4496 NdisAllocateSpinLock(&Queue->Lock);
4502 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4504 Queue->Entry[i].Occupied = FALSE;
4505 Queue->Entry[i].MsgLen = 0;
4506 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4509 return NDIS_STATUS_SUCCESS;
4512 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4513 * \param *Queue The MLME Queue
4514 * \param Machine The State Machine Id
4515 * \param MsgType The Message Type
4516 * \param MsgLen The Message length
4517 * \param *Msg The message pointer
4518 * \return TRUE if enqueue is successful, FALSE if the queue is full
4521 * \note The message has to be initialized
4523 IRQL = PASSIVE_LEVEL
4524 IRQL = DISPATCH_LEVEL
4527 BOOLEAN MlmeEnqueue(
4528 IN PRTMP_ADAPTER pAd,
4535 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4537 // Do nothing if the driver is starting halt state.
4538 // This might happen when timer already been fired before cancel timer with mlmehalt
4539 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4542 // First check the size, it MUST not exceed the mlme queue size
4543 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4545 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4549 if (MlmeQueueFull(Queue))
4554 NdisAcquireSpinLock(&(Queue->Lock));
4558 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4563 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4564 Queue->Entry[Tail].Occupied = TRUE;
4565 Queue->Entry[Tail].Machine = Machine;
4566 Queue->Entry[Tail].MsgType = MsgType;
4567 Queue->Entry[Tail].MsgLen = MsgLen;
4571 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4574 NdisReleaseSpinLock(&(Queue->Lock));
4578 /*! \brief This function is used when Recv gets a MLME message
4579 * \param *Queue The MLME Queue
4580 * \param TimeStampHigh The upper 32 bit of timestamp
4581 * \param TimeStampLow The lower 32 bit of timestamp
4582 * \param Rssi The receiving RSSI strength
4583 * \param MsgLen The length of the message
4584 * \param *Msg The message pointer
4585 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4589 IRQL = DISPATCH_LEVEL
4592 BOOLEAN MlmeEnqueueForRecv(
4593 IN PRTMP_ADAPTER pAd,
4595 IN ULONG TimeStampHigh,
4596 IN ULONG TimeStampLow,
4605 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4607 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4609 // Do nothing if the driver is starting halt state.
4610 // This might happen when timer already been fired before cancel timer with mlmehalt
4611 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4613 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4617 // First check the size, it MUST not exceed the mlme queue size
4618 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4620 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4624 if (MlmeQueueFull(Queue))
4629 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4631 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4633 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4638 // OK, we got all the informations, it is time to put things into queue
4639 NdisAcquireSpinLock(&(Queue->Lock));
4643 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4647 Queue->Entry[Tail].Occupied = TRUE;
4648 Queue->Entry[Tail].Machine = Machine;
4649 Queue->Entry[Tail].MsgType = MsgType;
4650 Queue->Entry[Tail].MsgLen = MsgLen;
4651 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4652 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4653 Queue->Entry[Tail].Rssi0 = Rssi0;
4654 Queue->Entry[Tail].Rssi1 = Rssi1;
4655 Queue->Entry[Tail].Rssi2 = Rssi2;
4656 Queue->Entry[Tail].Signal = Signal;
4657 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4659 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4663 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4666 NdisReleaseSpinLock(&(Queue->Lock));
4668 RT28XX_MLME_HANDLER(pAd);
4674 /*! \brief Dequeue a message from the MLME Queue
4675 * \param *Queue The MLME Queue
4676 * \param *Elem The message dequeued from MLME Queue
4677 * \return TRUE if the Elem contains something, FALSE otherwise
4681 IRQL = DISPATCH_LEVEL
4684 BOOLEAN MlmeDequeue(
4685 IN MLME_QUEUE *Queue,
4686 OUT MLME_QUEUE_ELEM **Elem)
4688 NdisAcquireSpinLock(&(Queue->Lock));
4689 *Elem = &(Queue->Entry[Queue->Head]);
4692 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4696 NdisReleaseSpinLock(&(Queue->Lock));
4700 // IRQL = DISPATCH_LEVEL
4701 VOID MlmeRestartStateMachine(
4702 IN PRTMP_ADAPTER pAd)
4704 MLME_QUEUE_ELEM *Elem = NULL;
4707 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4709 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4710 if(pAd->Mlme.bRunning)
4712 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4717 pAd->Mlme.bRunning = TRUE;
4719 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4721 // Remove all Mlme queues elements
4722 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4724 //From message type, determine which state machine I should drive
4725 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4727 // free MLME element
4728 Elem->Occupied = FALSE;
4733 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4737 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4739 // Cancel all timer events
4740 // Be careful to cancel new added timer
4741 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4742 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4743 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4744 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4745 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4746 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4749 // Change back to original channel in case of doing scan
4750 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4751 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4753 // Resume MSDU which is turned off durning scan
4754 RTMPResumeMsduTransmission(pAd);
4756 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4758 // Set all state machines back IDLE
4759 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4760 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4761 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4762 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4763 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4764 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4767 // Remove running state
4768 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4769 pAd->Mlme.bRunning = FALSE;
4770 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4773 /*! \brief test if the MLME Queue is empty
4774 * \param *Queue The MLME Queue
4775 * \return TRUE if the Queue is empty, FALSE otherwise
4779 IRQL = DISPATCH_LEVEL
4782 BOOLEAN MlmeQueueEmpty(
4783 IN MLME_QUEUE *Queue)
4787 NdisAcquireSpinLock(&(Queue->Lock));
4788 Ans = (Queue->Num == 0);
4789 NdisReleaseSpinLock(&(Queue->Lock));
4794 /*! \brief test if the MLME Queue is full
4795 * \param *Queue The MLME Queue
4796 * \return TRUE if the Queue is empty, FALSE otherwise
4800 IRQL = PASSIVE_LEVEL
4801 IRQL = DISPATCH_LEVEL
4804 BOOLEAN MlmeQueueFull(
4805 IN MLME_QUEUE *Queue)
4809 NdisAcquireSpinLock(&(Queue->Lock));
4810 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4811 NdisReleaseSpinLock(&(Queue->Lock));
4816 /*! \brief The destructor of MLME Queue
4821 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4823 IRQL = PASSIVE_LEVEL
4826 VOID MlmeQueueDestroy(
4827 IN MLME_QUEUE *pQueue)
4829 NdisAcquireSpinLock(&(pQueue->Lock));
4833 NdisReleaseSpinLock(&(pQueue->Lock));
4834 NdisFreeSpinLock(&(pQueue->Lock));
4837 /*! \brief To substitute the message type if the message is coming from external
4838 * \param pFrame The frame received
4839 * \param *Machine The state machine
4840 * \param *MsgType the message type for the state machine
4841 * \return TRUE if the substitution is successful, FALSE otherwise
4845 IRQL = DISPATCH_LEVEL
4848 BOOLEAN MsgTypeSubst(
4849 IN PRTMP_ADAPTER pAd,
4850 IN PFRAME_802_11 pFrame,
4858 // Pointer to start of data frames including SNAP header
4859 pData = (PUCHAR) pFrame + LENGTH_802_11;
4861 // The only data type will pass to this function is EAPOL frame
4862 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4864 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4866 // Cisco Aironet SNAP header
4867 *Machine = AIRONET_STATE_MACHINE;
4868 *MsgType = MT2_AIRONET_MSG;
4872 *Machine = WPA_PSK_STATE_MACHINE;
4873 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4874 return(WpaMsgTypeSubst(EAPType, MsgType));
4878 switch (pFrame->Hdr.FC.SubType)
4880 case SUBTYPE_ASSOC_REQ:
4881 *Machine = ASSOC_STATE_MACHINE;
4882 *MsgType = MT2_PEER_ASSOC_REQ;
4884 case SUBTYPE_ASSOC_RSP:
4885 *Machine = ASSOC_STATE_MACHINE;
4886 *MsgType = MT2_PEER_ASSOC_RSP;
4888 case SUBTYPE_REASSOC_REQ:
4889 *Machine = ASSOC_STATE_MACHINE;
4890 *MsgType = MT2_PEER_REASSOC_REQ;
4892 case SUBTYPE_REASSOC_RSP:
4893 *Machine = ASSOC_STATE_MACHINE;
4894 *MsgType = MT2_PEER_REASSOC_RSP;
4896 case SUBTYPE_PROBE_REQ:
4897 *Machine = SYNC_STATE_MACHINE;
4898 *MsgType = MT2_PEER_PROBE_REQ;
4900 case SUBTYPE_PROBE_RSP:
4901 *Machine = SYNC_STATE_MACHINE;
4902 *MsgType = MT2_PEER_PROBE_RSP;
4904 case SUBTYPE_BEACON:
4905 *Machine = SYNC_STATE_MACHINE;
4906 *MsgType = MT2_PEER_BEACON;
4909 *Machine = SYNC_STATE_MACHINE;
4910 *MsgType = MT2_PEER_ATIM;
4912 case SUBTYPE_DISASSOC:
4913 *Machine = ASSOC_STATE_MACHINE;
4914 *MsgType = MT2_PEER_DISASSOC_REQ;
4917 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4918 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4919 if (Seq == 1 || Seq == 3)
4921 *Machine = AUTH_RSP_STATE_MACHINE;
4922 *MsgType = MT2_PEER_AUTH_ODD;
4924 else if (Seq == 2 || Seq == 4)
4926 *Machine = AUTH_STATE_MACHINE;
4927 *MsgType = MT2_PEER_AUTH_EVEN;
4934 case SUBTYPE_DEAUTH:
4935 *Machine = AUTH_RSP_STATE_MACHINE;
4936 *MsgType = MT2_PEER_DEAUTH;
4938 case SUBTYPE_ACTION:
4939 *Machine = ACTION_STATE_MACHINE;
4940 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4941 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4943 *MsgType = MT2_ACT_INVALID;
4947 *MsgType = (pFrame->Octet[0]&0x7F);
4958 // ===========================================================================================
4960 // ===========================================================================================
4962 /*! \brief Initialize the state machine.
4963 * \param *S pointer to the state machine
4964 * \param Trans State machine transition function
4965 * \param StNr number of states
4966 * \param MsgNr number of messages
4967 * \param DefFunc default function, when there is invalid state/message combination
4968 * \param InitState initial state of the state machine
4969 * \param Base StateMachine base, internal use only
4970 * \pre p_sm should be a legal pointer
4973 IRQL = PASSIVE_LEVEL
4976 VOID StateMachineInit(
4977 IN STATE_MACHINE *S,
4978 IN STATE_MACHINE_FUNC Trans[],
4981 IN STATE_MACHINE_FUNC DefFunc,
4987 // set number of states and messages
4992 S->TransFunc = Trans;
4994 // init all state transition to default function
4995 for (i = 0; i < StNr; i++)
4997 for (j = 0; j < MsgNr; j++)
4999 S->TransFunc[i * MsgNr + j] = DefFunc;
5003 // set the starting state
5004 S->CurrState = InitState;
5007 /*! \brief This function fills in the function pointer into the cell in the state machine
5008 * \param *S pointer to the state machine
5010 * \param Msg incoming message
5011 * \param f the function to be executed when (state, message) combination occurs at the state machine
5012 * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
5015 IRQL = PASSIVE_LEVEL
5018 VOID StateMachineSetAction(
5019 IN STATE_MACHINE *S,
5022 IN STATE_MACHINE_FUNC Func)
5026 MsgIdx = Msg - S->Base;
5028 if (St < S->NrState && MsgIdx < S->NrMsg)
5030 // boundary checking before setting the action
5031 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5035 /*! \brief This function does the state transition
5036 * \param *Adapter the NIC adapter pointer
5037 * \param *S the state machine
5038 * \param *Elem the message to be executed
5041 IRQL = DISPATCH_LEVEL
5044 VOID StateMachinePerformAction(
5045 IN PRTMP_ADAPTER pAd,
5046 IN STATE_MACHINE *S,
5047 IN MLME_QUEUE_ELEM *Elem)
5049 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5053 ==========================================================================
5055 The drop function, when machine executes this, the message is simply
5056 ignored. This function does nothing, the message is freed in
5057 StateMachinePerformAction()
5058 ==========================================================================
5061 IN PRTMP_ADAPTER pAd,
5062 IN MLME_QUEUE_ELEM *Elem)
5066 // ===========================================================================================
5068 // ===========================================================================================
5071 ==========================================================================
5074 IRQL = PASSIVE_LEVEL
5076 ==========================================================================
5079 IN PRTMP_ADAPTER pAd,
5083 pAd->Mlme.ShiftReg = 1;
5085 pAd->Mlme.ShiftReg = Seed;
5089 ==========================================================================
5091 ==========================================================================
5094 IN PRTMP_ADAPTER pAd)
5101 if (pAd->Mlme.ShiftReg == 0)
5102 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5104 for (i = 0; i < 8; i++)
5106 if (pAd->Mlme.ShiftReg & 0x00000001)
5108 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5113 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5116 R = (R << 1) | Result;
5122 VOID AsicUpdateAutoFallBackTable(
5123 IN PRTMP_ADAPTER pAd,
5124 IN PUCHAR pRateTable)
5127 HT_FBK_CFG0_STRUC HtCfg0;
5128 HT_FBK_CFG1_STRUC HtCfg1;
5129 LG_FBK_CFG0_STRUC LgCfg0;
5130 LG_FBK_CFG1_STRUC LgCfg1;
5131 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5133 // set to initial value
5134 HtCfg0.word = 0x65432100;
5135 HtCfg1.word = 0xedcba988;
5136 LgCfg0.word = 0xedcba988;
5137 LgCfg1.word = 0x00002100;
5139 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5140 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5142 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5143 switch (pCurrTxRate->Mode)
5149 switch(pCurrTxRate->CurrMCS)
5152 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5155 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5158 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5161 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5164 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5167 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5170 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5173 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5178 #ifdef DOT11_N_SUPPORT
5182 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5184 switch(pCurrTxRate->CurrMCS)
5187 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5190 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5193 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5196 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5199 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5202 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5205 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5208 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5211 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5214 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5217 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5220 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5223 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5226 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5229 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5232 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5235 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5240 #endif // DOT11_N_SUPPORT //
5243 pNextTxRate = pCurrTxRate;
5246 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5247 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5248 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5249 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5253 ========================================================================
5255 Routine Description:
5256 Set MAC register value according operation mode.
5257 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5258 If MM or GF mask is not set, those passing argument doesn't not take effect.
5260 Operation mode meaning:
5261 = 0 : Pure HT, no preotection.
5262 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5263 = 0x10: No Transmission in 40M is protected.
5264 = 0x11: Transmission in both 40M and 20M shall be protected
5266 we should choose not to use GF. But still set correct ASIC registers.
5267 ========================================================================
5269 VOID AsicUpdateProtect(
5270 IN PRTMP_ADAPTER pAd,
5271 IN USHORT OperationMode,
5273 IN BOOLEAN bDisableBGProtect,
5274 IN BOOLEAN bNonGFExist)
5276 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5282 #ifdef DOT11_N_SUPPORT
5283 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5288 if (pAd->BATable.numAsOriginator)
5291 // enable the RTS/CTS to avoid channel collision
5293 SetMask = ALLN_SETPROTECT;
5296 #endif // DOT11_N_SUPPORT //
5298 // Config ASIC RTS threshold register
5299 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5300 MacReg &= 0xFF0000FF;
5302 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5304 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5306 #ifdef DOT11_N_SUPPORT
5307 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5308 #endif // DOT11_N_SUPPORT //
5309 (pAd->CommonCfg.bAggregationCapable == TRUE))
5310 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5312 MacReg |= (0x1000 << 8);
5316 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5320 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5322 // Initial common protection settings
5323 RTMPZeroMemory(Protect, sizeof(Protect));
5326 ProtCfg.field.TxopAllowGF40 = 1;
5327 ProtCfg.field.TxopAllowGF20 = 1;
5328 ProtCfg.field.TxopAllowMM40 = 1;
5329 ProtCfg.field.TxopAllowMM20 = 1;
5330 ProtCfg.field.TxopAllowOfdm = 1;
5331 ProtCfg.field.TxopAllowCck = 1;
5332 ProtCfg.field.RTSThEn = 1;
5333 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5335 // update PHY mode and rate
5336 if (pAd->CommonCfg.Channel > 14)
5337 ProtCfg.field.ProtectRate = 0x4000;
5338 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5340 // Handle legacy(B/G) protection
5341 if (bDisableBGProtect)
5343 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5344 ProtCfg.field.ProtectCtrl = 0;
5345 Protect[0] = ProtCfg.word;
5346 Protect[1] = ProtCfg.word;
5350 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5351 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5352 Protect[0] = ProtCfg.word;
5353 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5354 Protect[1] = ProtCfg.word;
5357 #ifdef DOT11_N_SUPPORT
5358 // Decide HT frame protection.
5359 if ((SetMask & ALLN_SETPROTECT) != 0)
5361 switch(OperationMode)
5365 // 1.All STAs in the BSS are 20/40 MHz HT
5366 // 2. in ai 20/40MHz BSS
5367 // 3. all STAs are 20MHz in a 20MHz BSS
5368 // Pure HT. no protection.
5372 // PROT_TXOP(25:20) -- 010111
5373 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5374 // PROT_CTRL(17:16) -- 00 (None)
5375 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5376 Protect[2] = 0x01744004;
5380 // PROT_TXOP(25:20) -- 111111
5381 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5382 // PROT_CTRL(17:16) -- 00 (None)
5383 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5384 Protect[3] = 0x03f44084;
5388 // PROT_TXOP(25:20) -- 010111
5389 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5390 // PROT_CTRL(17:16) -- 00 (None)
5391 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5392 Protect[4] = 0x01744004;
5396 // PROT_TXOP(25:20) -- 111111
5397 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5398 // PROT_CTRL(17:16) -- 00 (None)
5399 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5400 Protect[5] = 0x03f44084;
5404 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5405 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5406 Protect[4] = 0x01754004;
5407 Protect[5] = 0x03f54084;
5409 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5413 // This is "HT non-member protection mode."
5414 // If there may be non-HT STAs my BSS
5415 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5416 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5417 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5419 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5420 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5422 //Assign Protection method for 20&40 MHz packets
5423 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5424 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5425 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5426 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5427 Protect[2] = ProtCfg.word;
5428 Protect[3] = ProtCfg4.word;
5429 Protect[4] = ProtCfg.word;
5430 Protect[5] = ProtCfg4.word;
5431 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5435 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5436 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5437 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5439 //Assign Protection method for 40MHz packets
5440 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5441 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5442 Protect[2] = ProtCfg.word;
5443 Protect[3] = ProtCfg4.word;
5446 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5447 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5449 Protect[4] = ProtCfg.word;
5450 Protect[5] = ProtCfg4.word;
5452 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5456 // HT mixed mode. PROTECT ALL!
5458 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5459 ProtCfg4.word = 0x03f44084;
5460 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5461 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5463 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5464 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5466 //Assign Protection method for 20&40 MHz packets
5467 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5468 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5469 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5470 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5471 Protect[2] = ProtCfg.word;
5472 Protect[3] = ProtCfg4.word;
5473 Protect[4] = ProtCfg.word;
5474 Protect[5] = ProtCfg4.word;
5475 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5479 // Special on for Atheros problem n chip.
5480 Protect[2] = 0x01754004;
5481 Protect[3] = 0x03f54084;
5482 Protect[4] = 0x01754004;
5483 Protect[5] = 0x03f54084;
5484 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5488 #endif // DOT11_N_SUPPORT //
5490 offset = CCK_PROT_CFG;
5491 for (i = 0;i < 6;i++)
5493 if ((SetMask & (1<< i)))
5495 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5501 ==========================================================================
5504 IRQL = PASSIVE_LEVEL
5505 IRQL = DISPATCH_LEVEL
5507 ==========================================================================
5509 VOID AsicSwitchChannel(
5510 IN PRTMP_ADAPTER pAd,
5514 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5515 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5517 UINT32 Value = 0; //BbpReg, Value;
5518 RTMP_RF_REGS *RFRegTable;
5520 // Search Tx power value
5521 for (index = 0; index < pAd->ChannelListNum; index++)
5523 if (Channel == pAd->ChannelList[index].Channel)
5525 TxPwer = pAd->ChannelList[index].Power;
5526 TxPwer2 = pAd->ChannelList[index].Power2;
5531 if (index == MAX_NUM_OF_CHANNELS)
5533 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5537 RFRegTable = RF2850RegTable;
5539 switch (pAd->RfIcType)
5546 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5548 if (Channel == RFRegTable[index].Channel)
5550 R2 = RFRegTable[index].R2;
5551 if (pAd->Antenna.field.TxPath == 1)
5553 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5556 if (pAd->Antenna.field.RxPath == 2)
5558 R2 |= 0x40; // write 1 to off Rxpath.
5560 else if (pAd->Antenna.field.RxPath == 1)
5562 R2 |= 0x20040; // write 1 to off RxPath
5567 // initialize R3, R4
5568 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5569 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5571 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5573 if ((TxPwer >= -7) && (TxPwer < 0))
5575 TxPwer = (7+TxPwer);
5576 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5577 R3 |= (TxPwer << 10);
5578 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5582 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5583 R3 |= (TxPwer << 10) | (1 << 9);
5587 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5589 TxPwer2 = (7+TxPwer2);
5590 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5591 R4 |= (TxPwer2 << 7);
5592 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5596 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5597 R4 |= (TxPwer2 << 7) | (1 << 6);
5602 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5603 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5606 // Based on BBP current mode before changing RF channel.
5607 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5613 pAd->LatchRfRegs.Channel = Channel;
5614 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5615 pAd->LatchRfRegs.R2 = R2;
5616 pAd->LatchRfRegs.R3 = R3;
5617 pAd->LatchRfRegs.R4 = R4;
5619 // Set RF value 1's set R3[bit2] = [0]
5620 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5621 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5622 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5623 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5627 // Set RF value 2's set R3[bit2] = [1]
5628 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5629 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5630 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5631 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5635 // Set RF value 3's set R3[bit2] = [0]
5636 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5637 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5638 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5639 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5651 // Change BBP setting during siwtch from a->g, g->a
5654 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5656 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5657 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5658 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5659 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.
5660 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5662 // Rx High power VGA offset for LNA select
5663 if (pAd->NicConfig2.field.ExternalLNAForG)
5665 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5666 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5670 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5671 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5674 // 5G band selection PIN, bit1 and bit2 are complement
5675 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5678 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5680 // Turn off unused PA or LNA when only 1T or 1R
5681 if (pAd->Antenna.field.TxPath == 1)
5683 TxPinCfg &= 0xFFFFFFF3;
5685 if (pAd->Antenna.field.RxPath == 1)
5687 TxPinCfg &= 0xFFFFF3FF;
5690 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5694 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5696 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5697 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5698 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5699 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.
5700 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5702 // Rx High power VGA offset for LNA select
5703 if (pAd->NicConfig2.field.ExternalLNAForA)
5705 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5709 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5712 // 5G band selection PIN, bit1 and bit2 are complement
5713 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5716 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5718 // Turn off unused PA or LNA when only 1T or 1R
5719 if (pAd->Antenna.field.TxPath == 1)
5721 TxPinCfg &= 0xFFFFFFF3;
5723 if (pAd->Antenna.field.RxPath == 1)
5725 TxPinCfg &= 0xFFFFF3FF;
5728 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5731 // R66 should be set according to Channel and use 20MHz when scanning
5732 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5734 RTMPSetAGCInitValue(pAd, BW_20);
5736 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5739 // On 11A, We should delay and wait RF/BBP to be stable
5740 // and the appropriate time should be 1000 micro seconds
5741 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5743 RTMPusecDelay(1000);
5745 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
5748 (R3 & 0x00003e00) >> 9,
5749 (R4 & 0x000007c0) >> 6,
5750 pAd->Antenna.field.TxPath,
5751 pAd->LatchRfRegs.R1,
5752 pAd->LatchRfRegs.R2,
5753 pAd->LatchRfRegs.R3,
5754 pAd->LatchRfRegs.R4));
5758 ==========================================================================
5760 This function is required for 2421 only, and should not be used during
5761 site survey. It's only required after NIC decided to stay at a channel
5762 for a longer period.
5763 When this function is called, it's always after AsicSwitchChannel().
5765 IRQL = PASSIVE_LEVEL
5766 IRQL = DISPATCH_LEVEL
5768 ==========================================================================
5770 VOID AsicLockChannel(
5771 IN PRTMP_ADAPTER pAd,
5777 ==========================================================================
5780 IRQL = PASSIVE_LEVEL
5781 IRQL = DISPATCH_LEVEL
5783 ==========================================================================
5785 VOID AsicAntennaSelect(
5786 IN PRTMP_ADAPTER pAd,
5792 ========================================================================
5794 Routine Description:
5795 Antenna miscellaneous setting.
5798 pAd Pointer to our adapter
5799 BandState Indicate current Band State.
5804 IRQL <= DISPATCH_LEVEL
5807 1.) Frame End type control
5808 only valid for G only (RF_2527 & RF_2529)
5809 0: means DPDT, set BBP R4 bit 5 to 1
5810 1: means SPDT, set BBP R4 bit 5 to 0
5813 ========================================================================
5815 VOID AsicAntennaSetting(
5816 IN PRTMP_ADAPTER pAd,
5817 IN ABGBAND_STATE BandState)
5821 VOID AsicRfTuningExec(
5822 IN PVOID SystemSpecific1,
5823 IN PVOID FunctionContext,
5824 IN PVOID SystemSpecific2,
5825 IN PVOID SystemSpecific3)
5830 ==========================================================================
5832 Gives CCK TX rate 2 more dB TX power.
5833 This routine works only in LINK UP in INFRASTRUCTURE mode.
5835 calculate desired Tx power in RF R3.Tx0~5, should consider -
5836 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5837 1. TxPowerPercentage
5838 2. auto calibration based on TSSI feedback
5839 3. extra 2 db for CCK
5840 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5842 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5843 it should be called AFTER MlmeDynamicTxRatSwitching()
5844 ==========================================================================
5846 VOID AsicAdjustTxPower(
5847 IN PRTMP_ADAPTER pAd)
5851 BOOLEAN bAutoTxAgc = FALSE;
5852 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5853 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5854 PCHAR pTxAgcCompensate;
5858 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5859 || (pAd->bPCIclkOff == TRUE)
5860 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
5861 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
5864 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5866 if (pAd->CommonCfg.CentralChannel > 14)
5868 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5869 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5870 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5871 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5872 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5876 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5877 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5878 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5879 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5880 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5885 if (pAd->CommonCfg.Channel > 14)
5887 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5888 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5889 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5890 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5891 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5895 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5896 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5897 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5898 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5899 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5903 // TX power compensation for temperature variation based on TSSI. try every 4 second
5904 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5906 if (pAd->CommonCfg.Channel <= 14)
5909 bAutoTxAgc = pAd->bAutoTxAgcG;
5910 TssiRef = pAd->TssiRefG;
5911 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5912 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5913 TxAgcStep = pAd->TxAgcStepG;
5914 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5919 bAutoTxAgc = pAd->bAutoTxAgcA;
5920 TssiRef = pAd->TssiRefA;
5921 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
5922 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
5923 TxAgcStep = pAd->TxAgcStepA;
5924 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5929 /* BbpR1 is unsigned char */
5930 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
5932 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
5933 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
5934 /* step value is defined in pAd->TxAgcStepG for tx power value */
5936 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
5937 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
5938 above value are examined in mass factory production */
5939 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
5941 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
5942 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
5943 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
5945 if (BbpR49 > pTssiMinusBoundary[1])
5947 // Reading is larger than the reference value
5948 // check for how large we need to decrease the Tx power
5949 for (idx = 1; idx < 5; idx++)
5951 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
5954 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
5955 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
5957 DeltaPwr += (*pTxAgcCompensate);
5958 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
5959 BbpR49, TssiRef, TxAgcStep, idx-1));
5961 else if (BbpR49 < pTssiPlusBoundary[1])
5963 // Reading is smaller than the reference value
5964 // check for how large we need to increase the Tx power
5965 for (idx = 1; idx < 5; idx++)
5967 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
5970 // The index is the step we should increase, idx = 0 means there is nothing to compensate
5971 *pTxAgcCompensate = TxAgcStep * (idx-1);
5972 DeltaPwr += (*pTxAgcCompensate);
5973 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5974 BbpR49, TssiRef, TxAgcStep, idx-1));
5978 *pTxAgcCompensate = 0;
5979 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5980 BbpR49, TssiRef, TxAgcStep, 0));
5986 if (pAd->CommonCfg.Channel <= 14)
5988 bAutoTxAgc = pAd->bAutoTxAgcG;
5989 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5993 bAutoTxAgc = pAd->bAutoTxAgcA;
5994 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5998 DeltaPwr += (*pTxAgcCompensate);
6001 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6004 /* calculate delta power based on the percentage specified from UI */
6005 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6006 // We lower TX power here according to the percentage specified from UI
6007 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6009 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6011 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6015 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6019 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6023 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6028 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6033 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6035 /* reset different new tx power for different TX rate */
6038 if (TxPwr[i] != 0xffffffff)
6042 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6044 if ((Value + DeltaPwr) < 0)
6046 Value = 0; /* min */
6048 else if ((Value + DeltaPwr) > 0xF)
6050 Value = 0xF; /* max */
6054 Value += DeltaPwr; /* temperature compensation */
6057 /* fill new value to CSR offset */
6058 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6061 /* write tx power value to CSR */
6062 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6063 TX power for OFDM 6M/9M
6064 TX power for CCK5.5M/11M
6065 TX power for CCK1M/2M */
6066 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6067 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6074 ==========================================================================
6076 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6077 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6078 the wakeup timer timeout. Driver has to issue a separate command to wake
6081 IRQL = DISPATCH_LEVEL
6083 ==========================================================================
6085 VOID AsicSleepThenAutoWakeup(
6086 IN PRTMP_ADAPTER pAd,
6087 IN USHORT TbttNumToNextWakeUp)
6089 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6093 ==========================================================================
6095 AsicForceWakeup() is used whenever manual wakeup is required
6096 AsicForceSleep() should only be used when not in INFRA BSS. When
6097 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6098 ==========================================================================
6100 VOID AsicForceSleep(
6101 IN PRTMP_ADAPTER pAd)
6107 ==========================================================================
6109 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6112 IRQL = PASSIVE_LEVEL
6113 IRQL = DISPATCH_LEVEL
6114 ==========================================================================
6116 VOID AsicForceWakeup(
6117 IN PRTMP_ADAPTER pAd,
6120 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6121 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6125 ==========================================================================
6129 IRQL = DISPATCH_LEVEL
6131 ==========================================================================
6134 IN PRTMP_ADAPTER pAd,
6138 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6139 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6141 Addr4 = (ULONG)(pBssid[0]) |
6142 (ULONG)(pBssid[1] << 8) |
6143 (ULONG)(pBssid[2] << 16) |
6144 (ULONG)(pBssid[3] << 24);
6145 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6148 // always one BSSID in STA mode
6149 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6151 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6154 VOID AsicSetMcastWC(
6155 IN PRTMP_ADAPTER pAd)
6157 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6160 pEntry->Sst = SST_ASSOC;
6161 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6162 pEntry->PsMode = PWR_ACTIVE;
6163 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6164 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6168 ==========================================================================
6171 IRQL = DISPATCH_LEVEL
6173 ==========================================================================
6175 VOID AsicDelWcidTab(
6176 IN PRTMP_ADAPTER pAd,
6179 ULONG Addr0 = 0x0, Addr1 = 0x0;
6182 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6183 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6184 RTMP_IO_WRITE32(pAd, offset, Addr0);
6186 RTMP_IO_WRITE32(pAd, offset, Addr1);
6190 ==========================================================================
6193 IRQL = DISPATCH_LEVEL
6195 ==========================================================================
6198 IN PRTMP_ADAPTER pAd)
6200 TX_LINK_CFG_STRUC TxLinkCfg;
6203 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6204 TxLinkCfg.field.TxRDGEn = 1;
6205 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6207 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6210 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6212 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6216 ==========================================================================
6219 IRQL = DISPATCH_LEVEL
6221 ==========================================================================
6223 VOID AsicDisableRDG(
6224 IN PRTMP_ADAPTER pAd)
6226 TX_LINK_CFG_STRUC TxLinkCfg;
6230 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6231 TxLinkCfg.field.TxRDGEn = 0;
6232 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6234 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6237 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6238 #ifdef DOT11_N_SUPPORT
6239 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6240 #endif // DOT11_N_SUPPORT //
6243 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6244 if (pAd->CommonCfg.bEnableTxBurst)
6247 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6251 ==========================================================================
6254 IRQL = PASSIVE_LEVEL
6255 IRQL = DISPATCH_LEVEL
6257 ==========================================================================
6259 VOID AsicDisableSync(
6260 IN PRTMP_ADAPTER pAd)
6262 BCN_TIME_CFG_STRUC csr;
6264 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6266 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6267 // that NIC will never wakes up because TSF stops and no more
6269 pAd->TbttTickCount = 0;
6270 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6271 csr.field.bBeaconGen = 0;
6272 csr.field.bTBTTEnable = 0;
6273 csr.field.TsfSyncMode = 0;
6274 csr.field.bTsfTicking = 0;
6275 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6280 ==========================================================================
6283 IRQL = DISPATCH_LEVEL
6285 ==========================================================================
6287 VOID AsicEnableBssSync(
6288 IN PRTMP_ADAPTER pAd)
6290 BCN_TIME_CFG_STRUC csr;
6292 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6294 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6296 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6298 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6299 csr.field.bTsfTicking = 1;
6300 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6301 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6302 csr.field.bTBTTEnable = 1;
6305 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6309 ==========================================================================
6312 BEACON frame in shared memory should be built ok before this routine
6313 can be called. Otherwise, a garbage frame maybe transmitted out every
6316 IRQL = DISPATCH_LEVEL
6318 ==========================================================================
6320 VOID AsicEnableIbssSync(
6321 IN PRTMP_ADAPTER pAd)
6323 BCN_TIME_CFG_STRUC csr9;
6327 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6329 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6330 csr9.field.bBeaconGen = 0;
6331 csr9.field.bTBTTEnable = 0;
6332 csr9.field.bTsfTicking = 0;
6333 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6335 // move BEACON TXD and frame content to on-chip memory
6336 ptr = (PUCHAR)&pAd->BeaconTxWI;
6337 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6339 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6340 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6344 // start right after the 16-byte TXWI field
6345 ptr = pAd->BeaconBuf;
6346 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6348 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6349 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6353 // start sending BEACON
6354 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6355 csr9.field.bTsfTicking = 1;
6356 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6357 csr9.field.bTBTTEnable = 1;
6358 csr9.field.bBeaconGen = 1;
6359 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6363 ==========================================================================
6366 IRQL = PASSIVE_LEVEL
6367 IRQL = DISPATCH_LEVEL
6369 ==========================================================================
6371 VOID AsicSetEdcaParm(
6372 IN PRTMP_ADAPTER pAd,
6373 IN PEDCA_PARM pEdcaParm)
6375 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6376 AC_TXOP_CSR0_STRUC csr0;
6377 AC_TXOP_CSR1_STRUC csr1;
6378 AIFSN_CSR_STRUC AifsnCsr;
6379 CWMIN_CSR_STRUC CwminCsr;
6380 CWMAX_CSR_STRUC CwmaxCsr;
6387 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6389 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6390 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6391 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6393 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6394 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6397 //========================================================
6398 // MAC Register has a copy .
6399 //========================================================
6400 if( pAd->CommonCfg.bEnableTxBurst )
6402 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6403 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6406 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6407 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6408 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6409 Ac0Cfg.field.Aifsn = 2;
6410 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6412 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6413 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6414 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6415 Ac1Cfg.field.Aifsn = 2;
6416 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6418 if (pAd->CommonCfg.PhyMode == PHY_11B)
6420 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6421 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6425 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6426 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6428 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6429 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6430 Ac2Cfg.field.Aifsn = 2;
6431 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6432 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6433 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6434 Ac3Cfg.field.Aifsn = 2;
6435 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6437 //========================================================
6438 // DMA Register has a copy too.
6439 //========================================================
6440 csr0.field.Ac0Txop = 0; // QID_AC_BE
6441 csr0.field.Ac1Txop = 0; // QID_AC_BK
6442 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6443 if (pAd->CommonCfg.PhyMode == PHY_11B)
6445 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6446 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6450 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6451 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6453 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6456 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6457 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6458 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6459 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6460 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6463 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6464 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6465 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6466 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6467 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6469 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6471 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6475 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6476 //========================================================
6477 // MAC Register has a copy.
6478 //========================================================
6480 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6481 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6483 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6485 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6486 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6487 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6488 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6490 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6491 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6492 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6493 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6495 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6496 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6497 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6498 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6500 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6502 // Tuning for Wi-Fi WMM S06
6503 if (pAd->CommonCfg.bWiFiTest &&
6504 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6505 Ac2Cfg.field.Aifsn -= 1;
6507 // Tuning for TGn Wi-Fi 5.2.32
6508 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6509 if (STA_TGN_WIFI_ON(pAd) &&
6510 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6512 Ac0Cfg.field.Aifsn = 3;
6513 Ac2Cfg.field.AcTxop = 5;
6517 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6518 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6519 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6520 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6523 if (pAd->CommonCfg.bWiFiTest)
6525 if (Ac3Cfg.field.AcTxop == 102)
6527 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6528 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6529 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6530 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6531 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6534 //#endif // WIFI_TEST //
6536 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6537 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6538 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6539 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6542 //========================================================
6543 // DMA Register has a copy too.
6544 //========================================================
6545 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6546 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6547 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6549 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6550 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6551 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6554 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6555 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6556 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6558 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6559 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6561 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6564 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6565 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6566 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6567 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6568 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6571 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6572 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6573 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6575 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6577 // Tuning for Wi-Fi WMM S06
6578 if (pAd->CommonCfg.bWiFiTest &&
6579 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6580 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6582 // Tuning for TGn Wi-Fi 5.2.32
6583 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6584 if (STA_TGN_WIFI_ON(pAd) &&
6585 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6587 AifsnCsr.field.Aifsn0 = 3;
6588 AifsnCsr.field.Aifsn2 = 7;
6592 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6593 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6595 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6597 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6600 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6601 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6602 pEdcaParm->Aifsn[0],
6603 pEdcaParm->Cwmin[0],
6604 pEdcaParm->Cwmax[0],
6605 pEdcaParm->Txop[0]<<5,
6606 pEdcaParm->bACM[0]));
6607 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6608 pEdcaParm->Aifsn[1],
6609 pEdcaParm->Cwmin[1],
6610 pEdcaParm->Cwmax[1],
6611 pEdcaParm->Txop[1]<<5,
6612 pEdcaParm->bACM[1]));
6613 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6614 pEdcaParm->Aifsn[2],
6615 pEdcaParm->Cwmin[2],
6616 pEdcaParm->Cwmax[2],
6617 pEdcaParm->Txop[2]<<5,
6618 pEdcaParm->bACM[2]));
6619 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6620 pEdcaParm->Aifsn[3],
6621 pEdcaParm->Cwmin[3],
6622 pEdcaParm->Cwmax[3],
6623 pEdcaParm->Txop[3]<<5,
6624 pEdcaParm->bACM[3]));
6630 ==========================================================================
6633 IRQL = PASSIVE_LEVEL
6634 IRQL = DISPATCH_LEVEL
6636 ==========================================================================
6638 VOID AsicSetSlotTime(
6639 IN PRTMP_ADAPTER pAd,
6640 IN BOOLEAN bUseShortSlotTime)
6643 UINT32 RegValue = 0;
6645 if (pAd->CommonCfg.Channel > 14)
6646 bUseShortSlotTime = TRUE;
6648 if (bUseShortSlotTime)
6649 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6651 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6653 SlotTime = (bUseShortSlotTime)? 9 : 20;
6655 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6657 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6658 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6659 #ifdef DOT11_N_SUPPORT
6660 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6661 #endif // DOT11_N_SUPPORT //
6664 // In this case, we will think it is doing Wi-Fi test
6665 // And we will not set to short slot when bEnableTxBurst is TRUE.
6667 else if (pAd->CommonCfg.bEnableTxBurst)
6672 // For some reasons, always set it to short slot time.
6674 // ToDo: Should consider capability with 11B
6676 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6678 if (pAd->StaCfg.BssType == BSS_ADHOC)
6682 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6683 RegValue = RegValue & 0xFFFFFF00;
6685 RegValue |= SlotTime;
6687 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6691 ========================================================================
6693 Add Shared key information into ASIC.
6694 Update shared key, TxMic and RxMic to Asic Shared key table
6695 Update its cipherAlg to Asic Shared key Mode.
6698 ========================================================================
6700 VOID AsicAddSharedKeyEntry(
6701 IN PRTMP_ADAPTER pAd,
6709 ULONG offset; //, csr0;
6710 SHAREDKEY_MODE_STRUC csr1;
6713 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6714 //============================================================================================
6716 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6717 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6718 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
6721 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6722 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6726 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6727 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6729 //============================================================================================
6731 // fill key material - key + TX MIC + RX MIC
6733 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6734 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6736 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6739 offset += MAX_LEN_OF_SHARE_KEY;
6744 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6753 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6759 // Update cipher algorithm. WSTA always use BSS0
6761 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6762 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6763 if ((BssIndex%2) == 0)
6766 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6767 else if (KeyIdx == 1)
6768 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6769 else if (KeyIdx == 2)
6770 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6772 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6777 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6778 else if (KeyIdx == 1)
6779 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6780 else if (KeyIdx == 2)
6781 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6783 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6785 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6786 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6790 // IRQL = DISPATCH_LEVEL
6791 VOID AsicRemoveSharedKeyEntry(
6792 IN PRTMP_ADAPTER pAd,
6797 SHAREDKEY_MODE_STRUC csr1;
6799 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6801 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6802 if ((BssIndex%2) == 0)
6805 csr1.field.Bss0Key0CipherAlg = 0;
6806 else if (KeyIdx == 1)
6807 csr1.field.Bss0Key1CipherAlg = 0;
6808 else if (KeyIdx == 2)
6809 csr1.field.Bss0Key2CipherAlg = 0;
6811 csr1.field.Bss0Key3CipherAlg = 0;
6816 csr1.field.Bss1Key0CipherAlg = 0;
6817 else if (KeyIdx == 1)
6818 csr1.field.Bss1Key1CipherAlg = 0;
6819 else if (KeyIdx == 2)
6820 csr1.field.Bss1Key2CipherAlg = 0;
6822 csr1.field.Bss1Key3CipherAlg = 0;
6824 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6825 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6826 ASSERT(BssIndex < 4);
6832 VOID AsicUpdateWCIDAttribute(
6833 IN PRTMP_ADAPTER pAd,
6837 IN BOOLEAN bUsePairewiseKeyTable)
6839 ULONG WCIDAttri = 0, offset;
6842 // Update WCID attribute.
6843 // Only TxKey could update WCID attribute.
6845 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6846 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6847 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6850 VOID AsicUpdateWCIDIVEIV(
6851 IN PRTMP_ADAPTER pAd,
6858 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6860 RTMP_IO_WRITE32(pAd, offset, uIV);
6861 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6864 VOID AsicUpdateRxWCIDTable(
6865 IN PRTMP_ADAPTER pAd,
6872 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6873 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6874 RTMP_IO_WRITE32(pAd, offset, Addr);
6875 Addr = pAddr[4] + (pAddr[5] << 8);
6876 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6881 ========================================================================
6883 Routine Description:
6884 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6887 pAd Pointer to our adapter
6888 WCID WCID Entry number.
6889 BssIndex BSSID index, station or none multiple BSSID support
6890 this value should be 0.
6891 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6892 pCipherKey Pointer to Cipher Key.
6893 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6894 otherwise PairewiseKey table
6895 bTxKey This is the transmit key if enabled.
6901 This routine will set the relative key stuff to Asic including WCID attribute,
6902 Cipher Key, Cipher algorithm and IV/EIV.
6904 IV/EIV will be update if this CipherKey is the transmission key because
6905 ASIC will base on IV's KeyID value to select Cipher Key.
6907 If bTxKey sets to FALSE, this is not the TX key, but it could be
6910 For AP mode bTxKey must be always set to TRUE.
6911 ========================================================================
6913 VOID AsicAddKeyEntry(
6914 IN PRTMP_ADAPTER pAd,
6918 IN PCIPHER_KEY pCipherKey,
6919 IN BOOLEAN bUsePairewiseKeyTable,
6924 PUCHAR pKey = pCipherKey->Key;
6925 PUCHAR pTxMic = pCipherKey->TxMic;
6926 PUCHAR pRxMic = pCipherKey->RxMic;
6927 PUCHAR pTxtsc = pCipherKey->TxTsc;
6928 UCHAR CipherAlg = pCipherKey->CipherAlg;
6929 SHAREDKEY_MODE_STRUC csr1;
6932 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
6934 // 1.) decide key table offset
6936 if (bUsePairewiseKeyTable)
6937 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6939 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
6942 // 2.) Set Key to Asic
6944 //for (i = 0; i < KeyLen; i++)
6945 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
6947 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6949 offset += MAX_LEN_OF_PEER_KEY;
6952 // 3.) Set MIC key if available
6956 for (i = 0; i < 8; i++)
6958 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6961 offset += LEN_TKIP_TXMICK;
6965 for (i = 0; i < 8; i++)
6967 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6973 // 4.) Modify IV/EIV if needs
6974 // This will force Asic to use this key ID by setting IV.
6978 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6982 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
6983 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
6984 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
6986 IV4 = (KeyIdx << 6);
6987 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
6988 IV4 |= 0x20; // turn on extension bit means EIV existence
6990 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
6996 for (i = 0; i < 4; i++)
6998 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7001 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7004 if (!bUsePairewiseKeyTable)
7007 // Only update the shared key security mode
7009 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7010 if ((BssIndex % 2) == 0)
7013 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7014 else if (KeyIdx == 1)
7015 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7016 else if (KeyIdx == 2)
7017 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7019 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7024 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7025 else if (KeyIdx == 1)
7026 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7027 else if (KeyIdx == 2)
7028 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7030 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7032 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7035 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7040 ========================================================================
7042 Add Pair-wise key material into ASIC.
7043 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7046 ========================================================================
7048 VOID AsicAddPairwiseKeyEntry(
7049 IN PRTMP_ADAPTER pAd,
7052 IN CIPHER_KEY *pCipherKey)
7056 PUCHAR pKey = pCipherKey->Key;
7057 PUCHAR pTxMic = pCipherKey->TxMic;
7058 PUCHAR pRxMic = pCipherKey->RxMic;
7060 UCHAR CipherAlg = pCipherKey->CipherAlg;
7064 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7065 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7067 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7069 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7072 RTMP_IO_READ32(pAd, offset + i, &Value);
7075 offset += MAX_LEN_OF_PEER_KEY;
7082 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7090 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7094 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7095 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7096 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7099 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7100 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7104 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7105 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7109 ========================================================================
7111 Remove Pair-wise key material from ASIC.
7114 ========================================================================
7116 VOID AsicRemovePairwiseKeyEntry(
7117 IN PRTMP_ADAPTER pAd,
7124 // re-set the entry's WCID attribute as OPEN-NONE.
7125 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7126 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7127 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7130 BOOLEAN AsicSendCommandToMcu(
7131 IN PRTMP_ADAPTER pAd,
7137 HOST_CMD_CSR_STRUC H2MCmd;
7138 H2M_MAILBOX_STRUC H2MMailbox;
7143 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7144 if (H2MMailbox.field.Owner == 0)
7156 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7158 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7160 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7161 // Reset DMA/CPU ring index
7162 RTMPRingCleanUp(pAd, QID_AC_BK);
7163 RTMPRingCleanUp(pAd, QID_AC_BE);
7164 RTMPRingCleanUp(pAd, QID_AC_VI);
7165 RTMPRingCleanUp(pAd, QID_AC_VO);
7166 RTMPRingCleanUp(pAd, QID_HCCA);
7167 RTMPRingCleanUp(pAd, QID_MGMT);
7168 RTMPRingCleanUp(pAd, QID_RX);
7171 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7173 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7174 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7179 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7180 H2MMailbox.field.CmdToken = Token;
7181 H2MMailbox.field.HighByte = Arg1;
7182 H2MMailbox.field.LowByte = Arg0;
7183 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7186 H2MCmd.field.HostCommand = Command;
7187 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7189 if (Command != 0x80)
7196 BOOLEAN AsicCheckCommanOk(
7197 IN PRTMP_ADAPTER pAd,
7200 UINT32 CmdStatus = 0, CID = 0, i;
7201 UINT32 ThisCIDMask = 0;
7206 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7207 // Find where the command is. Because this is randomly specified by firmware.
7208 if ((CID & CID0MASK) == Command)
7210 ThisCIDMask = CID0MASK;
7213 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7215 ThisCIDMask = CID1MASK;
7218 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7220 ThisCIDMask = CID2MASK;
7223 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7225 ThisCIDMask = CID3MASK;
7233 // Get CommandStatus Value
7234 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7236 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7239 // If Status is 1, the comamnd is success.
7240 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7241 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7243 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7244 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7245 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7248 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7252 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7254 // Clear Command and Status.
7255 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7256 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7262 ========================================================================
7264 Routine Description:
7265 Verify the support rate for different PHY type
7268 pAd Pointer to our adapter
7273 IRQL = PASSIVE_LEVEL
7275 ========================================================================
7277 VOID RTMPCheckRates(
7278 IN PRTMP_ADAPTER pAd,
7279 IN OUT UCHAR SupRate[],
7280 IN OUT UCHAR *SupRateLen)
7282 UCHAR RateIdx, i, j;
7283 UCHAR NewRate[12], NewRateLen;
7287 if (pAd->CommonCfg.PhyMode == PHY_11B)
7292 // Check for support rates exclude basic rate bit
7293 for (i = 0; i < *SupRateLen; i++)
7294 for (j = 0; j < RateIdx; j++)
7295 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7296 NewRate[NewRateLen++] = SupRate[i];
7298 *SupRateLen = NewRateLen;
7299 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7302 #ifdef DOT11_N_SUPPORT
7303 BOOLEAN RTMPCheckChannel(
7304 IN PRTMP_ADAPTER pAd,
7305 IN UCHAR CentralChannel,
7309 UCHAR UpperChannel = 0, LowerChannel = 0;
7310 UCHAR NoEffectChannelinList = 0;
7312 // Find upper and lower channel according to 40MHz current operation.
7313 if (CentralChannel < Channel)
7315 UpperChannel = Channel;
7316 if (CentralChannel > 2)
7317 LowerChannel = CentralChannel - 2;
7321 else if (CentralChannel > Channel)
7323 UpperChannel = CentralChannel + 2;
7324 LowerChannel = Channel;
7327 for (k = 0;k < pAd->ChannelListNum;k++)
7329 if (pAd->ChannelList[k].Channel == UpperChannel)
7331 NoEffectChannelinList ++;
7333 if (pAd->ChannelList[k].Channel == LowerChannel)
7335 NoEffectChannelinList ++;
7339 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7340 if (NoEffectChannelinList == 2)
7347 ========================================================================
7349 Routine Description:
7350 Verify the support rate for HT phy type
7353 pAd Pointer to our adapter
7356 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7358 IRQL = PASSIVE_LEVEL
7360 ========================================================================
7362 BOOLEAN RTMPCheckHt(
7363 IN PRTMP_ADAPTER pAd,
7365 IN HT_CAPABILITY_IE *pHtCapability,
7366 IN ADD_HT_INFO_IE *pAddHtInfo)
7368 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7371 // If use AMSDU, set flag.
7372 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7373 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7374 // Save Peer Capability
7375 if (pHtCapability->HtCapInfo.ShortGIfor20)
7376 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7377 if (pHtCapability->HtCapInfo.ShortGIfor40)
7378 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7379 if (pHtCapability->HtCapInfo.TxSTBC)
7380 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7381 if (pHtCapability->HtCapInfo.RxSTBC)
7382 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7383 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7385 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7388 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7390 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7393 // Will check ChannelWidth for MCSSet[4] below
7394 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7395 switch (pAd->CommonCfg.RxStream)
7398 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7399 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7400 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7401 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7404 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7405 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7406 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7407 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7410 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7411 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7412 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7413 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7417 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7419 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7420 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7421 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7423 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7425 // Send Assoc Req with my HT capability.
7426 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7427 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7428 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7429 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7430 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7431 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7432 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7433 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7434 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7435 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7436 if (pAd->CommonCfg.bRdg)
7438 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7439 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7442 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7443 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7445 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7448 #endif // DOT11_N_SUPPORT //
7451 ========================================================================
7453 Routine Description:
7454 Verify the support rate for different PHY type
7457 pAd Pointer to our adapter
7462 IRQL = PASSIVE_LEVEL
7464 ========================================================================
7466 VOID RTMPUpdateMlmeRate(
7467 IN PRTMP_ADAPTER pAd)
7470 UCHAR ProperMlmeRate; //= RATE_54;
7471 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7472 BOOLEAN bMatch = FALSE;
7474 switch (pAd->CommonCfg.PhyMode)
7477 ProperMlmeRate = RATE_11;
7478 MinimumRate = RATE_1;
7480 case PHY_11BG_MIXED:
7481 #ifdef DOT11_N_SUPPORT
7482 case PHY_11ABGN_MIXED:
7483 case PHY_11BGN_MIXED:
7484 #endif // DOT11_N_SUPPORT //
7485 if ((pAd->MlmeAux.SupRateLen == 4) &&
7486 (pAd->MlmeAux.ExtRateLen == 0))
7488 ProperMlmeRate = RATE_11;
7490 ProperMlmeRate = RATE_24;
7492 if (pAd->MlmeAux.Channel <= 14)
7493 MinimumRate = RATE_1;
7495 MinimumRate = RATE_6;
7498 #ifdef DOT11_N_SUPPORT
7499 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7500 case PHY_11GN_MIXED:
7501 case PHY_11AGN_MIXED:
7502 case PHY_11AN_MIXED:
7504 #endif // DOT11_N_SUPPORT //
7505 ProperMlmeRate = RATE_24;
7506 MinimumRate = RATE_6;
7508 case PHY_11ABG_MIXED:
7509 ProperMlmeRate = RATE_24;
7510 if (pAd->MlmeAux.Channel <= 14)
7511 MinimumRate = RATE_1;
7513 MinimumRate = RATE_6;
7516 ProperMlmeRate = RATE_1;
7517 MinimumRate = RATE_1;
7521 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7523 for (j = 0; j < RateIdx; j++)
7525 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7527 if (j == ProperMlmeRate)
7539 if (bMatch == FALSE)
7541 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7543 for (j = 0; j < RateIdx; j++)
7545 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7547 if (j == ProperMlmeRate)
7560 if (bMatch == FALSE)
7562 ProperMlmeRate = MinimumRate;
7565 pAd->CommonCfg.MlmeRate = MinimumRate;
7566 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7567 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7569 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7570 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7571 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7572 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7576 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7577 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7578 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7579 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7582 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7586 IN PRTMP_ADAPTER pAd,
7593 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7598 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7600 larger = max(Rssi0, Rssi1);
7603 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7605 larger = max(larger, Rssi2);
7615 ========================================================================
7616 Routine Description:
7617 Periodic evaluate antenna link status
7620 pAd - Adapter pointer
7625 ========================================================================
7627 VOID AsicEvaluateRxAnt(
7628 IN PRTMP_ADAPTER pAd)
7632 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7634 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7635 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7636 fRTMP_ADAPTER_RADIO_OFF |
7637 fRTMP_ADAPTER_NIC_NOT_EXIST |
7638 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7641 if (pAd->StaCfg.Psm == PWR_SAVE)
7645 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7647 if(pAd->Antenna.field.RxPath == 3)
7651 else if(pAd->Antenna.field.RxPath == 2)
7655 else if(pAd->Antenna.field.RxPath == 1)
7659 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7661 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7662 pAd->StaCfg.BBPR3 = BBPR3;
7664 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7667 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7668 pAd->RalinkCounters.OneSecTxRetryOkCount +
7669 pAd->RalinkCounters.OneSecTxFailCount;
7671 if (TxTotalCnt > 50)
7673 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7674 pAd->Mlme.bLowThroughput = FALSE;
7678 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7679 pAd->Mlme.bLowThroughput = TRUE;
7685 ========================================================================
7686 Routine Description:
7687 After evaluation, check antenna link status
7690 pAd - Adapter pointer
7695 ========================================================================
7697 VOID AsicRxAntEvalTimeout(
7698 IN PVOID SystemSpecific1,
7699 IN PVOID FunctionContext,
7700 IN PVOID SystemSpecific2,
7701 IN PVOID SystemSpecific3)
7703 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7705 CHAR larger = -127, rssi0, rssi1, rssi2;
7707 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7709 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7710 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7711 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7712 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7715 if (pAd->StaCfg.Psm == PWR_SAVE)
7719 // if the traffic is low, use average rssi as the criteria
7720 if (pAd->Mlme.bLowThroughput == TRUE)
7722 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7723 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7724 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7728 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7729 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7730 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7733 if(pAd->Antenna.field.RxPath == 3)
7735 larger = max(rssi0, rssi1);
7737 if (larger > (rssi2 + 20))
7738 pAd->Mlme.RealRxPath = 2;
7740 pAd->Mlme.RealRxPath = 3;
7742 else if(pAd->Antenna.field.RxPath == 2)
7744 if (rssi0 > (rssi1 + 20))
7745 pAd->Mlme.RealRxPath = 1;
7747 pAd->Mlme.RealRxPath = 2;
7750 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7752 if(pAd->Mlme.RealRxPath == 3)
7756 else if(pAd->Mlme.RealRxPath == 2)
7760 else if(pAd->Mlme.RealRxPath == 1)
7764 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7765 pAd->StaCfg.BBPR3 = BBPR3;
7771 VOID APSDPeriodicExec(
7772 IN PVOID SystemSpecific1,
7773 IN PVOID FunctionContext,
7774 IN PVOID SystemSpecific2,
7775 IN PVOID SystemSpecific3)
7777 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7779 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7782 pAd->CommonCfg.TriggerTimerCount++;
7787 ========================================================================
7788 Routine Description:
7789 Set/reset MAC registers according to bPiggyBack parameter
7792 pAd - Adapter pointer
7793 bPiggyBack - Enable / Disable Piggy-Back
7798 ========================================================================
7800 VOID RTMPSetPiggyBack(
7801 IN PRTMP_ADAPTER pAd,
7802 IN BOOLEAN bPiggyBack)
7804 TX_LINK_CFG_STRUC TxLinkCfg;
7806 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7808 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7809 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7813 ========================================================================
7814 Routine Description:
7815 check if this entry need to switch rate automatically
7825 ========================================================================
7827 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7828 IN PRTMP_ADAPTER pAd,
7829 IN PMAC_TABLE_ENTRY pEntry)
7831 BOOLEAN result = TRUE;
7833 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7835 // only associated STA counts
7836 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7838 result = pAd->StaCfg.bAutoTxRateSwitch;
7848 BOOLEAN RTMPAutoRateSwitchCheck(
7849 IN PRTMP_ADAPTER pAd)
7851 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7853 if (pAd->StaCfg.bAutoTxRateSwitch)
7862 ========================================================================
7863 Routine Description:
7864 check if this entry need to fix tx legacy rate
7874 ========================================================================
7876 UCHAR RTMPStaFixedTxMode(
7877 IN PRTMP_ADAPTER pAd,
7878 IN PMAC_TABLE_ENTRY pEntry)
7880 UCHAR tx_mode = FIXED_TXMODE_HT;
7882 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7884 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7891 ========================================================================
7892 Routine Description:
7893 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
7903 ========================================================================
7905 VOID RTMPUpdateLegacyTxSetting(
7906 UCHAR fixed_tx_mode,
7907 PMAC_TABLE_ENTRY pEntry)
7909 HTTRANSMIT_SETTING TransmitSetting;
7911 if (fixed_tx_mode == FIXED_TXMODE_HT)
7914 TransmitSetting.word = 0;
7916 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
7917 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
7919 if (fixed_tx_mode == FIXED_TXMODE_CCK)
7921 TransmitSetting.field.MODE = MODE_CCK;
7922 // CCK mode allow MCS 0~3
7923 if (TransmitSetting.field.MCS > MCS_3)
7924 TransmitSetting.field.MCS = MCS_3;
7928 TransmitSetting.field.MODE = MODE_OFDM;
7929 // OFDM mode allow MCS 0~7
7930 if (TransmitSetting.field.MCS > MCS_7)
7931 TransmitSetting.field.MCS = MCS_7;
7934 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
7936 pEntry->HTPhyMode.word = TransmitSetting.word;
7937 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
7938 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
7943 ==========================================================================
7945 dynamic tune BBP R66 to find a balance between sensibility and
7948 IRQL = DISPATCH_LEVEL
7950 ==========================================================================
7952 VOID AsicStaBbpTuning(
7953 IN PRTMP_ADAPTER pAd)
7955 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
7958 // 2860C did not support Fase CCA, therefore can't tune
7959 if (pAd->MACVersion == 0x28600100)
7965 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
7968 if ((pAd->OpMode == OPMODE_STA)
7969 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7971 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
7972 && (pAd->bPCIclkOff == FALSE))
7974 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
7977 if (pAd->Antenna.field.RxPath > 1)
7978 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
7980 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
7982 if (pAd->LatchRfRegs.Channel <= 14)
7985 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7987 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
7988 if (OrigR66Value != R66)
7990 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7995 R66 = 0x2E + GET_LNA_GAIN(pAd);
7996 if (OrigR66Value != R66)
7998 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8005 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8007 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8009 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8010 if (OrigR66Value != R66)
8012 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8017 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8018 if (OrigR66Value != R66)
8020 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8026 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8028 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8029 if (OrigR66Value != R66)
8031 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8036 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8037 if (OrigR66Value != R66)
8039 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8049 VOID AsicResetFromDMABusy(
8050 IN PRTMP_ADAPTER pAd)
8053 BOOLEAN bCtrl = FALSE;
8055 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8057 // Be sure restore link control value so we can write register.
8058 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8059 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8061 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8062 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8063 RTMPusecDelay(6000);
8064 pAd->bPCIclkOff = FALSE;
8068 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8070 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8072 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8073 // Reset DMA/CPU ring index
8074 RTMPRingCleanUp(pAd, QID_AC_BK);
8075 RTMPRingCleanUp(pAd, QID_AC_BE);
8076 RTMPRingCleanUp(pAd, QID_AC_VI);
8077 RTMPRingCleanUp(pAd, QID_AC_VO);
8078 RTMPRingCleanUp(pAd, QID_HCCA);
8079 RTMPRingCleanUp(pAd, QID_MGMT);
8080 RTMPRingCleanUp(pAd, QID_RX);
8083 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8085 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8087 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8088 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8089 RTMPPCIeLinkCtrlSetting(pAd, 3);
8091 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8092 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8093 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8097 IN PRTMP_ADAPTER pAd)
8099 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8101 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8102 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8103 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8105 // After hard-reset BBP, initialize all BBP values.
8106 NICRestoreBBPValue(pAd);
8107 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8111 IN PRTMP_ADAPTER pAd)
8115 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8116 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8118 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8120 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8122 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8126 IN PRTMP_ADAPTER pAd)
8128 ULONG Value1, Value2;
8131 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8132 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8135 // sum should be equals to 0xff, which is the total buffer size.
8136 if ((Value1 + Value2) < 0xff)
8138 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8139 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8141 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8143 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8145 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8149 VOID RTMPSetAGCInitValue(
8150 IN PRTMP_ADAPTER pAd,
8155 if (pAd->LatchRfRegs.Channel <= 14)
8157 R66 = 0x2E + GET_LNA_GAIN(pAd);
8158 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8162 if (BandWidth == BW_20)
8164 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8165 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8167 #ifdef DOT11_N_SUPPORT
8170 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8171 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8173 #endif // DOT11_N_SUPPORT //
8178 VOID AsicTurnOffRFClk(
8179 IN PRTMP_ADAPTER pAd,
8184 UINT32 R1 = 0, R2 = 0, R3 = 0;
8186 RTMP_RF_REGS *RFRegTable;
8188 RFRegTable = RF2850RegTable;
8190 switch (pAd->RfIcType)
8197 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8199 if (Channel == RFRegTable[index].Channel)
8201 R1 = RFRegTable[index].R1 & 0xffffdfff;
8202 R2 = RFRegTable[index].R2 & 0xfffbffff;
8203 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8205 RTMP_RF_IO_WRITE32(pAd, R1);
8206 RTMP_RF_IO_WRITE32(pAd, R2);
8208 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8209 // Set RF R2 bit18=0, R3 bit[18:19]=0
8210 //if (pAd->StaCfg.bRadio == FALSE)
8213 RTMP_RF_IO_WRITE32(pAd, R3);
8215 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8216 Channel, pAd->RfIcType, R2, R3));
8219 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8220 Channel, pAd->RfIcType, R2));
8232 VOID AsicTurnOnRFClk(
8233 IN PRTMP_ADAPTER pAd,
8238 UINT32 R1 = 0, R2 = 0, R3 = 0;
8240 RTMP_RF_REGS *RFRegTable;
8242 RFRegTable = RF2850RegTable;
8244 switch (pAd->RfIcType)
8251 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8253 if (Channel == RFRegTable[index].Channel)
8255 R3 = pAd->LatchRfRegs.R3;
8258 RTMP_RF_IO_WRITE32(pAd, R3);
8260 R1 = RFRegTable[index].R1;
8261 RTMP_RF_IO_WRITE32(pAd, R1);
8263 R2 = RFRegTable[index].R2;
8264 if (pAd->Antenna.field.TxPath == 1)
8266 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8269 if (pAd->Antenna.field.RxPath == 2)
8271 R2 |= 0x40; // write 1 to off Rxpath.
8273 else if (pAd->Antenna.field.RxPath == 1)
8275 R2 |= 0x20040; // write 1 to off RxPath
8277 RTMP_RF_IO_WRITE32(pAd, R2);
8288 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",