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 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
55 UCHAR RateSwitchTable[] = {
56 // 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)
57 0x11, 0x00, 0, 0, 0, // Initial used item after association
58 0x00, 0x00, 0, 40, 101,
59 0x01, 0x00, 1, 40, 50,
60 0x02, 0x00, 2, 35, 45,
61 0x03, 0x00, 3, 20, 45,
62 0x04, 0x21, 0, 30, 50,
63 0x05, 0x21, 1, 20, 50,
64 0x06, 0x21, 2, 20, 50,
65 0x07, 0x21, 3, 15, 50,
66 0x08, 0x21, 4, 15, 30,
67 0x09, 0x21, 5, 10, 25,
70 0x0c, 0x20, 12, 15, 30,
71 0x0d, 0x20, 13, 8, 20,
72 0x0e, 0x20, 14, 8, 20,
73 0x0f, 0x20, 15, 8, 25,
74 0x10, 0x22, 15, 8, 25,
92 UCHAR RateSwitchTable11B[] = {
93 // 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)
94 0x04, 0x03, 0, 0, 0, // Initial used item after association
95 0x00, 0x00, 0, 40, 101,
96 0x01, 0x00, 1, 40, 50,
97 0x02, 0x00, 2, 35, 45,
98 0x03, 0x00, 3, 20, 45,
101 UCHAR RateSwitchTable11BG[] = {
102 // 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)
103 0x0a, 0x00, 0, 0, 0, // Initial used item after association
104 0x00, 0x00, 0, 40, 101,
105 0x01, 0x00, 1, 40, 50,
106 0x02, 0x00, 2, 35, 45,
107 0x03, 0x00, 3, 20, 45,
108 0x04, 0x10, 2, 20, 35,
109 0x05, 0x10, 3, 16, 35,
110 0x06, 0x10, 4, 10, 25,
111 0x07, 0x10, 5, 16, 25,
112 0x08, 0x10, 6, 10, 25,
113 0x09, 0x10, 7, 10, 13,
116 UCHAR RateSwitchTable11G[] = {
117 // 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)
118 0x08, 0x00, 0, 0, 0, // Initial used item after association
119 0x00, 0x10, 0, 20, 101,
120 0x01, 0x10, 1, 20, 35,
121 0x02, 0x10, 2, 20, 35,
122 0x03, 0x10, 3, 16, 35,
123 0x04, 0x10, 4, 10, 25,
124 0x05, 0x10, 5, 16, 25,
125 0x06, 0x10, 6, 10, 25,
126 0x07, 0x10, 7, 10, 13,
129 UCHAR RateSwitchTable11N1S[] = {
130 // 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)
131 0x09, 0x00, 0, 0, 0, // Initial used item after association
132 0x00, 0x21, 0, 30, 101,
133 0x01, 0x21, 1, 20, 50,
134 0x02, 0x21, 2, 20, 50,
135 0x03, 0x21, 3, 15, 50,
136 0x04, 0x21, 4, 15, 30,
137 0x05, 0x21, 5, 10, 25,
138 0x06, 0x21, 6, 8, 14,
139 0x07, 0x21, 7, 8, 14,
140 0x08, 0x23, 7, 8, 14,
143 UCHAR RateSwitchTable11N2S[] = {
144 // 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)
145 0x0a, 0x00, 0, 0, 0, // Initial used item after association
146 0x00, 0x21, 0, 30, 101,
147 0x01, 0x21, 1, 20, 50,
148 0x02, 0x21, 2, 20, 50,
149 0x03, 0x21, 3, 15, 50,
150 0x04, 0x21, 4, 15, 30,
151 0x05, 0x20, 12, 15, 30,
152 0x06, 0x20, 13, 8, 20,
153 0x07, 0x20, 14, 8, 20,
154 0x08, 0x20, 15, 8, 25,
155 0x09, 0x22, 15, 8, 25,
158 UCHAR RateSwitchTable11N3S[] = {
159 // 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)
160 0x0a, 0x00, 0, 0, 0, // Initial used item after association
161 0x00, 0x21, 0, 30, 101,
162 0x01, 0x21, 1, 20, 50,
163 0x02, 0x21, 2, 20, 50,
164 0x03, 0x21, 3, 15, 50,
165 0x04, 0x21, 4, 15, 30,
166 0x05, 0x20, 12, 15, 30,
167 0x06, 0x20, 13, 8, 20,
168 0x07, 0x20, 14, 8, 20,
169 0x08, 0x20, 15, 8, 25,
170 0x09, 0x22, 15, 8, 25,
173 UCHAR RateSwitchTable11N2SForABand[] = {
174 // 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)
175 0x0b, 0x09, 0, 0, 0, // Initial used item after association
176 0x00, 0x21, 0, 30, 101,
177 0x01, 0x21, 1, 20, 50,
178 0x02, 0x21, 2, 20, 50,
179 0x03, 0x21, 3, 15, 50,
180 0x04, 0x21, 4, 15, 30,
181 0x05, 0x21, 5, 15, 30,
182 0x06, 0x20, 12, 15, 30,
183 0x07, 0x20, 13, 8, 20,
184 0x08, 0x20, 14, 8, 20,
185 0x09, 0x20, 15, 8, 25,
186 0x0a, 0x22, 15, 8, 25,
189 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
190 // 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)
191 0x0b, 0x09, 0, 0, 0, // Initial used item after association
192 0x00, 0x21, 0, 30, 101,
193 0x01, 0x21, 1, 20, 50,
194 0x02, 0x21, 2, 20, 50,
195 0x03, 0x21, 3, 15, 50,
196 0x04, 0x21, 4, 15, 30,
197 0x05, 0x21, 5, 15, 30,
198 0x06, 0x20, 12, 15, 30,
199 0x07, 0x20, 13, 8, 20,
200 0x08, 0x20, 14, 8, 20,
201 0x09, 0x20, 15, 8, 25,
202 0x0a, 0x22, 15, 8, 25,
205 UCHAR RateSwitchTable11BGN1S[] = {
206 // 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)
207 0x0d, 0x00, 0, 0, 0, // Initial used item after association
208 0x00, 0x00, 0, 40, 101,
209 0x01, 0x00, 1, 40, 50,
210 0x02, 0x00, 2, 35, 45,
211 0x03, 0x00, 3, 20, 45,
212 0x04, 0x21, 0, 30,101, //50
213 0x05, 0x21, 1, 20, 50,
214 0x06, 0x21, 2, 20, 50,
215 0x07, 0x21, 3, 15, 50,
216 0x08, 0x21, 4, 15, 30,
217 0x09, 0x21, 5, 10, 25,
218 0x0a, 0x21, 6, 8, 14,
219 0x0b, 0x21, 7, 8, 14,
220 0x0c, 0x23, 7, 8, 14,
223 UCHAR RateSwitchTable11BGN2S[] = {
224 // 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)
225 0x0a, 0x00, 0, 0, 0, // Initial used item after association
226 0x00, 0x21, 0, 30,101, //50
227 0x01, 0x21, 1, 20, 50,
228 0x02, 0x21, 2, 20, 50,
229 0x03, 0x21, 3, 15, 50,
230 0x04, 0x21, 4, 15, 30,
231 0x05, 0x20, 12, 15, 30,
232 0x06, 0x20, 13, 8, 20,
233 0x07, 0x20, 14, 8, 20,
234 0x08, 0x20, 15, 8, 25,
235 0x09, 0x22, 15, 8, 25,
238 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
239 // 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)
240 0x0a, 0x00, 0, 0, 0, // Initial used item after association
241 0x00, 0x21, 0, 30,101, //50
242 0x01, 0x21, 1, 20, 50,
243 0x02, 0x21, 2, 20, 50,
244 0x03, 0x21, 3, 20, 50,
245 0x04, 0x21, 4, 15, 50,
247 0x05, 0x20, 20, 15, 30,
248 0x06, 0x20, 21, 8, 20,
249 0x07, 0x20, 22, 8, 20,
250 0x08, 0x20, 23, 8, 25,
251 0x09, 0x22, 23, 8, 25,
252 #else // for RT2860 2*3 test
253 0x05, 0x20, 12, 15, 30,
254 0x06, 0x20, 13, 8, 20,
255 0x07, 0x20, 14, 8, 20,
256 0x08, 0x20, 15, 8, 25,
257 0x09, 0x22, 15, 8, 25,
261 UCHAR RateSwitchTable11BGN2SForABand[] = {
262 // 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)
263 0x0b, 0x09, 0, 0, 0, // Initial used item after association
264 0x00, 0x21, 0, 30,101, //50
265 0x01, 0x21, 1, 20, 50,
266 0x02, 0x21, 2, 20, 50,
267 0x03, 0x21, 3, 15, 50,
268 0x04, 0x21, 4, 15, 30,
269 0x05, 0x21, 5, 15, 30,
270 0x06, 0x20, 12, 15, 30,
271 0x07, 0x20, 13, 8, 20,
272 0x08, 0x20, 14, 8, 20,
273 0x09, 0x20, 15, 8, 25,
274 0x0a, 0x22, 15, 8, 25,
277 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
278 // 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)
279 0x0c, 0x09, 0, 0, 0, // Initial used item after association
280 0x00, 0x21, 0, 30,101, //50
281 0x01, 0x21, 1, 20, 50,
282 0x02, 0x21, 2, 20, 50,
283 0x03, 0x21, 3, 15, 50,
284 0x04, 0x21, 4, 15, 30,
285 0x05, 0x21, 5, 15, 30,
286 0x06, 0x21, 12, 15, 30,
287 0x07, 0x20, 20, 15, 30,
288 0x08, 0x20, 21, 8, 20,
289 0x09, 0x20, 22, 8, 20,
290 0x0a, 0x20, 23, 8, 25,
291 0x0b, 0x22, 23, 8, 25,
294 PUCHAR ReasonString[] = {
296 /* 1 */ "Unspecified Reason",
297 /* 2 */ "Previous Auth no longer valid",
298 /* 3 */ "STA is leaving / has left",
299 /* 4 */ "DIS-ASSOC due to inactivity",
300 /* 5 */ "AP unable to hanle all associations",
301 /* 6 */ "class 2 error",
302 /* 7 */ "class 3 error",
303 /* 8 */ "STA is leaving / has left",
304 /* 9 */ "require auth before assoc/re-assoc",
308 /* 13 */ "invalid IE",
309 /* 14 */ "MIC error",
310 /* 15 */ "4-way handshake timeout",
311 /* 16 */ "2-way (group key) handshake timeout",
312 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
316 extern UCHAR OfdmRateToRxwiMCS[];
317 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
318 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
319 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
320 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
321 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
323 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
324 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
325 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
327 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
328 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
329 // clean environment.
330 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
331 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
333 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
334 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
336 UCHAR SsidIe = IE_SSID;
337 UCHAR SupRateIe = IE_SUPP_RATES;
338 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
339 UCHAR HtCapIe = IE_HT_CAP;
340 UCHAR AddHtInfoIe = IE_ADD_HT;
341 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
342 UCHAR ErpIe = IE_ERP;
343 UCHAR DsIe = IE_DS_PARM;
344 UCHAR TimIe = IE_TIM;
345 UCHAR WpaIe = IE_WPA;
346 UCHAR Wpa2Ie = IE_WPA2;
347 UCHAR IbssIe = IE_IBSS_PARM;
348 UCHAR Ccx2Ie = IE_CCX_V2;
349 UCHAR WapiIe = IE_WAPI;
351 extern UCHAR WPA_OUI[];
353 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
355 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
356 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
358 // Reset the RFIC setting to new series
359 RTMP_RF_REGS RF2850RegTable[] = {
360 // ch R1 R2 R3(TX0~4=0) R4
361 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
362 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
363 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
364 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
365 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
366 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
367 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
368 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
369 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
370 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
371 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
372 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
373 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
374 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
376 // 802.11 UNI / HyperLan 2
377 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
378 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
379 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
380 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
381 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
382 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
383 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
384 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
385 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
386 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
387 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
388 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
391 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
393 // 2008.04.30 modified
394 // The system team has AN to improve the EVM value
395 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
396 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
397 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
398 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
400 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
401 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
402 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
403 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
404 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
405 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
406 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
407 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
408 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
409 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
410 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
411 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
414 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
415 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
416 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
417 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
418 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
419 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
420 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
423 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
424 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
425 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
426 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
427 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
428 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
429 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
431 // still lack of MMAC(Japan) ch 34,38,42,46
433 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
435 FREQUENCY_ITEM FreqItems3020[] =
437 /**************************************************/
438 // ISM : 2.4 to 2.483 GHz //
439 /**************************************************/
441 /**************************************************/
442 //-CH---N-------R---K-----------
458 //2008/07/10:KH Modified to share this variable
459 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
462 ==========================================================================
464 initialize the MLME task and its data structure (queue, spinlock,
465 timer, state machines).
470 always return NDIS_STATUS_SUCCESS
472 ==========================================================================
474 NDIS_STATUS MlmeInit(
475 IN PRTMP_ADAPTER pAd)
477 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
479 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
483 Status = MlmeQueueInit(&pAd->Mlme.Queue);
484 if(Status != NDIS_STATUS_SUCCESS)
487 pAd->Mlme.bRunning = FALSE;
488 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
491 BssTableInit(&pAd->ScanTab);
493 // init STA state machines
494 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
495 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
496 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
497 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
498 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
499 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
501 // Since we are using switch/case to implement it, the init is different from the above
502 // state machine init
503 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
506 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
508 // Init mlme periodic timer
509 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
511 // Set mlme periodic timer
512 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
514 // software-based RX Antenna diversity
515 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
518 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
524 ==========================================================================
526 main loop of the MLME
528 Mlme has to be initialized, and there are something inside the queue
530 This function is invoked from MPSetInformation and MPReceive;
531 This task guarantee only one MlmeHandler will run.
533 IRQL = DISPATCH_LEVEL
535 ==========================================================================
538 IN PRTMP_ADAPTER pAd)
540 MLME_QUEUE_ELEM *Elem = NULL;
542 // Only accept MLME and Frame from peer side, no other (control/data) frame should
543 // get into this state machine
545 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
546 if(pAd->Mlme.bRunning)
548 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
553 pAd->Mlme.bRunning = TRUE;
555 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
557 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
559 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
560 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
561 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
563 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
567 //From message type, determine which state machine I should drive
568 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
571 if (Elem->MsgType == MT2_RESET_CONF)
573 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
574 MlmeRestartStateMachine(pAd);
575 Elem->Occupied = FALSE;
581 // if dequeue success
582 switch (Elem->Machine)
584 // STA state machines
585 case ASSOC_STATE_MACHINE:
586 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
588 case AUTH_STATE_MACHINE:
589 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
591 case AUTH_RSP_STATE_MACHINE:
592 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
594 case SYNC_STATE_MACHINE:
595 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
597 case MLME_CNTL_STATE_MACHINE:
598 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
600 case WPA_PSK_STATE_MACHINE:
601 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
603 case AIRONET_STATE_MACHINE:
604 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
606 case ACTION_STATE_MACHINE:
607 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
614 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
619 Elem->Occupied = FALSE;
624 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
628 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
629 pAd->Mlme.bRunning = FALSE;
630 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
634 ==========================================================================
636 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
638 Adapter - NIC Adapter pointer
640 The MLME task will no longer work properly
644 ==========================================================================
647 IN PRTMP_ADAPTER pAd)
651 UINT32 TxPinCfg = 0x00050F0F;
654 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
656 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
658 // disable BEACON generation and other BEACON related hardware timers
659 AsicDisableSync(pAd);
663 // Cancel pending timers
664 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
665 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
666 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
667 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
668 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
669 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &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 LED_CFG_STRUC LedCfg;
685 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
686 LedCfg.field.LedPolar = 0;
687 LedCfg.field.RLedMode = 0;
688 LedCfg.field.GLedMode = 0;
689 LedCfg.field.YLedMode = 0;
690 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
697 if (IS_RT3070(pAd) || IS_RT3071(pAd))
699 TxPinCfg &= 0xFFFFF0F0;
700 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
705 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
707 MlmeQueueDestroy(&pAd->Mlme.Queue);
708 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
710 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
713 VOID MlmeResetRalinkCounters(
714 IN PRTMP_ADAPTER pAd)
716 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
717 // clear all OneSecxxx counters.
718 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
719 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
720 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
721 pAd->RalinkCounters.OneSecRxOkCnt = 0;
722 pAd->RalinkCounters.OneSecTxFailCount = 0;
723 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
724 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
725 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
727 // TODO: for debug only. to be removed
728 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
729 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
730 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
731 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
732 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
733 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
734 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
735 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
736 pAd->RalinkCounters.OneSecTxDoneCount = 0;
737 pAd->RalinkCounters.OneSecRxCount = 0;
738 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
739 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
744 unsigned long rx_AMSDU;
745 unsigned long rx_Total;
748 ==========================================================================
750 This routine is executed periodically to -
751 1. Decide if it's a right time to turn on PwrMgmt bit of all
753 2. Calculate ChannelQuality based on statistics of the last
754 period, so that TX rate won't toggling very frequently between a
755 successful TX and a failed TX.
756 3. If the calculated ChannelQuality indicated current connection not
757 healthy, then a ROAMing attempt is tried here.
759 IRQL = DISPATCH_LEVEL
761 ==========================================================================
763 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
764 VOID MlmePeriodicExec(
765 IN PVOID SystemSpecific1,
766 IN PVOID FunctionContext,
767 IN PVOID SystemSpecific2,
768 IN PVOID SystemSpecific3)
771 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
773 // Do nothing if the driver is starting halt state.
774 // This might happen when timer already been fired before cancel timer with mlmehalt
775 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
776 fRTMP_ADAPTER_RADIO_OFF |
777 fRTMP_ADAPTER_RADIO_MEASUREMENT |
778 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
781 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
784 // Do nothing if monitor mode is on
788 if (pAd->Mlme.PeriodicRound & 0x1)
790 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
791 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
792 (STA_TGN_WIFI_ON(pAd)) &&
793 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
796 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
797 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
799 else if ((STA_TGN_WIFI_ON(pAd)) &&
800 ((pAd->MACVersion & 0xffff) == 0x0101))
802 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
803 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
808 pAd->bUpdateBcnCntDone = FALSE;
810 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
811 pAd->Mlme.PeriodicRound ++;
814 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
815 NICUpdateFifoStaCounters(pAd);
817 // execute every 500ms
818 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
820 // perform dynamic tx rate switching based on past TX history
822 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
824 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
825 MlmeDynamicTxRateSwitching(pAd);
829 // Normal 1 second Mlme PeriodicExec.
830 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
832 pAd->Mlme.OneSecPeriodicRound ++;
842 //ORIBATimerTimeout(pAd);
844 // Media status changed, report to NDIS
845 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
847 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
848 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
850 pAd->IndicateMediaState = NdisMediaStateConnected;
851 RTMP_IndicateMediaState(pAd);
856 pAd->IndicateMediaState = NdisMediaStateDisconnected;
857 RTMP_IndicateMediaState(pAd);
861 NdisGetSystemUpTime(&pAd->Mlme.Now32);
863 // add the most up-to-date h/w raw counters into software variable, so that
864 // the dynamic tuning mechanism below are based on most up-to-date information
865 NICUpdateRawCounters(pAd);
868 RT2870_WatchDog(pAd);
871 // Need statistics after read counter. So put after NICUpdateRawCounters
872 ORIBATimerTimeout(pAd);
874 // The time period for checking antenna is according to traffic
876 if (pAd->Mlme.bEnableAutoAntennaCheck)
878 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
879 pAd->RalinkCounters.OneSecTxRetryOkCount +
880 pAd->RalinkCounters.OneSecTxFailCount;
882 // dynamic adjust antenna evaluation period according to the traffic
885 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
887 AsicEvaluateRxAnt(pAd);
892 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
894 AsicEvaluateRxAnt(pAd);
900 STAMlmePeriodicExec(pAd);
902 MlmeResetRalinkCounters(pAd);
906 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
907 // and sending CTS-to-self over and over.
908 // Software Patch Solution:
909 // 1. Polling debug state register 0x10F4 every one second.
910 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
911 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
915 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
916 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
918 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
920 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
922 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
927 RT28XX_MLME_HANDLER(pAd);
931 pAd->bUpdateBcnCntDone = FALSE;
934 VOID STAMlmePeriodicExec(
940 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
942 // WPA MIC error should block association attempt for 60 seconds
943 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
944 pAd->StaCfg.bBlockAssoc = FALSE;
947 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
949 if (pAd->IndicateMediaState == NdisMediaStateConnected)
951 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
953 pAd->PreMediaState = pAd->IndicateMediaState;
959 AsicStaBbpTuning(pAd);
961 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
962 pAd->RalinkCounters.OneSecTxRetryOkCount +
963 pAd->RalinkCounters.OneSecTxFailCount;
965 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
967 // update channel quality for Roaming and UI LinkQuality display
968 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
971 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
972 // Radio is currently in noisy environment
973 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
974 AsicAdjustTxPower(pAd);
978 // Is PSM bit consistent with user power management policy?
979 // This is the only place that will set PSM bit ON.
980 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
981 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
983 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
985 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
986 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
987 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
989 RTMPSetAGCInitValue(pAd, BW_20);
990 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
993 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
994 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
996 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
998 // When APSD is enabled, the period changes as 20 sec
999 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1000 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1004 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1005 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1007 if (pAd->CommonCfg.bWmmCapable)
1008 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1010 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1015 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1017 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1018 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1019 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1021 // Lost AP, send disconnect & link down event
1022 LinkDown(pAd, FALSE);
1025 union iwreq_data wrqu;
1026 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1027 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1030 // RTMPPatchMacBbpBug(pAd);
1031 MlmeAutoReconnectLastSSID(pAd);
1033 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1035 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1036 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1037 MlmeAutoReconnectLastSSID(pAd);
1040 // Add auto seamless roaming
1041 if (pAd->StaCfg.bFastRoaming)
1043 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1045 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));
1047 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1049 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1053 else if (ADHOC_ON(pAd))
1056 if ((pAd->CommonCfg.Channel > 14)
1057 && (pAd->CommonCfg.bIEEE80211H == 1)
1058 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1060 RadarDetectPeriodic(pAd);
1063 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1064 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1066 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1067 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1069 MLME_START_REQ_STRUCT StartReq;
1071 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1072 LinkDown(pAd, FALSE);
1074 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1075 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1076 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1079 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1081 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1083 if (pEntry->ValidAsCLI == FALSE)
1086 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1087 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1090 else // no INFRA nor ADHOC connection
1093 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1094 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1095 goto SKIP_AUTO_SCAN_CONN;
1097 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1099 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1100 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1101 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1103 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1105 MLME_SCAN_REQ_STRUCT ScanReq;
1107 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1109 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1110 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1111 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1112 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1113 // Reset Missed scan number
1114 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1116 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1117 MlmeAutoReconnectLastSSID(pAd);
1119 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1121 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1124 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1128 MlmeAutoReconnectLastSSID(pAd);
1134 SKIP_AUTO_SCAN_CONN:
1136 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1138 pAd->MacTab.fAnyBASession = TRUE;
1139 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1141 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1143 pAd->MacTab.fAnyBASession = FALSE;
1144 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1152 IN PVOID SystemSpecific1,
1153 IN PVOID FunctionContext,
1154 IN PVOID SystemSpecific2,
1155 IN PVOID SystemSpecific3)
1158 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1160 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1161 RTMP_IndicateMediaState(pAd);
1162 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1165 // IRQL = DISPATCH_LEVEL
1167 IN PRTMP_ADAPTER pAd)
1169 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1170 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1172 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1174 MLME_CNTL_STATE_MACHINE,
1175 OID_802_11_BSSID_LIST_SCAN,
1178 RT28XX_MLME_HANDLER(pAd);
1182 // IRQL = DISPATCH_LEVEL
1183 VOID MlmeAutoReconnectLastSSID(
1184 IN PRTMP_ADAPTER pAd)
1188 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1189 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1190 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1192 NDIS_802_11_SSID OidSsid;
1193 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1194 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1196 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1198 MLME_CNTL_STATE_MACHINE,
1200 sizeof(NDIS_802_11_SSID),
1202 RT28XX_MLME_HANDLER(pAd);
1207 ==========================================================================
1208 Validate SSID for connection try and rescan purpose
1209 Valid SSID will have visible chars only.
1210 The valid length is from 0 to 32.
1211 IRQL = DISPATCH_LEVEL
1212 ==========================================================================
1214 BOOLEAN MlmeValidateSSID(
1220 if (SsidLen > MAX_LEN_OF_SSID)
1223 // Check each character value
1224 for (index = 0; index < SsidLen; index++)
1226 if (pSsid[index] < 0x20)
1234 VOID MlmeSelectTxRateTable(
1235 IN PRTMP_ADAPTER pAd,
1236 IN PMAC_TABLE_ENTRY pEntry,
1238 IN PUCHAR pTableSize,
1239 IN PUCHAR pInitTxRateIdx)
1243 // decide the rate table for tuning
1244 if (pAd->CommonCfg.TxRateTableSize > 0)
1246 *ppTable = RateSwitchTable;
1247 *pTableSize = RateSwitchTable[0];
1248 *pInitTxRateIdx = RateSwitchTable[1];
1253 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1255 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1256 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1257 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1259 *ppTable = RateSwitchTable11N1S;
1260 *pTableSize = RateSwitchTable11N1S[0];
1261 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1264 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1265 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1266 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1267 (pAd->Antenna.field.TxPath == 2))
1269 if (pAd->LatchRfRegs.Channel <= 14)
1271 *ppTable = RateSwitchTable11N2S;
1272 *pTableSize = RateSwitchTable11N2S[0];
1273 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1277 *ppTable = RateSwitchTable11N2SForABand;
1278 *pTableSize = RateSwitchTable11N2SForABand[0];
1279 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1284 if ((pEntry->RateLen == 4)
1285 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1288 *ppTable = RateSwitchTable11B;
1289 *pTableSize = RateSwitchTable11B[0];
1290 *pInitTxRateIdx = RateSwitchTable11B[1];
1293 else if (pAd->LatchRfRegs.Channel <= 14)
1295 *ppTable = RateSwitchTable11BG;
1296 *pTableSize = RateSwitchTable11BG[0];
1297 *pInitTxRateIdx = RateSwitchTable11BG[1];
1302 *ppTable = RateSwitchTable11G;
1303 *pTableSize = RateSwitchTable11G[0];
1304 *pInitTxRateIdx = RateSwitchTable11G[1];
1310 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1311 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1312 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1313 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1315 *ppTable = RateSwitchTable11BGN1S;
1316 *pTableSize = RateSwitchTable11BGN1S[0];
1317 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1322 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1323 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1324 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1325 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1327 if (pAd->LatchRfRegs.Channel <= 14)
1329 *ppTable = RateSwitchTable11BGN2S;
1330 *pTableSize = RateSwitchTable11BGN2S[0];
1331 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1336 *ppTable = RateSwitchTable11BGN2SForABand;
1337 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1338 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1344 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1345 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1347 *ppTable = RateSwitchTable11N1S;
1348 *pTableSize = RateSwitchTable11N1S[0];
1349 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1354 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1355 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1357 if (pAd->LatchRfRegs.Channel <= 14)
1359 *ppTable = RateSwitchTable11N2S;
1360 *pTableSize = RateSwitchTable11N2S[0];
1361 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1365 *ppTable = RateSwitchTable11N2SForABand;
1366 *pTableSize = RateSwitchTable11N2SForABand[0];
1367 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1373 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1374 if ((pEntry->RateLen == 4)
1375 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1376 // && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1379 *ppTable = RateSwitchTable11B;
1380 *pTableSize = RateSwitchTable11B[0];
1381 *pInitTxRateIdx = RateSwitchTable11B[1];
1386 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1387 if ((pEntry->RateLen > 8)
1388 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1391 *ppTable = RateSwitchTable11BG;
1392 *pTableSize = RateSwitchTable11BG[0];
1393 *pInitTxRateIdx = RateSwitchTable11BG[1];
1398 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1399 if ((pEntry->RateLen == 8)
1400 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1403 *ppTable = RateSwitchTable11G;
1404 *pTableSize = RateSwitchTable11G[0];
1405 *pInitTxRateIdx = RateSwitchTable11G[1];
1411 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1412 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1414 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1416 *ppTable = RateSwitchTable11B;
1417 *pTableSize = RateSwitchTable11B[0];
1418 *pInitTxRateIdx = RateSwitchTable11B[1];
1420 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1422 *ppTable = RateSwitchTable11G;
1423 *pTableSize = RateSwitchTable11G[0];
1424 *pInitTxRateIdx = RateSwitchTable11G[1];
1429 *ppTable = RateSwitchTable11BG;
1430 *pTableSize = RateSwitchTable11BG[0];
1431 *pInitTxRateIdx = RateSwitchTable11BG[1];
1436 if (pAd->LatchRfRegs.Channel <= 14)
1438 if (pAd->CommonCfg.TxStream == 1)
1440 *ppTable = RateSwitchTable11N1S;
1441 *pTableSize = RateSwitchTable11N1S[0];
1442 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1443 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1447 *ppTable = RateSwitchTable11N2S;
1448 *pTableSize = RateSwitchTable11N2S[0];
1449 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1450 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1455 if (pAd->CommonCfg.TxStream == 1)
1457 *ppTable = RateSwitchTable11N1S;
1458 *pTableSize = RateSwitchTable11N1S[0];
1459 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1460 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1464 *ppTable = RateSwitchTable11N2SForABand;
1465 *pTableSize = RateSwitchTable11N2SForABand[0];
1466 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1467 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1471 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1472 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1478 ==========================================================================
1480 This routine checks if there're other APs out there capable for
1481 roaming. Caller should call this routine only when Link up in INFRA mode
1482 and channel quality is below CQI_GOOD_THRESHOLD.
1484 IRQL = DISPATCH_LEVEL
1487 ==========================================================================
1489 VOID MlmeCheckForRoaming(
1490 IN PRTMP_ADAPTER pAd,
1494 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1497 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1498 // put all roaming candidates into RoamTab, and sort in RSSI order
1499 BssTableInit(pRoamTab);
1500 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1502 pBss = &pAd->ScanTab.BssEntry[i];
1504 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1505 continue; // AP disappear
1506 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1507 continue; // RSSI too weak. forget it.
1508 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1509 continue; // skip current AP
1510 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1511 continue; // only AP with stronger RSSI is eligible for roaming
1513 // AP passing all above rules is put into roaming candidate table
1514 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1515 pRoamTab->BssNr += 1;
1518 if (pRoamTab->BssNr > 0)
1520 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1521 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1523 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1524 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1525 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1526 RT28XX_MLME_HANDLER(pAd);
1529 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1533 ==========================================================================
1535 This routine checks if there're other APs out there capable for
1536 roaming. Caller should call this routine only when link up in INFRA mode
1537 and channel quality is below CQI_GOOD_THRESHOLD.
1539 IRQL = DISPATCH_LEVEL
1542 ==========================================================================
1544 VOID MlmeCheckForFastRoaming(
1545 IN PRTMP_ADAPTER pAd,
1549 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1552 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1553 // put all roaming candidates into RoamTab, and sort in RSSI order
1554 BssTableInit(pRoamTab);
1555 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1557 pBss = &pAd->ScanTab.BssEntry[i];
1559 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1560 continue; // RSSI too weak. forget it.
1561 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1562 continue; // skip current AP
1563 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1564 continue; // skip different SSID
1565 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1566 continue; // skip AP without better RSSI
1568 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));
1569 // AP passing all above rules is put into roaming candidate table
1570 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1571 pRoamTab->BssNr += 1;
1574 if (pRoamTab->BssNr > 0)
1576 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1577 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1579 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1580 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1581 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1582 RT28XX_MLME_HANDLER(pAd);
1585 // Maybe site survey required
1588 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1590 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1591 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1592 pAd->StaCfg.ScanCnt = 2;
1593 pAd->StaCfg.LastScanTime = Now;
1598 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1602 ==========================================================================
1604 This routine calculates TxPER, RxPER of the past N-sec period. And
1605 according to the calculation result, ChannelQuality is calculated here
1606 to decide if current AP is still doing the job.
1608 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1610 StaCfg.ChannelQuality - 0..100
1612 IRQL = DISPATCH_LEVEL
1614 NOTE: This routine decide channle quality based on RX CRC error ratio.
1615 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1616 is performed right before this routine, so that this routine can decide
1617 channel quality based on the most up-to-date information
1618 ==========================================================================
1620 VOID MlmeCalculateChannelQuality(
1621 IN PRTMP_ADAPTER pAd,
1624 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1628 ULONG BeaconLostTime = BEACON_LOST_TIME;
1630 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1633 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1635 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1636 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1644 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1645 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1649 // calculate RX PER - don't take RxPER into consideration if too few sample
1651 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1655 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1658 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1660 if (INFRA_ON(pAd) &&
1661 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1662 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1664 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1665 pAd->Mlme.ChannelQuality = 0;
1672 else if (MaxRssi < -90)
1675 NorRssi = (MaxRssi + 90) * 2;
1677 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1678 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1679 TX_WEIGHTING * (100 - TxPRR) +
1680 RX_WEIGHTING* (100 - RxPER)) / 100;
1681 if (pAd->Mlme.ChannelQuality >= 100)
1682 pAd->Mlme.ChannelQuality = 100;
1688 IN PRTMP_ADAPTER pAd,
1689 IN PMAC_TABLE_ENTRY pEntry,
1690 IN PRTMP_TX_RATE_SWITCH pTxRate)
1692 UCHAR MaxMode = MODE_OFDM;
1694 MaxMode = MODE_HTGREENFIELD;
1696 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1697 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1699 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1701 if (pTxRate->CurrMCS < MCS_AUTO)
1702 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1704 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1705 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1709 // If peer adhoc is b-only mode, we can't send 11g rate.
1710 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1711 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1714 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1716 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1717 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1718 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1720 // Patch speed error in status page
1721 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1725 if (pTxRate->Mode <= MaxMode)
1726 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1728 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1729 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1731 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1733 // Reexam each bandwidth's SGI support.
1734 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1736 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1737 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1738 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1739 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1742 // Turn RTS/CTS rate to 6Mbps.
1743 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1745 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1746 if (pAd->MacTab.fAnyBASession)
1748 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1752 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1755 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1757 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1758 if (pAd->MacTab.fAnyBASession)
1760 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1764 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1767 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1769 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1772 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1774 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1777 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1778 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1779 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1780 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1782 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1783 pAd->WIFItestbed.bGreenField)
1784 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1787 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1791 ==========================================================================
1793 This routine calculates the acumulated TxPER of eaxh TxRate. And
1794 according to the calculation result, change CommonCfg.TxRate which
1795 is the stable TX Rate we expect the Radio situation could sustained.
1797 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1801 IRQL = DISPATCH_LEVEL
1804 call this routine every second
1805 ==========================================================================
1807 VOID MlmeDynamicTxRateSwitching(
1808 IN PRTMP_ADAPTER pAd)
1810 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1811 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1812 ULONG TxErrorRatio = 0;
1813 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1814 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1816 UCHAR TableSize = 0;
1817 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1818 CHAR Rssi, RssiOffset = 0;
1819 TX_STA_CNT1_STRUC StaTx1;
1820 TX_STA_CNT0_STRUC TxStaCnt0;
1821 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1822 MAC_TABLE_ENTRY *pEntry;
1825 // walk through MAC table, see if need to change AP's TX rate toward each entry
1827 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1829 pEntry = &pAd->MacTab.Content[i];
1831 // check if this entry need to switch rate automatically
1832 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1835 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1837 Rssi = RTMPMaxRssi(pAd,
1838 pAd->StaCfg.RssiSample.AvgRssi0,
1839 pAd->StaCfg.RssiSample.AvgRssi1,
1840 pAd->StaCfg.RssiSample.AvgRssi2);
1842 // Update statistic counter
1843 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1844 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1845 pAd->bUpdateBcnCntDone = TRUE;
1846 TxRetransmit = StaTx1.field.TxRetransmit;
1847 TxSuccess = StaTx1.field.TxSuccess;
1848 TxFailCount = TxStaCnt0.field.TxFailCount;
1849 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1851 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1852 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1853 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1854 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1855 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1856 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1858 // if no traffic in the past 1-sec period, don't change TX rate,
1859 // but clear all bad history. because the bad history may affect the next
1860 // Chariot throughput test
1861 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1862 pAd->RalinkCounters.OneSecTxRetryOkCount +
1863 pAd->RalinkCounters.OneSecTxFailCount;
1866 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1870 if (INFRA_ON(pAd) && (i == 1))
1871 Rssi = RTMPMaxRssi(pAd,
1872 pAd->StaCfg.RssiSample.AvgRssi0,
1873 pAd->StaCfg.RssiSample.AvgRssi1,
1874 pAd->StaCfg.RssiSample.AvgRssi2);
1876 Rssi = RTMPMaxRssi(pAd,
1877 pEntry->RssiSample.AvgRssi0,
1878 pEntry->RssiSample.AvgRssi1,
1879 pEntry->RssiSample.AvgRssi2);
1881 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1882 pEntry->OneSecTxRetryOkCount +
1883 pEntry->OneSecTxFailCount;
1886 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1889 CurrRateIdx = pEntry->CurrTxRateIndex;
1891 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1893 if (CurrRateIdx >= TableSize)
1895 CurrRateIdx = TableSize - 1;
1898 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1899 // So need to sync here.
1900 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1901 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1902 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1906 // Need to sync Real Tx rate and our record.
1907 // Then return for next DRS.
1908 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1909 pEntry->CurrTxRateIndex = InitTxRateIdx;
1910 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1912 // reset all OneSecTx counters
1913 RESET_ONE_SEC_TX_CNT(pEntry);
1917 // decide the next upgrade rate and downgrade rate, if any
1918 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
1920 UpRateIdx = CurrRateIdx + 1;
1921 DownRateIdx = CurrRateIdx -1;
1923 else if (CurrRateIdx == 0)
1925 UpRateIdx = CurrRateIdx + 1;
1926 DownRateIdx = CurrRateIdx;
1928 else if (CurrRateIdx == (TableSize - 1))
1930 UpRateIdx = CurrRateIdx;
1931 DownRateIdx = CurrRateIdx - 1;
1934 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1936 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
1938 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
1939 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
1943 TrainUp = pCurrTxRate->TrainUp;
1944 TrainDown = pCurrTxRate->TrainDown;
1947 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
1950 // Keep the last time TxRateChangeAction status.
1952 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
1957 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
1958 // (criteria copied from RT2500 for Netopia case)
1960 if (TxTotalCnt <= 15)
1964 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1965 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
1966 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1967 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
1969 // check the existence and index of each needed MCS
1970 while (idx < pTable[0])
1972 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
1974 if (pCurrTxRate->CurrMCS == MCS_0)
1978 else if (pCurrTxRate->CurrMCS == MCS_1)
1982 else if (pCurrTxRate->CurrMCS == MCS_2)
1986 else if (pCurrTxRate->CurrMCS == MCS_3)
1990 else if (pCurrTxRate->CurrMCS == MCS_4)
1994 else if (pCurrTxRate->CurrMCS == MCS_5)
1998 else if (pCurrTxRate->CurrMCS == MCS_6)
2002 //else if (pCurrTxRate->CurrMCS == MCS_7)
2003 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2007 else if (pCurrTxRate->CurrMCS == MCS_12)
2011 else if (pCurrTxRate->CurrMCS == MCS_13)
2015 else if (pCurrTxRate->CurrMCS == MCS_14)
2019 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800))
2023 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2027 else if (pCurrTxRate->CurrMCS == MCS_21)
2031 else if (pCurrTxRate->CurrMCS == MCS_22)
2035 else if (pCurrTxRate->CurrMCS == MCS_23)
2042 if (pAd->LatchRfRegs.Channel <= 14)
2044 if (pAd->NicConfig2.field.ExternalLNAForG)
2055 if (pAd->NicConfig2.field.ExternalLNAForA)
2066 if ((pTable == RateSwitchTable11BGN3S) ||
2067 (pTable == RateSwitchTable11N3S) ||
2068 (pTable == RateSwitchTable))
2069 {// N mode with 3 stream // 3*3
2070 if (MCS23 && (Rssi >= -70))
2072 else if (MCS22 && (Rssi >= -72))
2074 else if (MCS21 && (Rssi >= -76))
2076 else if (MCS20 && (Rssi >= -78))
2078 else if (MCS4 && (Rssi >= -82))
2080 else if (MCS3 && (Rssi >= -84))
2082 else if (MCS2 && (Rssi >= -86))
2084 else if (MCS1 && (Rssi >= -88))
2089 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2090 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2091 {// N mode with 2 stream
2092 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2094 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2096 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2098 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2100 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2102 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2104 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2106 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2111 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2112 {// N mode with 1 stream
2113 if (MCS7 && (Rssi > (-72+RssiOffset)))
2115 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2117 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2119 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2121 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2123 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2125 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2132 if (MCS7 && (Rssi > -70))
2134 else if (MCS6 && (Rssi > -74))
2136 else if (MCS5 && (Rssi > -78))
2138 else if (MCS4 && (Rssi > -82))
2140 else if (MCS4 == 0) // for B-only mode
2142 else if (MCS3 && (Rssi > -85))
2144 else if (MCS2 && (Rssi > -87))
2146 else if (MCS1 && (Rssi > -90))
2152 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2154 pEntry->CurrTxRateIndex = TxRateIdx;
2155 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2156 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2159 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2160 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2161 pEntry->fLastSecAccordingRSSI = TRUE;
2162 // reset all OneSecTx counters
2163 RESET_ONE_SEC_TX_CNT(pEntry);
2168 if (pEntry->fLastSecAccordingRSSI == TRUE)
2170 pEntry->fLastSecAccordingRSSI = FALSE;
2171 pEntry->LastSecTxRateChangeAction = 0;
2172 // reset all OneSecTx counters
2173 RESET_ONE_SEC_TX_CNT(pEntry);
2180 BOOLEAN bTrainUpDown = FALSE;
2182 pEntry->CurrTxRateStableTime ++;
2184 // downgrade TX quality if PER >= Rate-Down threshold
2185 if (TxErrorRatio >= TrainDown)
2187 bTrainUpDown = TRUE;
2188 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2190 // upgrade TX quality if PER <= Rate-Up threshold
2191 else if (TxErrorRatio <= TrainUp)
2193 bTrainUpDown = TRUE;
2194 bUpgradeQuality = TRUE;
2195 if (pEntry->TxQuality[CurrRateIdx])
2196 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2198 if (pEntry->TxRateUpPenalty)
2199 pEntry->TxRateUpPenalty --;
2200 else if (pEntry->TxQuality[UpRateIdx])
2201 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2204 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2208 // perform DRS - consider TxRate Down first, then rate up.
2209 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2211 pEntry->CurrTxRateIndex = DownRateIdx;
2213 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2215 pEntry->CurrTxRateIndex = UpRateIdx;
2220 // if rate-up happen, clear all bad history of all TX rates
2221 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2223 pEntry->CurrTxRateStableTime = 0;
2224 pEntry->TxRateUpPenalty = 0;
2225 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2226 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2227 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2230 // For TxRate fast train up
2232 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2234 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2236 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2238 bTxRateChanged = TRUE;
2240 // if rate-down happen, only clear DownRate's bad history
2241 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2243 pEntry->CurrTxRateStableTime = 0;
2244 pEntry->TxRateUpPenalty = 0; // no penalty
2245 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2246 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2247 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2250 // For TxRate fast train down
2252 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2254 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2256 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2258 bTxRateChanged = TRUE;
2262 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2263 bTxRateChanged = FALSE;
2266 pEntry->LastTxOkCount = TxSuccess;
2268 // reset all OneSecTx counters
2269 RESET_ONE_SEC_TX_CNT(pEntry);
2271 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2272 if (bTxRateChanged && pNextTxRate)
2274 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2280 ========================================================================
2281 Routine Description:
2282 Station side, Auto TxRate faster train up timer call back function.
2285 SystemSpecific1 - Not used.
2286 FunctionContext - Pointer to our Adapter context.
2287 SystemSpecific2 - Not used.
2288 SystemSpecific3 - Not used.
2293 ========================================================================
2295 VOID StaQuickResponeForRateUpExec(
2296 IN PVOID SystemSpecific1,
2297 IN PVOID FunctionContext,
2298 IN PVOID SystemSpecific2,
2299 IN PVOID SystemSpecific3)
2301 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2302 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2304 ULONG TxErrorRatio = 0;
2305 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2306 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2308 UCHAR TableSize = 0;
2309 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2310 TX_STA_CNT1_STRUC StaTx1;
2311 TX_STA_CNT0_STRUC TxStaCnt0;
2313 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2314 MAC_TABLE_ENTRY *pEntry;
2317 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2320 // walk through MAC table, see if need to change AP's TX rate toward each entry
2322 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2324 pEntry = &pAd->MacTab.Content[i];
2326 // check if this entry need to switch rate automatically
2327 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2330 if (INFRA_ON(pAd) && (i == 1))
2331 Rssi = RTMPMaxRssi(pAd,
2332 pAd->StaCfg.RssiSample.AvgRssi0,
2333 pAd->StaCfg.RssiSample.AvgRssi1,
2334 pAd->StaCfg.RssiSample.AvgRssi2);
2336 Rssi = RTMPMaxRssi(pAd,
2337 pEntry->RssiSample.AvgRssi0,
2338 pEntry->RssiSample.AvgRssi1,
2339 pEntry->RssiSample.AvgRssi2);
2341 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2343 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2345 // decide the next upgrade rate and downgrade rate, if any
2346 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2348 UpRateIdx = CurrRateIdx + 1;
2349 DownRateIdx = CurrRateIdx -1;
2351 else if (CurrRateIdx == 0)
2353 UpRateIdx = CurrRateIdx + 1;
2354 DownRateIdx = CurrRateIdx;
2356 else if (CurrRateIdx == (TableSize - 1))
2358 UpRateIdx = CurrRateIdx;
2359 DownRateIdx = CurrRateIdx - 1;
2362 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2364 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2366 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2367 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2371 TrainUp = pCurrTxRate->TrainUp;
2372 TrainDown = pCurrTxRate->TrainDown;
2375 if (pAd->MacTab.Size == 1)
2377 // Update statistic counter
2378 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2379 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2381 TxRetransmit = StaTx1.field.TxRetransmit;
2382 TxSuccess = StaTx1.field.TxSuccess;
2383 TxFailCount = TxStaCnt0.field.TxFailCount;
2384 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2386 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2387 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2388 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2389 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2390 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2391 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2394 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2398 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2399 pEntry->OneSecTxRetryOkCount +
2400 pEntry->OneSecTxFailCount;
2403 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2408 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2409 // (criteria copied from RT2500 for Netopia case)
2411 if (TxTotalCnt <= 12)
2413 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2414 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2416 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2418 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2419 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2421 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2423 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2426 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2432 ULONG OneSecTxNoRetryOKRationCount;
2434 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2439 // downgrade TX quality if PER >= Rate-Down threshold
2440 if (TxErrorRatio >= TrainDown)
2442 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2445 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2447 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2449 // perform DRS - consider TxRate Down first, then rate up.
2450 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2452 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2454 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2455 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2460 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2462 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2466 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2468 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2473 // if rate-up happen, clear all bad history of all TX rates
2474 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2476 pAd->DrsCounters.TxRateUpPenalty = 0;
2477 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2478 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2479 bTxRateChanged = TRUE;
2481 // if rate-down happen, only clear DownRate's bad history
2482 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2484 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2486 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2487 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2488 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2489 bTxRateChanged = TRUE;
2493 bTxRateChanged = FALSE;
2496 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2497 if (bTxRateChanged && pNextTxRate)
2499 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2505 ==========================================================================
2507 This routine is executed periodically inside MlmePeriodicExec() after
2508 association with an AP.
2509 It checks if StaCfg.Psm is consistent with user policy (recorded in
2510 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2511 there're some conditions to consider:
2512 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2513 the time when Mibss==TRUE
2514 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2515 if outgoing traffic available in TxRing or MgmtRing.
2517 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2519 IRQL = DISPATCH_LEVEL
2521 ==========================================================================
2523 VOID MlmeCheckPsmChange(
2524 IN PRTMP_ADAPTER pAd,
2530 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2531 // 2. user wants either MAX_PSP or FAST_PSP
2532 // 3. but current psm is not in PWR_SAVE
2533 // 4. CNTL state machine is not doing SCANning
2534 // 5. no TX SUCCESS event for the past 1-sec period
2535 #ifdef NDIS51_MINIPORT
2536 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2537 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2540 PowerMode = pAd->StaCfg.WindowsPowerMode;
2542 if (INFRA_ON(pAd) &&
2543 (PowerMode != Ndis802_11PowerModeCAM) &&
2544 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2545 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2546 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2547 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2548 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2550 // add by johnli, use Rx OK data count per second to calculate throughput
2551 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2552 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2553 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2555 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2557 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2558 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2560 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2562 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2565 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2566 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2567 MlmeSetPsmBit(pAd, PWR_SAVE);
2568 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2570 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2574 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2580 // IRQL = PASSIVE_LEVEL
2581 // IRQL = DISPATCH_LEVEL
2583 IN PRTMP_ADAPTER pAd,
2586 AUTO_RSP_CFG_STRUC csr4;
2588 pAd->StaCfg.Psm = psm;
2589 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2590 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2591 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2594 // IRQL = DISPATCH_LEVEL
2595 VOID MlmeSetTxPreamble(
2596 IN PRTMP_ADAPTER pAd,
2597 IN USHORT TxPreamble)
2599 AUTO_RSP_CFG_STRUC csr4;
2602 // Always use Long preamble before verifiation short preamble functionality works well.
2603 // Todo: remove the following line if short preamble functionality works
2605 //TxPreamble = Rt802_11PreambleLong;
2607 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2608 if (TxPreamble == Rt802_11PreambleLong)
2610 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2611 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2612 csr4.field.AutoResponderPreamble = 0;
2616 // NOTE: 1Mbps should always use long preamble
2617 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2618 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2619 csr4.field.AutoResponderPreamble = 1;
2622 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2626 ==========================================================================
2628 Update basic rate bitmap
2629 ==========================================================================
2632 VOID UpdateBasicRateBitmap(
2633 IN PRTMP_ADAPTER pAdapter)
2636 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2637 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2638 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2639 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2640 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2643 /* if A mode, always use fix BasicRateBitMap */
2644 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2645 if (pAdapter->CommonCfg.Channel > 14)
2646 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2649 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2651 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2655 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2661 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2663 if (bitmap & (1 << i))
2665 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2667 if (sup_p[j] == rate[i])
2672 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2674 if (ext_p[j] == rate[i])
2680 } /* End of UpdateBasicRateBitmap */
2682 // IRQL = PASSIVE_LEVEL
2683 // IRQL = DISPATCH_LEVEL
2684 // bLinkUp is to identify the inital link speed.
2685 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2686 VOID MlmeUpdateTxRates(
2687 IN PRTMP_ADAPTER pAd,
2692 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2693 UCHAR MinSupport = RATE_54;
2694 ULONG BasicRateBitmap = 0;
2695 UCHAR CurrBasicRate = RATE_1;
2696 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2697 PHTTRANSMIT_SETTING pHtPhy = NULL;
2698 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2699 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2700 BOOLEAN *auto_rate_cur_p;
2701 UCHAR HtMcs = MCS_AUTO;
2703 // find max desired rate
2704 UpdateBasicRateBitmap(pAd);
2707 auto_rate_cur_p = NULL;
2708 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2710 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2712 case 2: Rate = RATE_1; num++; break;
2713 case 4: Rate = RATE_2; num++; break;
2714 case 11: Rate = RATE_5_5; num++; break;
2715 case 22: Rate = RATE_11; num++; break;
2716 case 12: Rate = RATE_6; num++; break;
2717 case 18: Rate = RATE_9; num++; break;
2718 case 24: Rate = RATE_12; num++; break;
2719 case 36: Rate = RATE_18; num++; break;
2720 case 48: Rate = RATE_24; num++; break;
2721 case 72: Rate = RATE_36; num++; break;
2722 case 96: Rate = RATE_48; num++; break;
2723 case 108: Rate = RATE_54; num++; break;
2724 //default: Rate = RATE_1; break;
2726 if (MaxDesire < Rate) MaxDesire = Rate;
2729 //===========================================================================
2730 //===========================================================================
2732 pHtPhy = &pAd->StaCfg.HTPhyMode;
2733 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2734 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2736 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2737 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2739 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2740 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2741 (MaxDesire > RATE_11))
2743 MaxDesire = RATE_11;
2747 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2748 pMinHtPhy->word = 0;
2749 pMaxHtPhy->word = 0;
2752 // Auto rate switching is enabled only if more than one DESIRED RATES are
2753 // specified; otherwise disabled
2756 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2757 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2758 *auto_rate_cur_p = FALSE;
2762 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2763 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2764 *auto_rate_cur_p = TRUE;
2768 if (HtMcs != MCS_AUTO)
2770 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2771 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2772 *auto_rate_cur_p = FALSE;
2776 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2777 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2778 *auto_rate_cur_p = TRUE;
2782 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2784 pSupRate = &pAd->StaActive.SupRate[0];
2785 pExtRate = &pAd->StaActive.ExtRate[0];
2786 SupRateLen = pAd->StaActive.SupRateLen;
2787 ExtRateLen = pAd->StaActive.ExtRateLen;
2791 pSupRate = &pAd->CommonCfg.SupRate[0];
2792 pExtRate = &pAd->CommonCfg.ExtRate[0];
2793 SupRateLen = pAd->CommonCfg.SupRateLen;
2794 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2797 // find max supported rate
2798 for (i=0; i<SupRateLen; i++)
2800 switch (pSupRate[i] & 0x7f)
2802 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2803 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2804 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2805 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2806 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2807 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2808 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2809 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2810 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2811 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2812 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2813 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2814 default: Rate = RATE_1; break;
2816 if (MaxSupport < Rate) MaxSupport = Rate;
2818 if (MinSupport > Rate) MinSupport = Rate;
2821 for (i=0; i<ExtRateLen; i++)
2823 switch (pExtRate[i] & 0x7f)
2825 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2826 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2827 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2828 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2829 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2830 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2831 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2832 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2833 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2834 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2835 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2836 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2837 default: Rate = RATE_1; break;
2839 if (MaxSupport < Rate) MaxSupport = Rate;
2841 if (MinSupport > Rate) MinSupport = Rate;
2844 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2846 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2847 // the DURATION field of outgoing uniicast DATA/MGMT frame
2848 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2850 if (BasicRateBitmap & (0x01 << i))
2851 CurrBasicRate = (UCHAR)i;
2852 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2855 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2856 // max tx rate = min {max desire rate, max supported rate}
2857 if (MaxSupport < MaxDesire)
2858 pAd->CommonCfg.MaxTxRate = MaxSupport;
2860 pAd->CommonCfg.MaxTxRate = MaxDesire;
2862 pAd->CommonCfg.MinTxRate = MinSupport;
2863 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
2864 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
2866 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
2867 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
2868 // 3. -75 > RSSI, start at 11 Mbps (long distance)
2869 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
2870 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
2871 if (*auto_rate_cur_p)
2875 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2877 if (bLinkUp == TRUE)
2878 pAd->CommonCfg.TxRate = RATE_24;
2880 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2883 pAd->CommonCfg.TxRate = RATE_11;
2885 pAd->CommonCfg.TxRate = RATE_24;
2887 // should never exceed MaxTxRate (consider 11B-only mode)
2888 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2889 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2891 pAd->CommonCfg.TxRateIndex = 0;
2895 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2896 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2897 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2899 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2900 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2901 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2902 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
2905 if (pAd->CommonCfg.TxRate <= RATE_11)
2907 pMaxHtPhy->field.MODE = MODE_CCK;
2908 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
2909 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
2913 pMaxHtPhy->field.MODE = MODE_OFDM;
2914 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
2915 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
2916 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
2918 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
2921 pHtPhy->word = (pMaxHtPhy->word);
2922 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
2924 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
2925 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
2926 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
2930 switch (pAd->CommonCfg.PhyMode)
2932 case PHY_11BG_MIXED:
2934 case PHY_11BGN_MIXED:
2935 pAd->CommonCfg.MlmeRate = RATE_1;
2936 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2937 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2940 pAd->CommonCfg.RtsRate = RATE_11;
2942 // pAd->CommonCfg.RtsRate = RATE_1;
2947 case PHY_11AGN_MIXED:
2948 case PHY_11GN_MIXED:
2950 case PHY_11AN_MIXED:
2952 pAd->CommonCfg.MlmeRate = RATE_6;
2953 pAd->CommonCfg.RtsRate = RATE_6;
2954 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2955 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2957 case PHY_11ABG_MIXED:
2958 case PHY_11ABGN_MIXED:
2959 if (pAd->CommonCfg.Channel <= 14)
2961 pAd->CommonCfg.MlmeRate = RATE_1;
2962 pAd->CommonCfg.RtsRate = RATE_1;
2963 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2964 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2968 pAd->CommonCfg.MlmeRate = RATE_6;
2969 pAd->CommonCfg.RtsRate = RATE_6;
2970 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2971 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2975 pAd->CommonCfg.MlmeRate = RATE_6;
2976 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2977 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2978 pAd->CommonCfg.RtsRate = RATE_1;
2982 // Keep Basic Mlme Rate.
2984 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
2985 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
2986 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
2988 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
2989 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
2992 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
2993 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
2994 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
2995 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
2996 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
2997 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
2998 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 ));
3002 ==========================================================================
3004 This function update HT Rate setting.
3005 Input Wcid value is valid for 2 case :
3006 1. it's used for Station in infra mode that copy AP rate to Mactable.
3007 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3009 IRQL = DISPATCH_LEVEL
3011 ==========================================================================
3013 VOID MlmeUpdateHtTxRates(
3014 IN PRTMP_ADAPTER pAd,
3017 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3019 RT_HT_CAPABILITY *pRtHtCap = NULL;
3020 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3023 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3024 PHTTRANSMIT_SETTING pHtPhy = NULL;
3025 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3026 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3027 BOOLEAN *auto_rate_cur_p;
3029 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3031 auto_rate_cur_p = NULL;
3034 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3035 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3036 pHtPhy = &pAd->StaCfg.HTPhyMode;
3037 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3038 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3040 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3043 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3045 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3048 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3049 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3050 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3051 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3052 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3053 pMaxHtPhy->field.STBC = STBC_USE;
3055 pMaxHtPhy->field.STBC = STBC_NONE;
3059 if (pDesireHtPhy->bHtEnable == FALSE)
3062 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3063 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3064 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3065 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3066 pMaxHtPhy->field.STBC = STBC_USE;
3068 pMaxHtPhy->field.STBC = STBC_NONE;
3071 // Decide MAX ht rate.
3072 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3073 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3075 pMaxHtPhy->field.MODE = MODE_HTMIX;
3077 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3078 pMaxHtPhy->field.BW = BW_40;
3080 pMaxHtPhy->field.BW = BW_20;
3082 if (pMaxHtPhy->field.BW == BW_20)
3083 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3085 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3087 for (i=23; i>=0; i--) // 3*3
3090 bitmask = (1<<(i-(j*8)));
3092 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3094 pMaxHtPhy->field.MCS = i;
3102 // Copy MIN ht rate. rt2860???
3103 pMinHtPhy->field.BW = BW_20;
3104 pMinHtPhy->field.MCS = 0;
3105 pMinHtPhy->field.STBC = 0;
3106 pMinHtPhy->field.ShortGI = 0;
3107 //If STA assigns fixed rate. update to fixed here.
3108 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3110 if (pDesireHtPhy->MCSSet[4] != 0)
3112 pMaxHtPhy->field.MCS = 32;
3113 pMinHtPhy->field.MCS = 32;
3114 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3117 for (i=23; (CHAR)i >= 0; i--) // 3*3
3120 bitmask = (1<<(i-(j*8)));
3121 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3123 pMaxHtPhy->field.MCS = i;
3124 pMinHtPhy->field.MCS = i;
3133 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3134 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3135 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3136 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3137 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3139 // use default now. rt2860
3140 if (pDesireHtPhy->MCSSet[0] != 0xff)
3141 *auto_rate_cur_p = FALSE;
3143 *auto_rate_cur_p = TRUE;
3145 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3146 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3147 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3148 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3151 // IRQL = DISPATCH_LEVEL
3153 IN PRTMP_ADAPTER pAd)
3155 RT28XX_MLME_RADIO_OFF(pAd);
3158 // IRQL = DISPATCH_LEVEL
3160 IN PRTMP_ADAPTER pAd)
3162 RT28XX_MLME_RADIO_ON(pAd);
3165 // ===========================================================================================
3167 // ===========================================================================================
3170 /*! \brief initialize BSS table
3171 * \param p_tab pointer to the table
3176 IRQL = PASSIVE_LEVEL
3177 IRQL = DISPATCH_LEVEL
3186 Tab->BssOverlapNr = 0;
3187 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3189 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3190 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3195 IN PRTMP_ADAPTER pAd,
3200 Tab->numAsOriginator = 0;
3201 Tab->numAsRecipient = 0;
3202 NdisAllocateSpinLock(&pAd->BATabLock);
3203 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3205 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3206 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3208 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3210 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3214 /*! \brief search the BSS table by SSID
3215 * \param p_tab pointer to the bss table
3216 * \param ssid SSID string
3217 * \return index of the table, BSS_NOT_FOUND if not in the table
3220 * \note search by sequential search
3222 IRQL = DISPATCH_LEVEL
3225 ULONG BssTableSearch(
3232 for (i = 0; i < Tab->BssNr; i++)
3235 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3236 // We should distinguish this case.
3238 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3239 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3240 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3245 return (ULONG)BSS_NOT_FOUND;
3248 ULONG BssSsidTableSearch(
3257 for (i = 0; i < Tab->BssNr; i++)
3260 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3261 // We should distinguish this case.
3263 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3264 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3265 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3266 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3271 return (ULONG)BSS_NOT_FOUND;
3274 ULONG BssTableSearchWithSSID(
3283 for (i = 0; i < Tab->BssNr; i++)
3285 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3286 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3287 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3288 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3289 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3290 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3295 return (ULONG)BSS_NOT_FOUND;
3298 // IRQL = DISPATCH_LEVEL
3299 VOID BssTableDeleteEntry(
3300 IN OUT BSS_TABLE *Tab,
3306 for (i = 0; i < Tab->BssNr; i++)
3308 if ((Tab->BssEntry[i].Channel == Channel) &&
3309 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3311 for (j = i; j < Tab->BssNr - 1; j++)
3313 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3315 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3323 ========================================================================
3324 Routine Description:
3325 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3328 // IRQL = DISPATCH_LEVEL
3329 ========================================================================
3331 VOID BATableDeleteORIEntry(
3332 IN OUT PRTMP_ADAPTER pAd,
3333 IN BA_ORI_ENTRY *pBAORIEntry)
3336 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3338 NdisAcquireSpinLock(&pAd->BATabLock);
3339 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3341 pAd->BATable.numAsOriginator -= 1;
3342 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3343 // Erase Bitmap flag.
3345 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3346 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3347 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3348 pBAORIEntry->Token = 1;
3349 // Not clear Sequence here.
3350 NdisReleaseSpinLock(&pAd->BATabLock);
3360 IRQL = DISPATCH_LEVEL
3364 IN PRTMP_ADAPTER pAd,
3365 OUT BSS_ENTRY *pBss,
3370 IN USHORT BeaconPeriod,
3371 IN PCF_PARM pCfParm,
3373 IN USHORT CapabilityInfo,
3375 IN UCHAR SupRateLen,
3377 IN UCHAR ExtRateLen,
3378 IN HT_CAPABILITY_IE *pHtCapability,
3379 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3380 IN UCHAR HtCapabilityLen,
3381 IN UCHAR AddHtInfoLen,
3382 IN UCHAR NewExtChanOffset,
3385 IN LARGE_INTEGER TimeStamp,
3387 IN PEDCA_PARM pEdcaParm,
3388 IN PQOS_CAPABILITY_PARM pQosCapability,
3389 IN PQBSS_LOAD_PARM pQbssLoad,
3390 IN USHORT LengthVIE,
3391 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3393 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3394 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3398 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3399 // Or send beacon /probe response with SSID len matching real SSID length,
3400 // but SSID is all zero. such as "00-00-00-00" with length 4.
3401 // We have to prevent this case overwrite correct table
3402 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3404 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3405 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3406 pBss->SsidLen = SsidLen;
3412 pBss->BssType = BssType;
3413 pBss->BeaconPeriod = BeaconPeriod;
3414 if (BssType == BSS_INFRA)
3416 if (pCfParm->bValid)
3418 pBss->CfpCount = pCfParm->CfpCount;
3419 pBss->CfpPeriod = pCfParm->CfpPeriod;
3420 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3421 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3426 pBss->AtimWin = AtimWin;
3429 pBss->CapabilityInfo = CapabilityInfo;
3430 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3431 // Combine with AuthMode, they will decide the connection methods.
3432 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3433 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3434 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3435 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3437 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3438 pBss->SupRateLen = SupRateLen;
3439 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3440 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3441 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3442 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3443 pBss->NewExtChanOffset = NewExtChanOffset;
3444 pBss->ExtRateLen = ExtRateLen;
3445 pBss->Channel = Channel;
3446 pBss->CentralChannel = Channel;
3448 // Update CkipFlag. if not exists, the value is 0x0
3449 pBss->CkipFlag = CkipFlag;
3451 // New for microsoft Fixed IEs
3452 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3453 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3454 pBss->FixIEs.Capabilities = CapabilityInfo;
3456 // New for microsoft Variable IEs
3459 pBss->VarIELen = LengthVIE;
3460 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3467 pBss->AddHtInfoLen = 0;
3468 pBss->HtCapabilityLen = 0;
3470 if (HtCapabilityLen> 0)
3472 pBss->HtCapabilityLen = HtCapabilityLen;
3473 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3474 if (AddHtInfoLen > 0)
3476 pBss->AddHtInfoLen = AddHtInfoLen;
3477 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3479 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3481 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3483 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3485 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3490 BssCipherParse(pBss);
3494 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3496 pBss->EdcaParm.bValid = FALSE;
3498 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3500 pBss->QosCapability.bValid = FALSE;
3502 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3504 pBss->QbssLoad.bValid = FALSE;
3511 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3512 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3514 pEid = (PEID_STRUCT) pVIE;
3516 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3521 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3523 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3525 pBss->WpaIE.IELen = 0;
3528 pBss->WpaIE.IELen = pEid->Len + 2;
3529 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3533 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3535 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3537 pBss->RsnIE.IELen = 0;
3540 pBss->RsnIE.IELen = pEid->Len + 2;
3541 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3545 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3546 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3552 * \brief insert an entry into the bss table
3553 * \param p_tab The BSS table
3554 * \param Bssid BSSID
3556 * \param ssid_len Length of SSID
3558 * \param beacon_period
3565 * \param channel_idx
3569 * \note If SSID is identical, the old entry will be replaced by the new one
3571 IRQL = DISPATCH_LEVEL
3574 ULONG BssTableSetEntry(
3575 IN PRTMP_ADAPTER pAd,
3581 IN USHORT BeaconPeriod,
3584 IN USHORT CapabilityInfo,
3586 IN UCHAR SupRateLen,
3588 IN UCHAR ExtRateLen,
3589 IN HT_CAPABILITY_IE *pHtCapability,
3590 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3591 IN UCHAR HtCapabilityLen,
3592 IN UCHAR AddHtInfoLen,
3593 IN UCHAR NewExtChanOffset,
3596 IN LARGE_INTEGER TimeStamp,
3598 IN PEDCA_PARM pEdcaParm,
3599 IN PQOS_CAPABILITY_PARM pQosCapability,
3600 IN PQBSS_LOAD_PARM pQbssLoad,
3601 IN USHORT LengthVIE,
3602 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3606 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3607 if (Idx == BSS_NOT_FOUND)
3609 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3612 // It may happen when BSS Table was full.
3613 // The desired AP will not be added into BSS Table
3614 // In this case, if we found the desired AP then overwrite BSS Table.
3616 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3618 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3619 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3621 Idx = Tab->BssOverlapNr;
3622 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3623 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3624 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3625 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3631 return BSS_NOT_FOUND;
3635 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3636 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3637 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3642 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3643 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3644 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3646 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3647 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3648 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3655 // IRQL = DISPATCH_LEVEL
3656 VOID BssTableSsidSort(
3657 IN PRTMP_ADAPTER pAd,
3658 OUT BSS_TABLE *OutTab,
3663 BssTableInit(OutTab);
3665 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3667 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3668 BOOLEAN bIsHiddenApIncluded = FALSE;
3670 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3671 (pAd->MlmeAux.Channel > 14) &&
3672 RadarChannelCheck(pAd, pInBss->Channel))
3676 bIsHiddenApIncluded = TRUE;
3679 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3680 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3682 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3684 // 2.4G/5G N only mode
3685 if ((pInBss->HtCapabilityLen == 0) &&
3686 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3688 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3693 // Check the Authmode first
3694 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3696 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3697 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3701 // Check cipher suite, AP must have more secured cipher than station setting
3702 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3704 // If it's not mixed mode, we should only let BSS pass with the same encryption
3705 if (pInBss->WPA.bMixMode == FALSE)
3706 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3709 // check group cipher
3710 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3713 // check pairwise cipher, skip if none matched
3714 // If profile set to AES, let it pass without question.
3715 // If profile set to TKIP, we must find one mateched
3716 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3717 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3718 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3721 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3723 // If it's not mixed mode, we should only let BSS pass with the same encryption
3724 if (pInBss->WPA2.bMixMode == FALSE)
3725 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3728 // check group cipher
3729 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3732 // check pairwise cipher, skip if none matched
3733 // If profile set to AES, let it pass without question.
3734 // If profile set to TKIP, we must find one mateched
3735 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3736 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3737 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3741 // Bss Type matched, SSID matched.
3742 // We will check wepstatus for qualification Bss
3743 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3745 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3747 // For the SESv2 case, we will not qualify WepStatus.
3753 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3754 // It definitely will fail. So, skip it.
3755 // CCX also require not even try to connect it!!
3759 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3760 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3761 if ((pInBss->CentralChannel != pInBss->Channel) &&
3762 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3764 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3766 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3768 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3772 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3779 // copy matching BSS from InTab to OutTab
3780 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3784 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3786 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3788 // 2.4G/5G N only mode
3789 if ((pInBss->HtCapabilityLen == 0) &&
3790 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3792 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3797 // Check the Authmode first
3798 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3800 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3801 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3805 // Check cipher suite, AP must have more secured cipher than station setting
3806 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3808 // If it's not mixed mode, we should only let BSS pass with the same encryption
3809 if (pInBss->WPA.bMixMode == FALSE)
3810 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3813 // check group cipher
3814 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3817 // check pairwise cipher, skip if none matched
3818 // If profile set to AES, let it pass without question.
3819 // If profile set to TKIP, we must find one mateched
3820 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3821 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3822 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3825 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3827 // If it's not mixed mode, we should only let BSS pass with the same encryption
3828 if (pInBss->WPA2.bMixMode == FALSE)
3829 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3832 // check group cipher
3833 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3836 // check pairwise cipher, skip if none matched
3837 // If profile set to AES, let it pass without question.
3838 // If profile set to TKIP, we must find one mateched
3839 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3840 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3841 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3845 // Bss Type matched, SSID matched.
3846 // We will check wepstatus for qualification Bss
3847 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3850 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3851 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3852 if ((pInBss->CentralChannel != pInBss->Channel) &&
3853 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3855 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3857 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3859 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3863 // copy matching BSS from InTab to OutTab
3864 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3869 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3873 BssTableSortByRssi(OutTab);
3877 // IRQL = DISPATCH_LEVEL
3878 VOID BssTableSortByRssi(
3879 IN OUT BSS_TABLE *OutTab)
3884 for (i = 0; i < OutTab->BssNr - 1; i++)
3886 for (j = i+1; j < OutTab->BssNr; j++)
3888 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
3890 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
3891 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
3892 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
3898 VOID BssCipherParse(
3899 IN OUT PBSS_ENTRY pBss)
3903 PRSN_IE_HEADER_STRUCT pRsnHeader;
3904 PCIPHER_SUITE_STRUCT pCipher;
3905 PAKM_SUITE_STRUCT pAKM;
3908 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
3911 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
3915 pBss->WepStatus = Ndis802_11WEPEnabled;
3919 pBss->WepStatus = Ndis802_11WEPDisabled;
3921 // Set default to disable & open authentication before parsing variable IE
3922 pBss->AuthMode = Ndis802_11AuthModeOpen;
3923 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
3926 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
3927 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
3928 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
3929 pBss->WPA.RsnCapability = 0;
3930 pBss->WPA.bMixMode = FALSE;
3932 // Init WPA2 setting
3933 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
3934 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
3935 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
3936 pBss->WPA2.RsnCapability = 0;
3937 pBss->WPA2.bMixMode = FALSE;
3940 Length = (INT) pBss->VarIELen;
3944 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
3945 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
3946 pEid = (PEID_STRUCT) pTmp;
3950 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
3951 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
3957 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3958 pBss->WepStatus = Ndis802_11Encryption1Enabled;
3959 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3960 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3963 pBss->WepStatus = Ndis802_11Encryption2Enabled;
3964 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3965 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3968 pBss->WepStatus = Ndis802_11Encryption3Enabled;
3969 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3970 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3976 // if Cisco IE_WPA, break
3979 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
3984 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
3986 // if unsupported vendor specific IE
3989 // Skip OUI, version, and multicast suite
3990 // This part should be improved in the future when AP supported multiple cipher suite.
3991 // For now, it's OK since almost all APs have fixed cipher suite supported.
3992 // pTmp = (PUCHAR) pEid->Octet;
3995 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4003 // Parse group cipher
4007 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4008 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4011 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4014 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4019 // number of unicast suite
4022 // skip all unicast cipher suites
4023 //Count = *(PUSHORT) pTmp;
4024 Count = (pTmp[1]<<8) + pTmp[0];
4025 pTmp += sizeof(USHORT);
4027 // Parsing all unicast cipher suite
4032 TmpCipher = Ndis802_11WEPDisabled;
4036 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4037 TmpCipher = Ndis802_11Encryption1Enabled;
4040 TmpCipher = Ndis802_11Encryption2Enabled;
4043 TmpCipher = Ndis802_11Encryption3Enabled;
4048 if (TmpCipher > pBss->WPA.PairCipher)
4050 // Move the lower cipher suite to PairCipherAux
4051 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4052 pBss->WPA.PairCipher = TmpCipher;
4056 pBss->WPA.PairCipherAux = TmpCipher;
4062 // 4. get AKM suite counts
4063 //Count = *(PUSHORT) pTmp;
4064 Count = (pTmp[1]<<8) + pTmp[0];
4065 pTmp += sizeof(USHORT);
4071 // Set AP support WPA mode
4072 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4073 pBss->AuthMode = Ndis802_11AuthModeWPA;
4075 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4078 // Set AP support WPA mode
4079 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4080 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4082 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4089 // Fixed for WPA-None
4090 if (pBss->BssType == BSS_ADHOC)
4092 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4093 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4094 pBss->WepStatus = pBss->WPA.GroupCipher;
4095 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4096 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4099 pBss->WepStatus = pBss->WPA.PairCipher;
4101 // Check the Pair & Group, if different, turn on mixed mode flag
4102 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4103 pBss->WPA.bMixMode = TRUE;
4108 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4110 // 0. Version must be 1
4111 if (le2cpu16(pRsnHeader->Version) != 1)
4113 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4115 // 1. Check group cipher
4116 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4117 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4120 // Parse group cipher
4121 switch (pCipher->Type)
4124 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4125 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4128 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4131 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4136 // set to correct offset for next parsing
4137 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4139 // 2. Get pairwise cipher counts
4140 //Count = *(PUSHORT) pTmp;
4141 Count = (pTmp[1]<<8) + pTmp[0];
4142 pTmp += sizeof(USHORT);
4144 // 3. Get pairwise cipher
4145 // Parsing all unicast cipher suite
4149 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4150 TmpCipher = Ndis802_11WEPDisabled;
4151 switch (pCipher->Type)
4154 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4155 TmpCipher = Ndis802_11Encryption1Enabled;
4158 TmpCipher = Ndis802_11Encryption2Enabled;
4161 TmpCipher = Ndis802_11Encryption3Enabled;
4166 if (TmpCipher > pBss->WPA2.PairCipher)
4168 // Move the lower cipher suite to PairCipherAux
4169 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4170 pBss->WPA2.PairCipher = TmpCipher;
4174 pBss->WPA2.PairCipherAux = TmpCipher;
4176 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4180 // 4. get AKM suite counts
4181 //Count = *(PUSHORT) pTmp;
4182 Count = (pTmp[1]<<8) + pTmp[0];
4183 pTmp += sizeof(USHORT);
4185 // 5. Get AKM ciphers
4186 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4187 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4193 // Set AP support WPA mode
4194 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4195 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4197 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4200 // Set AP support WPA mode
4201 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4202 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4204 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4209 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4211 // Fixed for WPA-None
4212 if (pBss->BssType == BSS_ADHOC)
4214 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4215 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4216 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4217 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4218 pBss->WepStatus = pBss->WPA.GroupCipher;
4219 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4220 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4222 pBss->WepStatus = pBss->WPA2.PairCipher;
4224 // 6. Get RSN capability
4225 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4226 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4227 pTmp += sizeof(USHORT);
4229 // Check the Pair & Group, if different, turn on mixed mode flag
4230 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4231 pBss->WPA2.bMixMode = TRUE;
4237 Length -= (pEid->Len + 2);
4241 // ===========================================================================================
4243 // ===========================================================================================
4245 /*! \brief generates a random mac address value for IBSS BSSID
4246 * \param Addr the bssid location
4251 VOID MacAddrRandomBssid(
4252 IN PRTMP_ADAPTER pAd,
4257 for (i = 0; i < MAC_ADDR_LEN; i++)
4259 pAddr[i] = RandomByte(pAd);
4262 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4265 /*! \brief init the management mac frame header
4266 * \param p_hdr mac header
4267 * \param subtype subtype of the frame
4268 * \param p_ds destination address, don't care if it is a broadcast address
4270 * \pre the station has the following information in the pAd->StaCfg
4274 * \note this function initializes the following field
4276 IRQL = PASSIVE_LEVEL
4277 IRQL = DISPATCH_LEVEL
4280 VOID MgtMacHeaderInit(
4281 IN PRTMP_ADAPTER pAd,
4282 IN OUT PHEADER_802_11 pHdr80211,
4288 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4290 pHdr80211->FC.Type = BTYPE_MGMT;
4291 pHdr80211->FC.SubType = SubType;
4292 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4293 // pHdr80211->FC.Type = BTYPE_CNTL;
4294 pHdr80211->FC.ToDs = ToDs;
4295 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4297 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4299 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4302 // ===========================================================================================
4304 // ===========================================================================================
4306 /*!***************************************************************************
4307 * This routine build an outgoing frame, and fill all information specified
4308 * in argument list to the frame body. The actual frame size is the summation
4311 * Buffer - pointer to a pre-allocated memory segment
4312 * args - a list of <int arg_size, arg> pairs.
4313 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4314 * function will FAIL!!!
4316 * Size of the buffer
4318 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4320 IRQL = PASSIVE_LEVEL
4321 IRQL = DISPATCH_LEVEL
4323 ****************************************************************************/
4324 ULONG MakeOutgoingFrame(
4326 OUT ULONG *FrameLen, ...)
4333 // calculates the total length
4335 va_start(Args, FrameLen);
4338 leng = va_arg(Args, int);
4339 if (leng == END_OF_ARGS)
4343 p = va_arg(Args, PVOID);
4344 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4345 TotLeng = TotLeng + leng;
4348 va_end(Args); /* clean up */
4349 *FrameLen = TotLeng;
4353 // ===========================================================================================
4355 // ===========================================================================================
4357 /*! \brief Initialize The MLME Queue, used by MLME Functions
4358 * \param *Queue The MLME Queue
4359 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4362 * \note Because this is done only once (at the init stage), no need to be locked
4364 IRQL = PASSIVE_LEVEL
4367 NDIS_STATUS MlmeQueueInit(
4368 IN MLME_QUEUE *Queue)
4372 NdisAllocateSpinLock(&Queue->Lock);
4378 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4380 Queue->Entry[i].Occupied = FALSE;
4381 Queue->Entry[i].MsgLen = 0;
4382 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4385 return NDIS_STATUS_SUCCESS;
4388 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4389 * \param *Queue The MLME Queue
4390 * \param Machine The State Machine Id
4391 * \param MsgType The Message Type
4392 * \param MsgLen The Message length
4393 * \param *Msg The message pointer
4394 * \return TRUE if enqueue is successful, FALSE if the queue is full
4397 * \note The message has to be initialized
4399 IRQL = PASSIVE_LEVEL
4400 IRQL = DISPATCH_LEVEL
4403 BOOLEAN MlmeEnqueue(
4404 IN PRTMP_ADAPTER pAd,
4411 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4413 // Do nothing if the driver is starting halt state.
4414 // This might happen when timer already been fired before cancel timer with mlmehalt
4415 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4418 // First check the size, it MUST not exceed the mlme queue size
4419 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4421 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4425 if (MlmeQueueFull(Queue))
4430 NdisAcquireSpinLock(&(Queue->Lock));
4434 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4439 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4440 Queue->Entry[Tail].Occupied = TRUE;
4441 Queue->Entry[Tail].Machine = Machine;
4442 Queue->Entry[Tail].MsgType = MsgType;
4443 Queue->Entry[Tail].MsgLen = MsgLen;
4447 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4450 NdisReleaseSpinLock(&(Queue->Lock));
4454 /*! \brief This function is used when Recv gets a MLME message
4455 * \param *Queue The MLME Queue
4456 * \param TimeStampHigh The upper 32 bit of timestamp
4457 * \param TimeStampLow The lower 32 bit of timestamp
4458 * \param Rssi The receiving RSSI strength
4459 * \param MsgLen The length of the message
4460 * \param *Msg The message pointer
4461 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4465 IRQL = DISPATCH_LEVEL
4468 BOOLEAN MlmeEnqueueForRecv(
4469 IN PRTMP_ADAPTER pAd,
4471 IN ULONG TimeStampHigh,
4472 IN ULONG TimeStampLow,
4481 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4483 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4485 // Do nothing if the driver is starting halt state.
4486 // This might happen when timer already been fired before cancel timer with mlmehalt
4487 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4489 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4493 // First check the size, it MUST not exceed the mlme queue size
4494 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4496 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4500 if (MlmeQueueFull(Queue))
4506 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4508 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4513 // OK, we got all the informations, it is time to put things into queue
4514 NdisAcquireSpinLock(&(Queue->Lock));
4518 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4522 Queue->Entry[Tail].Occupied = TRUE;
4523 Queue->Entry[Tail].Machine = Machine;
4524 Queue->Entry[Tail].MsgType = MsgType;
4525 Queue->Entry[Tail].MsgLen = MsgLen;
4526 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4527 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4528 Queue->Entry[Tail].Rssi0 = Rssi0;
4529 Queue->Entry[Tail].Rssi1 = Rssi1;
4530 Queue->Entry[Tail].Rssi2 = Rssi2;
4531 Queue->Entry[Tail].Signal = Signal;
4532 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4534 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4538 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4541 NdisReleaseSpinLock(&(Queue->Lock));
4543 RT28XX_MLME_HANDLER(pAd);
4549 /*! \brief Dequeue a message from the MLME Queue
4550 * \param *Queue The MLME Queue
4551 * \param *Elem The message dequeued from MLME Queue
4552 * \return TRUE if the Elem contains something, FALSE otherwise
4556 IRQL = DISPATCH_LEVEL
4559 BOOLEAN MlmeDequeue(
4560 IN MLME_QUEUE *Queue,
4561 OUT MLME_QUEUE_ELEM **Elem)
4563 NdisAcquireSpinLock(&(Queue->Lock));
4564 *Elem = &(Queue->Entry[Queue->Head]);
4567 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4571 NdisReleaseSpinLock(&(Queue->Lock));
4575 // IRQL = DISPATCH_LEVEL
4576 VOID MlmeRestartStateMachine(
4577 IN PRTMP_ADAPTER pAd)
4581 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4584 // Cancel all timer events
4585 // Be careful to cancel new added timer
4586 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4587 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4588 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4589 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4590 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4591 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4594 // Change back to original channel in case of doing scan
4595 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4596 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4598 // Resume MSDU which is turned off durning scan
4599 RTMPResumeMsduTransmission(pAd);
4602 // Set all state machines back IDLE
4603 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4604 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4605 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4606 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4607 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4608 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4612 /*! \brief test if the MLME Queue is empty
4613 * \param *Queue The MLME Queue
4614 * \return TRUE if the Queue is empty, FALSE otherwise
4618 IRQL = DISPATCH_LEVEL
4621 BOOLEAN MlmeQueueEmpty(
4622 IN MLME_QUEUE *Queue)
4626 NdisAcquireSpinLock(&(Queue->Lock));
4627 Ans = (Queue->Num == 0);
4628 NdisReleaseSpinLock(&(Queue->Lock));
4633 /*! \brief test if the MLME Queue is full
4634 * \param *Queue The MLME Queue
4635 * \return TRUE if the Queue is empty, FALSE otherwise
4639 IRQL = PASSIVE_LEVEL
4640 IRQL = DISPATCH_LEVEL
4643 BOOLEAN MlmeQueueFull(
4644 IN MLME_QUEUE *Queue)
4648 NdisAcquireSpinLock(&(Queue->Lock));
4649 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4650 NdisReleaseSpinLock(&(Queue->Lock));
4655 /*! \brief The destructor of MLME Queue
4660 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4662 IRQL = PASSIVE_LEVEL
4665 VOID MlmeQueueDestroy(
4666 IN MLME_QUEUE *pQueue)
4668 NdisAcquireSpinLock(&(pQueue->Lock));
4672 NdisReleaseSpinLock(&(pQueue->Lock));
4673 NdisFreeSpinLock(&(pQueue->Lock));
4676 /*! \brief To substitute the message type if the message is coming from external
4677 * \param pFrame The frame received
4678 * \param *Machine The state machine
4679 * \param *MsgType the message type for the state machine
4680 * \return TRUE if the substitution is successful, FALSE otherwise
4684 IRQL = DISPATCH_LEVEL
4687 BOOLEAN MsgTypeSubst(
4688 IN PRTMP_ADAPTER pAd,
4689 IN PFRAME_802_11 pFrame,
4697 // Pointer to start of data frames including SNAP header
4698 pData = (PUCHAR) pFrame + LENGTH_802_11;
4700 // The only data type will pass to this function is EAPOL frame
4701 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4703 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4705 // Cisco Aironet SNAP header
4706 *Machine = AIRONET_STATE_MACHINE;
4707 *MsgType = MT2_AIRONET_MSG;
4711 *Machine = WPA_PSK_STATE_MACHINE;
4712 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4713 return(WpaMsgTypeSubst(EAPType, MsgType));
4717 switch (pFrame->Hdr.FC.SubType)
4719 case SUBTYPE_ASSOC_REQ:
4720 *Machine = ASSOC_STATE_MACHINE;
4721 *MsgType = MT2_PEER_ASSOC_REQ;
4723 case SUBTYPE_ASSOC_RSP:
4724 *Machine = ASSOC_STATE_MACHINE;
4725 *MsgType = MT2_PEER_ASSOC_RSP;
4727 case SUBTYPE_REASSOC_REQ:
4728 *Machine = ASSOC_STATE_MACHINE;
4729 *MsgType = MT2_PEER_REASSOC_REQ;
4731 case SUBTYPE_REASSOC_RSP:
4732 *Machine = ASSOC_STATE_MACHINE;
4733 *MsgType = MT2_PEER_REASSOC_RSP;
4735 case SUBTYPE_PROBE_REQ:
4736 *Machine = SYNC_STATE_MACHINE;
4737 *MsgType = MT2_PEER_PROBE_REQ;
4739 case SUBTYPE_PROBE_RSP:
4740 *Machine = SYNC_STATE_MACHINE;
4741 *MsgType = MT2_PEER_PROBE_RSP;
4743 case SUBTYPE_BEACON:
4744 *Machine = SYNC_STATE_MACHINE;
4745 *MsgType = MT2_PEER_BEACON;
4748 *Machine = SYNC_STATE_MACHINE;
4749 *MsgType = MT2_PEER_ATIM;
4751 case SUBTYPE_DISASSOC:
4752 *Machine = ASSOC_STATE_MACHINE;
4753 *MsgType = MT2_PEER_DISASSOC_REQ;
4756 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4757 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4758 if (Seq == 1 || Seq == 3)
4760 *Machine = AUTH_RSP_STATE_MACHINE;
4761 *MsgType = MT2_PEER_AUTH_ODD;
4763 else if (Seq == 2 || Seq == 4)
4765 *Machine = AUTH_STATE_MACHINE;
4766 *MsgType = MT2_PEER_AUTH_EVEN;
4773 case SUBTYPE_DEAUTH:
4774 *Machine = AUTH_RSP_STATE_MACHINE;
4775 *MsgType = MT2_PEER_DEAUTH;
4777 case SUBTYPE_ACTION:
4778 *Machine = ACTION_STATE_MACHINE;
4779 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4780 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4782 *MsgType = MT2_ACT_INVALID;
4786 *MsgType = (pFrame->Octet[0]&0x7F);
4797 // ===========================================================================================
4799 // ===========================================================================================
4801 /*! \brief Initialize the state machine.
4802 * \param *S pointer to the state machine
4803 * \param Trans State machine transition function
4804 * \param StNr number of states
4805 * \param MsgNr number of messages
4806 * \param DefFunc default function, when there is invalid state/message combination
4807 * \param InitState initial state of the state machine
4808 * \param Base StateMachine base, internal use only
4809 * \pre p_sm should be a legal pointer
4812 IRQL = PASSIVE_LEVEL
4815 VOID StateMachineInit(
4816 IN STATE_MACHINE *S,
4817 IN STATE_MACHINE_FUNC Trans[],
4820 IN STATE_MACHINE_FUNC DefFunc,
4826 // set number of states and messages
4831 S->TransFunc = Trans;
4833 // init all state transition to default function
4834 for (i = 0; i < StNr; i++)
4836 for (j = 0; j < MsgNr; j++)
4838 S->TransFunc[i * MsgNr + j] = DefFunc;
4842 // set the starting state
4843 S->CurrState = InitState;
4846 /*! \brief This function fills in the function pointer into the cell in the state machine
4847 * \param *S pointer to the state machine
4849 * \param Msg incoming message
4850 * \param f the function to be executed when (state, message) combination occurs at the state machine
4851 * \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
4854 IRQL = PASSIVE_LEVEL
4857 VOID StateMachineSetAction(
4858 IN STATE_MACHINE *S,
4861 IN STATE_MACHINE_FUNC Func)
4865 MsgIdx = Msg - S->Base;
4867 if (St < S->NrState && MsgIdx < S->NrMsg)
4869 // boundary checking before setting the action
4870 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
4874 /*! \brief This function does the state transition
4875 * \param *Adapter the NIC adapter pointer
4876 * \param *S the state machine
4877 * \param *Elem the message to be executed
4880 IRQL = DISPATCH_LEVEL
4883 VOID StateMachinePerformAction(
4884 IN PRTMP_ADAPTER pAd,
4885 IN STATE_MACHINE *S,
4886 IN MLME_QUEUE_ELEM *Elem)
4888 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
4892 ==========================================================================
4894 The drop function, when machine executes this, the message is simply
4895 ignored. This function does nothing, the message is freed in
4896 StateMachinePerformAction()
4897 ==========================================================================
4900 IN PRTMP_ADAPTER pAd,
4901 IN MLME_QUEUE_ELEM *Elem)
4905 // ===========================================================================================
4907 // ===========================================================================================
4910 ==========================================================================
4913 IRQL = PASSIVE_LEVEL
4915 ==========================================================================
4918 IN PRTMP_ADAPTER pAd,
4922 pAd->Mlme.ShiftReg = 1;
4924 pAd->Mlme.ShiftReg = Seed;
4928 ==========================================================================
4930 ==========================================================================
4933 IN PRTMP_ADAPTER pAd)
4940 if (pAd->Mlme.ShiftReg == 0)
4941 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
4943 for (i = 0; i < 8; i++)
4945 if (pAd->Mlme.ShiftReg & 0x00000001)
4947 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
4952 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
4955 R = (R << 1) | Result;
4961 VOID AsicUpdateAutoFallBackTable(
4962 IN PRTMP_ADAPTER pAd,
4963 IN PUCHAR pRateTable)
4966 HT_FBK_CFG0_STRUC HtCfg0;
4967 HT_FBK_CFG1_STRUC HtCfg1;
4968 LG_FBK_CFG0_STRUC LgCfg0;
4969 LG_FBK_CFG1_STRUC LgCfg1;
4970 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
4972 // set to initial value
4973 HtCfg0.word = 0x65432100;
4974 HtCfg1.word = 0xedcba988;
4975 LgCfg0.word = 0xedcba988;
4976 LgCfg1.word = 0x00002100;
4978 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
4979 for (i = 1; i < *((PUCHAR) pRateTable); i++)
4981 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
4982 switch (pCurrTxRate->Mode)
4988 switch(pCurrTxRate->CurrMCS)
4991 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4994 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4997 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5000 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5003 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5006 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5009 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5012 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5020 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5022 switch(pCurrTxRate->CurrMCS)
5025 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5028 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5031 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5034 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5037 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5040 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5043 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5046 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5049 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5052 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5055 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5058 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5061 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5064 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5067 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5070 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5073 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5080 pNextTxRate = pCurrTxRate;
5083 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5084 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5085 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5086 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5090 ========================================================================
5092 Routine Description:
5093 Set MAC register value according operation mode.
5094 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5095 If MM or GF mask is not set, those passing argument doesn't not take effect.
5097 Operation mode meaning:
5098 = 0 : Pure HT, no preotection.
5099 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5100 = 0x10: No Transmission in 40M is protected.
5101 = 0x11: Transmission in both 40M and 20M shall be protected
5103 we should choose not to use GF. But still set correct ASIC registers.
5104 ========================================================================
5106 VOID AsicUpdateProtect(
5107 IN PRTMP_ADAPTER pAd,
5108 IN USHORT OperationMode,
5110 IN BOOLEAN bDisableBGProtect,
5111 IN BOOLEAN bNonGFExist)
5113 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5119 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5124 if (pAd->BATable.numAsOriginator)
5127 // enable the RTS/CTS to avoid channel collision
5129 SetMask = ALLN_SETPROTECT;
5133 // Config ASIC RTS threshold register
5134 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5135 MacReg &= 0xFF0000FF;
5137 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5139 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5140 (pAd->CommonCfg.bAggregationCapable == TRUE))
5141 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5143 MacReg |= (0x1000 << 8);
5147 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5150 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5152 // Initial common protection settings
5153 RTMPZeroMemory(Protect, sizeof(Protect));
5156 ProtCfg.field.TxopAllowGF40 = 1;
5157 ProtCfg.field.TxopAllowGF20 = 1;
5158 ProtCfg.field.TxopAllowMM40 = 1;
5159 ProtCfg.field.TxopAllowMM20 = 1;
5160 ProtCfg.field.TxopAllowOfdm = 1;
5161 ProtCfg.field.TxopAllowCck = 1;
5162 ProtCfg.field.RTSThEn = 1;
5163 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5165 // update PHY mode and rate
5166 if (pAd->CommonCfg.Channel > 14)
5167 ProtCfg.field.ProtectRate = 0x4000;
5168 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5170 // Handle legacy(B/G) protection
5171 if (bDisableBGProtect)
5173 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5174 ProtCfg.field.ProtectCtrl = 0;
5175 Protect[0] = ProtCfg.word;
5176 Protect[1] = ProtCfg.word;
5180 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5181 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5182 Protect[0] = ProtCfg.word;
5183 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5184 Protect[1] = ProtCfg.word;
5187 // Decide HT frame protection.
5188 if ((SetMask & ALLN_SETPROTECT) != 0)
5190 switch(OperationMode)
5194 // 1.All STAs in the BSS are 20/40 MHz HT
5195 // 2. in ai 20/40MHz BSS
5196 // 3. all STAs are 20MHz in a 20MHz BSS
5197 // Pure HT. no protection.
5201 // PROT_TXOP(25:20) -- 010111
5202 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5203 // PROT_CTRL(17:16) -- 00 (None)
5204 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5205 Protect[2] = 0x01744004;
5209 // PROT_TXOP(25:20) -- 111111
5210 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5211 // PROT_CTRL(17:16) -- 00 (None)
5212 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5213 Protect[3] = 0x03f44084;
5217 // PROT_TXOP(25:20) -- 010111
5218 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5219 // PROT_CTRL(17:16) -- 00 (None)
5220 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5221 Protect[4] = 0x01744004;
5225 // PROT_TXOP(25:20) -- 111111
5226 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5227 // PROT_CTRL(17:16) -- 00 (None)
5228 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5229 Protect[5] = 0x03f44084;
5233 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5234 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5235 Protect[4] = 0x01754004;
5236 Protect[5] = 0x03f54084;
5238 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5242 // This is "HT non-member protection mode."
5243 // If there may be non-HT STAs my BSS
5244 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5245 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5246 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5248 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5249 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5251 //Assign Protection method for 20&40 MHz packets
5252 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5253 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5254 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5255 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5256 Protect[2] = ProtCfg.word;
5257 Protect[3] = ProtCfg4.word;
5258 Protect[4] = ProtCfg.word;
5259 Protect[5] = ProtCfg4.word;
5260 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5264 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5265 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5266 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5268 //Assign Protection method for 40MHz packets
5269 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5270 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5271 Protect[2] = ProtCfg.word;
5272 Protect[3] = ProtCfg4.word;
5275 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5276 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5278 Protect[4] = ProtCfg.word;
5279 Protect[5] = ProtCfg4.word;
5281 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5285 // HT mixed mode. PROTECT ALL!
5287 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5288 ProtCfg4.word = 0x03f44084;
5289 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5290 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5292 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5293 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5295 //Assign Protection method for 20&40 MHz packets
5296 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5297 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5298 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5299 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5300 Protect[2] = ProtCfg.word;
5301 Protect[3] = ProtCfg4.word;
5302 Protect[4] = ProtCfg.word;
5303 Protect[5] = ProtCfg4.word;
5304 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5308 Protect[2] = 0x01754004;
5309 Protect[3] = 0x03f54084;
5310 Protect[4] = 0x01754004;
5311 Protect[5] = 0x03f54084;
5312 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5317 offset = CCK_PROT_CFG;
5318 for (i = 0;i < 6;i++)
5320 if ((SetMask & (1<< i)))
5322 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5330 ========================================================================
5332 Routine Description: Write RT30xx RF register through MAC
5342 ========================================================================
5344 NTSTATUS RT30xxWriteRFRegister(
5345 IN PRTMP_ADAPTER pAd,
5349 RF_CSR_CFG_STRUC rfcsr;
5354 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5356 if (!rfcsr.field.RF_CSR_KICK)
5360 while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
5362 if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
5364 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
5365 return STATUS_UNSUCCESSFUL;
5368 rfcsr.field.RF_CSR_WR = 1;
5369 rfcsr.field.RF_CSR_KICK = 1;
5370 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5371 rfcsr.field.RF_CSR_DATA = Value;
5373 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5375 return STATUS_SUCCESS;
5380 ========================================================================
5382 Routine Description: Read RT30xx RF register through MAC
5392 ========================================================================
5394 NTSTATUS RT30xxReadRFRegister(
5395 IN PRTMP_ADAPTER pAd,
5399 RF_CSR_CFG_STRUC rfcsr;
5402 for (i=0; i<MAX_BUSY_COUNT; i++)
5404 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5406 if (rfcsr.field.RF_CSR_KICK == BUSY)
5411 rfcsr.field.RF_CSR_WR = 0;
5412 rfcsr.field.RF_CSR_KICK = 1;
5413 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5414 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5415 for (k=0; k<MAX_BUSY_COUNT; k++)
5417 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5419 if (rfcsr.field.RF_CSR_KICK == IDLE)
5422 if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
5423 (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
5425 *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
5429 if (rfcsr.field.RF_CSR_KICK == BUSY)
5431 DBGPRINT_ERR(("RF read R%d=0x%x fail, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
5432 return STATUS_UNSUCCESSFUL;
5435 return STATUS_SUCCESS;
5440 // add by johnli, RF power sequence setup
5442 ==========================================================================
5445 Load RF normal operation-mode setup
5447 ==========================================================================
5449 VOID RT30xxLoadRFNormalModeSetup(
5450 IN PRTMP_ADAPTER pAd)
5454 // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5455 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5456 RFValue = (RFValue & (~0x0C)) | 0x31;
5457 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5459 // TX_LO2_en, RF R15 register Bit 3 to 0
5460 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5462 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5464 // TX_LO1_en, RF R17 register Bit 3 to 0
5465 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5467 // to fix rx long range issue
5468 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5472 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5474 // RX_LO1_en, RF R20 register Bit 3 to 0
5475 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5477 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5479 // RX_LO2_en, RF R21 register Bit 3 to 0
5480 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5482 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5484 // LDORF_VC, RF R27 register Bit 2 to 0
5485 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5486 if ((pAd->MACVersion & 0xffff) < 0x0211)
5487 RFValue = (RFValue & (~0x77)) | 0x3;
5489 RFValue = (RFValue & (~0x77));
5490 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5495 ==========================================================================
5498 Load RF sleep-mode setup
5500 ==========================================================================
5502 VOID RT30xxLoadRFSleepModeSetup(
5503 IN PRTMP_ADAPTER pAd)
5508 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5509 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5511 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5513 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5514 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5516 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5518 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5519 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5521 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5523 // RX_CTB_en, RF R21 register Bit 7 to 0
5524 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5526 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5528 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5529 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5531 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5533 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5534 MACValue |= 0x1D000000;
5535 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5539 ==========================================================================
5542 Reverse RF sleep-mode setup
5544 ==========================================================================
5546 VOID RT30xxReverseRFSleepModeSetup(
5547 IN PRTMP_ADAPTER pAd)
5552 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5553 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5555 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5557 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5558 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5560 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5562 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5563 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5565 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5567 // RX_CTB_en, RF R21 register Bit 7 to 1
5568 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5570 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5572 // LDORF_VC, RF R27 register Bit 2 to 0
5573 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5574 if ((pAd->MACVersion & 0xffff) < 0x0211)
5575 RFValue = (RFValue & (~0x77)) | 0x3;
5577 RFValue = (RFValue & (~0x77));
5578 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5580 // RT3071 version E has fixed this issue
5581 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5583 // patch tx EVM issue temporarily
5584 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5585 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5586 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5590 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5591 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5592 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5599 ==========================================================================
5602 IRQL = PASSIVE_LEVEL
5603 IRQL = DISPATCH_LEVEL
5605 ==========================================================================
5607 VOID AsicSwitchChannel(
5608 IN PRTMP_ADAPTER pAd,
5612 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5613 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5615 UINT32 Value = 0; //BbpReg, Value;
5616 RTMP_RF_REGS *RFRegTable;
5618 // Search Tx power value
5620 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5621 // in ChannelList, so use TxPower array instead.
5623 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5625 if (Channel == pAd->TxPower[index].Channel)
5627 TxPwer = pAd->TxPower[index].Power;
5628 TxPwer2 = pAd->TxPower[index].Power2;
5633 for (index = 0; index < pAd->ChannelListNum; index++)
5635 if (Channel == pAd->ChannelList[index].Channel)
5637 TxPwer = pAd->ChannelList[index].Power;
5638 TxPwer2 = pAd->ChannelList[index].Power2;
5644 if (index == MAX_NUM_OF_CHANNELS)
5646 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5650 // The RF programming sequence is difference between 3xxx and 2xxx
5651 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5652 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5654 /* modify by WY for Read RF Reg. error */
5657 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5659 if (Channel == FreqItems3020[index].Channel)
5661 // Programming channel parameters
5662 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5663 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5664 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5665 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5666 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5669 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5670 RFValue = (RFValue & 0xE0) | TxPwer;
5671 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5674 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5675 RFValue = (RFValue & 0xE0) | TxPwer2;
5676 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5678 // Tx/Rx Stream setting
5679 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5680 //if (IS_RT3090(pAd))
5681 // RFValue |= 0x01; // Enable RF block.
5682 RFValue &= 0x03; //clear bit[7~2]
5683 if (pAd->Antenna.field.TxPath == 1)
5685 else if (pAd->Antenna.field.TxPath == 2)
5687 if (pAd->Antenna.field.RxPath == 1)
5689 else if (pAd->Antenna.field.RxPath == 2)
5691 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5694 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5695 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5696 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5699 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5701 RFValue = pAd->Mlme.CaliBW40RfR24;
5702 //DISABLE_11N_CHECK(pAd);
5706 RFValue = pAd->Mlme.CaliBW20RfR24;
5708 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5709 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5712 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5713 RFValue = RFValue | 0x1;
5714 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5716 // latch channel for future usage.
5717 pAd->LatchRfRegs.Channel = Channel;
5719 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5724 pAd->Antenna.field.TxPath,
5725 FreqItems3020[index].N,
5726 FreqItems3020[index].K,
5727 FreqItems3020[index].R));
5737 RFRegTable = RF2850RegTable;
5739 switch (pAd->RfIcType)
5746 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5748 if (Channel == RFRegTable[index].Channel)
5750 R2 = RFRegTable[index].R2;
5751 if (pAd->Antenna.field.TxPath == 1)
5753 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5756 if (pAd->Antenna.field.RxPath == 2)
5758 R2 |= 0x40; // write 1 to off Rxpath.
5760 else if (pAd->Antenna.field.RxPath == 1)
5762 R2 |= 0x20040; // write 1 to off RxPath
5767 // initialize R3, R4
5768 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5769 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5771 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5773 if ((TxPwer >= -7) && (TxPwer < 0))
5775 TxPwer = (7+TxPwer);
5776 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5777 R3 |= (TxPwer << 10);
5778 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5782 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5783 R3 |= (TxPwer << 10) | (1 << 9);
5787 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5789 TxPwer2 = (7+TxPwer2);
5790 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5791 R4 |= (TxPwer2 << 7);
5792 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5796 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5797 R4 |= (TxPwer2 << 7) | (1 << 6);
5802 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5803 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5806 // Based on BBP current mode before changing RF channel.
5807 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5813 pAd->LatchRfRegs.Channel = Channel;
5814 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5815 pAd->LatchRfRegs.R2 = R2;
5816 pAd->LatchRfRegs.R3 = R3;
5817 pAd->LatchRfRegs.R4 = R4;
5819 // Set RF value 1's set R3[bit2] = [0]
5820 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5821 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5822 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5823 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5827 // Set RF value 2's set R3[bit2] = [1]
5828 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5829 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5830 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5831 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5835 // Set RF value 3's set R3[bit2] = [0]
5836 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5837 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5838 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5839 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5851 // Change BBP setting during siwtch from a->g, g->a
5854 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5856 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5857 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5858 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5859 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.
5860 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5862 // Rx High power VGA offset for LNA select
5863 if (pAd->NicConfig2.field.ExternalLNAForG)
5865 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5866 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5870 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5871 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5874 // 5G band selection PIN, bit1 and bit2 are complement
5875 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5878 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5880 // Turn off unused PA or LNA when only 1T or 1R
5881 if (pAd->Antenna.field.TxPath == 1)
5883 TxPinCfg &= 0xFFFFFFF3;
5885 if (pAd->Antenna.field.RxPath == 1)
5887 TxPinCfg &= 0xFFFFF3FF;
5890 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5894 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5896 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5897 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5898 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5899 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.
5900 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5902 // Rx High power VGA offset for LNA select
5903 if (pAd->NicConfig2.field.ExternalLNAForA)
5905 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5909 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5912 // 5G band selection PIN, bit1 and bit2 are complement
5913 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5916 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5918 // Turn off unused PA or LNA when only 1T or 1R
5919 if (pAd->Antenna.field.TxPath == 1)
5921 TxPinCfg &= 0xFFFFFFF3;
5923 if (pAd->Antenna.field.RxPath == 1)
5925 TxPinCfg &= 0xFFFFF3FF;
5928 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5931 // R66 should be set according to Channel and use 20MHz when scanning
5932 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5934 RTMPSetAGCInitValue(pAd, BW_20);
5936 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5939 // On 11A, We should delay and wait RF/BBP to be stable
5940 // and the appropriate time should be 1000 micro seconds
5941 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5943 RTMPusecDelay(1000);
5945 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",
5948 (R3 & 0x00003e00) >> 9,
5949 (R4 & 0x000007c0) >> 6,
5950 pAd->Antenna.field.TxPath,
5951 pAd->LatchRfRegs.R1,
5952 pAd->LatchRfRegs.R2,
5953 pAd->LatchRfRegs.R3,
5954 pAd->LatchRfRegs.R4));
5958 ==========================================================================
5960 This function is required for 2421 only, and should not be used during
5961 site survey. It's only required after NIC decided to stay at a channel
5962 for a longer period.
5963 When this function is called, it's always after AsicSwitchChannel().
5965 IRQL = PASSIVE_LEVEL
5966 IRQL = DISPATCH_LEVEL
5968 ==========================================================================
5970 VOID AsicLockChannel(
5971 IN PRTMP_ADAPTER pAd,
5977 ==========================================================================
5980 IRQL = PASSIVE_LEVEL
5981 IRQL = DISPATCH_LEVEL
5983 ==========================================================================
5985 VOID AsicAntennaSelect(
5986 IN PRTMP_ADAPTER pAd,
5989 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
5991 // patch for AsicSetRxAnt failed
5992 pAd->RxAnt.EvaluatePeriod = 0;
5994 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
5995 // valid indication of the distance between this AP and its clients.
5996 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6000 // if no traffic then reset average rssi to trigger evaluation
6001 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6003 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6004 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6005 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6008 pAd->StaCfg.NumOfAvgRssiSample = 0;
6009 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6011 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6013 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6014 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6016 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6017 AsicEvaluateRxAnt(pAd);
6022 // if not connected, always switch antenna to try to connect
6025 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6026 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6027 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6029 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6031 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6037 ========================================================================
6039 Routine Description:
6040 Antenna miscellaneous setting.
6043 pAd Pointer to our adapter
6044 BandState Indicate current Band State.
6049 IRQL <= DISPATCH_LEVEL
6052 1.) Frame End type control
6053 only valid for G only (RF_2527 & RF_2529)
6054 0: means DPDT, set BBP R4 bit 5 to 1
6055 1: means SPDT, set BBP R4 bit 5 to 0
6058 ========================================================================
6060 VOID AsicAntennaSetting(
6061 IN PRTMP_ADAPTER pAd,
6062 IN ABGBAND_STATE BandState)
6066 VOID AsicRfTuningExec(
6067 IN PVOID SystemSpecific1,
6068 IN PVOID FunctionContext,
6069 IN PVOID SystemSpecific2,
6070 IN PVOID SystemSpecific3)
6075 ==========================================================================
6077 Gives CCK TX rate 2 more dB TX power.
6078 This routine works only in LINK UP in INFRASTRUCTURE mode.
6080 calculate desired Tx power in RF R3.Tx0~5, should consider -
6081 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6082 1. TxPowerPercentage
6083 2. auto calibration based on TSSI feedback
6084 3. extra 2 db for CCK
6085 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6087 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6088 it should be called AFTER MlmeDynamicTxRatSwitching()
6089 ==========================================================================
6091 VOID AsicAdjustTxPower(
6092 IN PRTMP_ADAPTER pAd)
6096 BOOLEAN bAutoTxAgc = FALSE;
6097 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6098 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6099 PCHAR pTxAgcCompensate;
6105 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6107 if (pAd->CommonCfg.CentralChannel > 14)
6109 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6110 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6111 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6112 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6113 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6117 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6118 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6119 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6120 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6121 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6126 if (pAd->CommonCfg.Channel > 14)
6128 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6129 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6130 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6131 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6132 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6136 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6137 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6138 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6139 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6140 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6144 // TX power compensation for temperature variation based on TSSI. try every 4 second
6145 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6147 if (pAd->CommonCfg.Channel <= 14)
6150 bAutoTxAgc = pAd->bAutoTxAgcG;
6151 TssiRef = pAd->TssiRefG;
6152 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6153 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6154 TxAgcStep = pAd->TxAgcStepG;
6155 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6160 bAutoTxAgc = pAd->bAutoTxAgcA;
6161 TssiRef = pAd->TssiRefA;
6162 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6163 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6164 TxAgcStep = pAd->TxAgcStepA;
6165 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6170 /* BbpR1 is unsigned char */
6171 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6173 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6174 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6175 /* step value is defined in pAd->TxAgcStepG for tx power value */
6177 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6178 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6179 above value are examined in mass factory production */
6180 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6182 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6183 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6184 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6186 if (BbpR49 > pTssiMinusBoundary[1])
6188 // Reading is larger than the reference value
6189 // check for how large we need to decrease the Tx power
6190 for (idx = 1; idx < 5; idx++)
6192 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6195 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6196 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6197 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6199 // *pTxAgcCompensate = -((UCHAR)R3);
6201 DeltaPwr += (*pTxAgcCompensate);
6202 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6203 BbpR49, TssiRef, TxAgcStep, idx-1));
6205 else if (BbpR49 < pTssiPlusBoundary[1])
6207 // Reading is smaller than the reference value
6208 // check for how large we need to increase the Tx power
6209 for (idx = 1; idx < 5; idx++)
6211 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6214 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6215 *pTxAgcCompensate = TxAgcStep * (idx-1);
6216 DeltaPwr += (*pTxAgcCompensate);
6217 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6218 BbpR49, TssiRef, TxAgcStep, idx-1));
6222 *pTxAgcCompensate = 0;
6223 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6224 BbpR49, TssiRef, TxAgcStep, 0));
6230 if (pAd->CommonCfg.Channel <= 14)
6232 bAutoTxAgc = pAd->bAutoTxAgcG;
6233 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6237 bAutoTxAgc = pAd->bAutoTxAgcA;
6238 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6242 DeltaPwr += (*pTxAgcCompensate);
6245 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6248 /* calculate delta power based on the percentage specified from UI */
6249 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6250 // We lower TX power here according to the percentage specified from UI
6251 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6253 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6255 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6259 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6263 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6267 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6272 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6277 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6279 /* reset different new tx power for different TX rate */
6282 if (TxPwr[i] != 0xffffffff)
6286 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6288 if ((Value + DeltaPwr) < 0)
6290 Value = 0; /* min */
6292 else if ((Value + DeltaPwr) > 0xF)
6294 Value = 0xF; /* max */
6298 Value += DeltaPwr; /* temperature compensation */
6301 /* fill new value to CSR offset */
6302 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6305 /* write tx power value to CSR */
6306 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6307 TX power for OFDM 6M/9M
6308 TX power for CCK5.5M/11M
6309 TX power for CCK1M/2M */
6310 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6311 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6319 ==========================================================================
6321 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6322 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6323 the wakeup timer timeout. Driver has to issue a separate command to wake
6326 IRQL = DISPATCH_LEVEL
6328 ==========================================================================
6330 VOID AsicSleepThenAutoWakeup(
6331 IN PRTMP_ADAPTER pAd,
6332 IN USHORT TbttNumToNextWakeUp)
6334 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6338 ==========================================================================
6340 AsicForceWakeup() is used whenever manual wakeup is required
6341 AsicForceSleep() should only be used when not in INFRA BSS. When
6342 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6343 ==========================================================================
6345 VOID AsicForceSleep(
6346 IN PRTMP_ADAPTER pAd)
6352 ==========================================================================
6354 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6357 IRQL = PASSIVE_LEVEL
6358 IRQL = DISPATCH_LEVEL
6359 ==========================================================================
6361 VOID AsicForceWakeup(
6362 IN PRTMP_ADAPTER pAd,
6365 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6366 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6370 ==========================================================================
6374 IRQL = DISPATCH_LEVEL
6376 ==========================================================================
6379 IN PRTMP_ADAPTER pAd,
6383 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6384 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6386 Addr4 = (ULONG)(pBssid[0]) |
6387 (ULONG)(pBssid[1] << 8) |
6388 (ULONG)(pBssid[2] << 16) |
6389 (ULONG)(pBssid[3] << 24);
6390 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6393 // always one BSSID in STA mode
6394 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6396 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6399 VOID AsicSetMcastWC(
6400 IN PRTMP_ADAPTER pAd)
6402 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6405 pEntry->Sst = SST_ASSOC;
6406 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6407 pEntry->PsMode = PWR_ACTIVE;
6408 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6409 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6413 ==========================================================================
6416 IRQL = DISPATCH_LEVEL
6418 ==========================================================================
6420 VOID AsicDelWcidTab(
6421 IN PRTMP_ADAPTER pAd,
6424 ULONG Addr0 = 0x0, Addr1 = 0x0;
6427 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6428 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6429 RTMP_IO_WRITE32(pAd, offset, Addr0);
6431 RTMP_IO_WRITE32(pAd, offset, Addr1);
6435 ==========================================================================
6438 IRQL = DISPATCH_LEVEL
6440 ==========================================================================
6443 IN PRTMP_ADAPTER pAd)
6445 TX_LINK_CFG_STRUC TxLinkCfg;
6448 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6449 TxLinkCfg.field.TxRDGEn = 1;
6450 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6452 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6455 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6457 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6461 ==========================================================================
6464 IRQL = DISPATCH_LEVEL
6466 ==========================================================================
6468 VOID AsicDisableRDG(
6469 IN PRTMP_ADAPTER pAd)
6471 TX_LINK_CFG_STRUC TxLinkCfg;
6475 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6476 TxLinkCfg.field.TxRDGEn = 0;
6477 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6479 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6484 //if ( pAd->CommonCfg.bEnableTxBurst )
6485 // Data |= 0x60; // for performance issue not set the TXOP to 0
6487 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6488 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6491 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6492 if (pAd->CommonCfg.bEnableTxBurst)
6495 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6499 ==========================================================================
6502 IRQL = PASSIVE_LEVEL
6503 IRQL = DISPATCH_LEVEL
6505 ==========================================================================
6507 VOID AsicDisableSync(
6508 IN PRTMP_ADAPTER pAd)
6510 BCN_TIME_CFG_STRUC csr;
6512 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6514 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6515 // that NIC will never wakes up because TSF stops and no more
6517 pAd->TbttTickCount = 0;
6518 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6519 csr.field.bBeaconGen = 0;
6520 csr.field.bTBTTEnable = 0;
6521 csr.field.TsfSyncMode = 0;
6522 csr.field.bTsfTicking = 0;
6523 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6528 ==========================================================================
6531 IRQL = DISPATCH_LEVEL
6533 ==========================================================================
6535 VOID AsicEnableBssSync(
6536 IN PRTMP_ADAPTER pAd)
6538 BCN_TIME_CFG_STRUC csr;
6540 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6542 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6543 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6546 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6547 csr.field.bTsfTicking = 1;
6548 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6549 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6550 csr.field.bTBTTEnable = 1;
6553 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6557 ==========================================================================
6560 BEACON frame in shared memory should be built ok before this routine
6561 can be called. Otherwise, a garbage frame maybe transmitted out every
6564 IRQL = DISPATCH_LEVEL
6566 ==========================================================================
6568 VOID AsicEnableIbssSync(
6569 IN PRTMP_ADAPTER pAd)
6571 BCN_TIME_CFG_STRUC csr9;
6575 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6577 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6578 csr9.field.bBeaconGen = 0;
6579 csr9.field.bTBTTEnable = 0;
6580 csr9.field.bTsfTicking = 0;
6581 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6585 // move BEACON TXD and frame content to on-chip memory
6586 ptr = (PUCHAR)&pAd->BeaconTxWI;
6587 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6589 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6590 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6591 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6595 // start right after the 16-byte TXWI field
6596 ptr = pAd->BeaconBuf;
6597 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6599 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6600 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6601 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6607 // For Wi-Fi faily generated beacons between participating stations.
6608 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
6609 // don't change settings 2006-5- by Jerry
6610 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
6612 // start sending BEACON
6613 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6614 csr9.field.bTsfTicking = 1;
6615 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6616 csr9.field.bTBTTEnable = 1;
6617 csr9.field.bBeaconGen = 1;
6618 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6622 ==========================================================================
6625 IRQL = PASSIVE_LEVEL
6626 IRQL = DISPATCH_LEVEL
6628 ==========================================================================
6630 VOID AsicSetEdcaParm(
6631 IN PRTMP_ADAPTER pAd,
6632 IN PEDCA_PARM pEdcaParm)
6634 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6635 AC_TXOP_CSR0_STRUC csr0;
6636 AC_TXOP_CSR1_STRUC csr1;
6637 AIFSN_CSR_STRUC AifsnCsr;
6638 CWMIN_CSR_STRUC CwminCsr;
6639 CWMAX_CSR_STRUC CwmaxCsr;
6646 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6648 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6649 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6650 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6652 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6653 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6656 //========================================================
6657 // MAC Register has a copy .
6658 //========================================================
6660 if( pAd->CommonCfg.bEnableTxBurst )
6662 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6663 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6666 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6668 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6670 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6671 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6672 Ac0Cfg.field.Aifsn = 2;
6673 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6675 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6676 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6677 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6678 Ac1Cfg.field.Aifsn = 2;
6679 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6681 if (pAd->CommonCfg.PhyMode == PHY_11B)
6683 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6684 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6688 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6689 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6691 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6692 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6693 Ac2Cfg.field.Aifsn = 2;
6694 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6695 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6696 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6697 Ac3Cfg.field.Aifsn = 2;
6698 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6700 //========================================================
6701 // DMA Register has a copy too.
6702 //========================================================
6703 csr0.field.Ac0Txop = 0; // QID_AC_BE
6704 csr0.field.Ac1Txop = 0; // QID_AC_BK
6705 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6706 if (pAd->CommonCfg.PhyMode == PHY_11B)
6708 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6709 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6713 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6714 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6716 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6719 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6720 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6721 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6722 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6723 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6726 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6727 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6728 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6729 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6730 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6732 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6734 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6738 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6739 //========================================================
6740 // MAC Register has a copy.
6741 //========================================================
6743 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6744 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6746 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6748 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6749 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6750 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6751 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6753 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6754 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6755 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6756 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6758 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6759 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6760 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6761 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6764 // Tuning for Wi-Fi WMM S06
6765 if (pAd->CommonCfg.bWiFiTest &&
6766 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6767 Ac2Cfg.field.Aifsn -= 1;
6769 // Tuning for TGn Wi-Fi 5.2.32
6770 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6771 if (STA_TGN_WIFI_ON(pAd) &&
6772 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6774 Ac0Cfg.field.Aifsn = 3;
6775 Ac2Cfg.field.AcTxop = 5;
6779 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6781 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6782 Ac2Cfg.field.Aifsn = 5;
6787 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6788 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6789 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6790 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6793 if (pAd->CommonCfg.bWiFiTest)
6795 if (Ac3Cfg.field.AcTxop == 102)
6797 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6798 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6799 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6800 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6801 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6804 //#endif // WIFI_TEST //
6806 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6807 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6808 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6809 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6812 //========================================================
6813 // DMA Register has a copy too.
6814 //========================================================
6815 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6816 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6817 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6819 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6820 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6821 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6824 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6825 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6826 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6828 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6830 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6833 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6834 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6835 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6836 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6837 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6840 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6841 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6842 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6845 // Tuning for Wi-Fi WMM S06
6846 if (pAd->CommonCfg.bWiFiTest &&
6847 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6848 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6850 // Tuning for TGn Wi-Fi 5.2.32
6851 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6852 if (STA_TGN_WIFI_ON(pAd) &&
6853 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6855 AifsnCsr.field.Aifsn0 = 3;
6856 AifsnCsr.field.Aifsn2 = 7;
6860 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6863 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6865 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6866 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
6869 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6871 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6874 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6875 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6876 pEdcaParm->Aifsn[0],
6877 pEdcaParm->Cwmin[0],
6878 pEdcaParm->Cwmax[0],
6879 pEdcaParm->Txop[0]<<5,
6880 pEdcaParm->bACM[0]));
6881 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6882 pEdcaParm->Aifsn[1],
6883 pEdcaParm->Cwmin[1],
6884 pEdcaParm->Cwmax[1],
6885 pEdcaParm->Txop[1]<<5,
6886 pEdcaParm->bACM[1]));
6887 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6888 pEdcaParm->Aifsn[2],
6889 pEdcaParm->Cwmin[2],
6890 pEdcaParm->Cwmax[2],
6891 pEdcaParm->Txop[2]<<5,
6892 pEdcaParm->bACM[2]));
6893 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6894 pEdcaParm->Aifsn[3],
6895 pEdcaParm->Cwmin[3],
6896 pEdcaParm->Cwmax[3],
6897 pEdcaParm->Txop[3]<<5,
6898 pEdcaParm->bACM[3]));
6904 ==========================================================================
6907 IRQL = PASSIVE_LEVEL
6908 IRQL = DISPATCH_LEVEL
6910 ==========================================================================
6912 VOID AsicSetSlotTime(
6913 IN PRTMP_ADAPTER pAd,
6914 IN BOOLEAN bUseShortSlotTime)
6917 UINT32 RegValue = 0;
6919 if (pAd->CommonCfg.Channel > 14)
6920 bUseShortSlotTime = TRUE;
6922 if (bUseShortSlotTime)
6923 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6925 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6927 SlotTime = (bUseShortSlotTime)? 9 : 20;
6930 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6931 if (pAd->CommonCfg.bEnableTxBurst)
6936 // For some reasons, always set it to short slot time.
6938 // ToDo: Should consider capability with 11B
6940 if (pAd->StaCfg.BssType == BSS_ADHOC)
6943 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6944 RegValue = RegValue & 0xFFFFFF00;
6946 RegValue |= SlotTime;
6948 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6952 ========================================================================
6954 Add Shared key information into ASIC.
6955 Update shared key, TxMic and RxMic to Asic Shared key table
6956 Update its cipherAlg to Asic Shared key Mode.
6959 ========================================================================
6961 VOID AsicAddSharedKeyEntry(
6962 IN PRTMP_ADAPTER pAd,
6970 ULONG offset; //, csr0;
6971 SHAREDKEY_MODE_STRUC csr1;
6973 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6974 //============================================================================================
6976 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6977 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6978 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]));
6981 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6982 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6986 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6987 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6989 //============================================================================================
6991 // fill key material - key + TX MIC + RX MIC
6996 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6997 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
6999 offset += MAX_LEN_OF_SHARE_KEY;
7002 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7008 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7014 // Update cipher algorithm. WSTA always use BSS0
7016 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7017 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7018 if ((BssIndex%2) == 0)
7021 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7022 else if (KeyIdx == 1)
7023 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7024 else if (KeyIdx == 2)
7025 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7027 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7032 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7033 else if (KeyIdx == 1)
7034 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7035 else if (KeyIdx == 2)
7036 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7038 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7040 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7041 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7045 // IRQL = DISPATCH_LEVEL
7046 VOID AsicRemoveSharedKeyEntry(
7047 IN PRTMP_ADAPTER pAd,
7052 SHAREDKEY_MODE_STRUC csr1;
7054 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7056 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7057 if ((BssIndex%2) == 0)
7060 csr1.field.Bss0Key0CipherAlg = 0;
7061 else if (KeyIdx == 1)
7062 csr1.field.Bss0Key1CipherAlg = 0;
7063 else if (KeyIdx == 2)
7064 csr1.field.Bss0Key2CipherAlg = 0;
7066 csr1.field.Bss0Key3CipherAlg = 0;
7071 csr1.field.Bss1Key0CipherAlg = 0;
7072 else if (KeyIdx == 1)
7073 csr1.field.Bss1Key1CipherAlg = 0;
7074 else if (KeyIdx == 2)
7075 csr1.field.Bss1Key2CipherAlg = 0;
7077 csr1.field.Bss1Key3CipherAlg = 0;
7079 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7080 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7081 ASSERT(BssIndex < 4);
7087 VOID AsicUpdateWCIDAttribute(
7088 IN PRTMP_ADAPTER pAd,
7092 IN BOOLEAN bUsePairewiseKeyTable)
7094 ULONG WCIDAttri = 0, offset;
7097 // Update WCID attribute.
7098 // Only TxKey could update WCID attribute.
7100 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7101 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7102 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7105 VOID AsicUpdateWCIDIVEIV(
7106 IN PRTMP_ADAPTER pAd,
7113 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7115 RTMP_IO_WRITE32(pAd, offset, uIV);
7116 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7119 VOID AsicUpdateRxWCIDTable(
7120 IN PRTMP_ADAPTER pAd,
7127 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7128 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7129 RTMP_IO_WRITE32(pAd, offset, Addr);
7130 Addr = pAddr[4] + (pAddr[5] << 8);
7131 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7136 ========================================================================
7138 Routine Description:
7139 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7142 pAd Pointer to our adapter
7143 WCID WCID Entry number.
7144 BssIndex BSSID index, station or none multiple BSSID support
7145 this value should be 0.
7146 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7147 pCipherKey Pointer to Cipher Key.
7148 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7149 otherwise PairewiseKey table
7150 bTxKey This is the transmit key if enabled.
7156 This routine will set the relative key stuff to Asic including WCID attribute,
7157 Cipher Key, Cipher algorithm and IV/EIV.
7159 IV/EIV will be update if this CipherKey is the transmission key because
7160 ASIC will base on IV's KeyID value to select Cipher Key.
7162 If bTxKey sets to FALSE, this is not the TX key, but it could be
7165 For AP mode bTxKey must be always set to TRUE.
7166 ========================================================================
7168 VOID AsicAddKeyEntry(
7169 IN PRTMP_ADAPTER pAd,
7173 IN PCIPHER_KEY pCipherKey,
7174 IN BOOLEAN bUsePairewiseKeyTable,
7178 // ULONG WCIDAttri = 0;
7180 PUCHAR pKey = pCipherKey->Key;
7181 // ULONG KeyLen = pCipherKey->KeyLen;
7182 PUCHAR pTxMic = pCipherKey->TxMic;
7183 PUCHAR pRxMic = pCipherKey->RxMic;
7184 PUCHAR pTxtsc = pCipherKey->TxTsc;
7185 UCHAR CipherAlg = pCipherKey->CipherAlg;
7186 SHAREDKEY_MODE_STRUC csr1;
7188 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7190 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7192 // 1.) decide key table offset
7194 if (bUsePairewiseKeyTable)
7195 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7197 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7200 // 2.) Set Key to Asic
7202 //for (i = 0; i < KeyLen; i++)
7205 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7206 offset += MAX_LEN_OF_PEER_KEY;
7209 // 3.) Set MIC key if available
7213 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7215 offset += LEN_TKIP_TXMICK;
7219 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7224 // 4.) Modify IV/EIV if needs
7225 // This will force Asic to use this key ID by setting IV.
7236 IV4 = (KeyIdx << 6);
7237 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7238 IV4 |= 0x20; // turn on extension bit means EIV existence
7240 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7241 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7247 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7249 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7252 if (!bUsePairewiseKeyTable)
7255 // Only update the shared key security mode
7257 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7258 if ((BssIndex % 2) == 0)
7261 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7262 else if (KeyIdx == 1)
7263 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7264 else if (KeyIdx == 2)
7265 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7267 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7272 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7273 else if (KeyIdx == 1)
7274 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7275 else if (KeyIdx == 2)
7276 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7278 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7280 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7283 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7288 ========================================================================
7290 Add Pair-wise key material into ASIC.
7291 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7294 ========================================================================
7296 VOID AsicAddPairwiseKeyEntry(
7297 IN PRTMP_ADAPTER pAd,
7300 IN CIPHER_KEY *pCipherKey)
7304 PUCHAR pKey = pCipherKey->Key;
7305 PUCHAR pTxMic = pCipherKey->TxMic;
7306 PUCHAR pRxMic = pCipherKey->RxMic;
7308 UCHAR CipherAlg = pCipherKey->CipherAlg;
7312 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7314 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7316 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7319 RTMP_IO_READ32(pAd, offset + i, &Value);
7322 offset += MAX_LEN_OF_PEER_KEY;
7328 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7335 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7339 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7340 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7341 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]));
7344 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7345 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7349 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7350 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7354 ========================================================================
7356 Remove Pair-wise key material from ASIC.
7359 ========================================================================
7361 VOID AsicRemovePairwiseKeyEntry(
7362 IN PRTMP_ADAPTER pAd,
7369 // re-set the entry's WCID attribute as OPEN-NONE.
7370 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7371 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7372 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7375 BOOLEAN AsicSendCommandToMcu(
7376 IN PRTMP_ADAPTER pAd,
7382 HOST_CMD_CSR_STRUC H2MCmd;
7383 H2M_MAILBOX_STRUC H2MMailbox;
7387 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7388 if (H2MMailbox.field.Owner == 0)
7397 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7403 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7404 H2MMailbox.field.CmdToken = Token;
7405 H2MMailbox.field.HighByte = Arg1;
7406 H2MMailbox.field.LowByte = Arg0;
7407 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7410 H2MCmd.field.HostCommand = Command;
7411 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7413 if (Command != 0x80)
7422 ========================================================================
7424 Routine Description:
7425 Verify the support rate for different PHY type
7428 pAd Pointer to our adapter
7433 IRQL = PASSIVE_LEVEL
7435 ========================================================================
7437 VOID RTMPCheckRates(
7438 IN PRTMP_ADAPTER pAd,
7439 IN OUT UCHAR SupRate[],
7440 IN OUT UCHAR *SupRateLen)
7442 UCHAR RateIdx, i, j;
7443 UCHAR NewRate[12], NewRateLen;
7447 if (pAd->CommonCfg.PhyMode == PHY_11B)
7452 // Check for support rates exclude basic rate bit
7453 for (i = 0; i < *SupRateLen; i++)
7454 for (j = 0; j < RateIdx; j++)
7455 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7456 NewRate[NewRateLen++] = SupRate[i];
7458 *SupRateLen = NewRateLen;
7459 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7462 BOOLEAN RTMPCheckChannel(
7463 IN PRTMP_ADAPTER pAd,
7464 IN UCHAR CentralChannel,
7468 UCHAR UpperChannel = 0, LowerChannel = 0;
7469 UCHAR NoEffectChannelinList = 0;
7471 // Find upper and lower channel according to 40MHz current operation.
7472 if (CentralChannel < Channel)
7474 UpperChannel = Channel;
7475 if (CentralChannel > 2)
7476 LowerChannel = CentralChannel - 2;
7480 else if (CentralChannel > Channel)
7482 UpperChannel = CentralChannel + 2;
7483 LowerChannel = Channel;
7486 for (k = 0;k < pAd->ChannelListNum;k++)
7488 if (pAd->ChannelList[k].Channel == UpperChannel)
7490 NoEffectChannelinList ++;
7492 if (pAd->ChannelList[k].Channel == LowerChannel)
7494 NoEffectChannelinList ++;
7498 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7499 if (NoEffectChannelinList == 2)
7506 ========================================================================
7508 Routine Description:
7509 Verify the support rate for HT phy type
7512 pAd Pointer to our adapter
7515 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7517 IRQL = PASSIVE_LEVEL
7519 ========================================================================
7521 BOOLEAN RTMPCheckHt(
7522 IN PRTMP_ADAPTER pAd,
7524 IN HT_CAPABILITY_IE *pHtCapability,
7525 IN ADD_HT_INFO_IE *pAddHtInfo)
7527 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7530 // If use AMSDU, set flag.
7531 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7532 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7533 // Save Peer Capability
7534 if (pHtCapability->HtCapInfo.ShortGIfor20)
7535 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7536 if (pHtCapability->HtCapInfo.ShortGIfor40)
7537 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7538 if (pHtCapability->HtCapInfo.TxSTBC)
7539 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7540 if (pHtCapability->HtCapInfo.RxSTBC)
7541 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7542 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7544 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7547 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7549 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7552 // Will check ChannelWidth for MCSSet[4] below
7553 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7554 switch (pAd->CommonCfg.RxStream)
7557 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7558 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7559 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7560 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7563 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7564 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7565 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7566 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7569 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7570 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7571 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7572 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7576 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7578 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7579 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7580 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7582 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7584 // Send Assoc Req with my HT capability.
7585 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7586 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7587 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7588 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7589 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7590 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7591 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7592 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7593 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7594 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7595 if (pAd->CommonCfg.bRdg)
7597 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7598 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7601 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7602 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7604 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7609 ========================================================================
7611 Routine Description:
7612 Verify the support rate for different PHY type
7615 pAd Pointer to our adapter
7620 IRQL = PASSIVE_LEVEL
7622 ========================================================================
7624 VOID RTMPUpdateMlmeRate(
7625 IN PRTMP_ADAPTER pAd)
7628 UCHAR ProperMlmeRate; //= RATE_54;
7629 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7630 BOOLEAN bMatch = FALSE;
7632 switch (pAd->CommonCfg.PhyMode)
7635 ProperMlmeRate = RATE_11;
7636 MinimumRate = RATE_1;
7638 case PHY_11BG_MIXED:
7639 case PHY_11ABGN_MIXED:
7640 case PHY_11BGN_MIXED:
7641 if ((pAd->MlmeAux.SupRateLen == 4) &&
7642 (pAd->MlmeAux.ExtRateLen == 0))
7644 ProperMlmeRate = RATE_11;
7646 ProperMlmeRate = RATE_24;
7648 if (pAd->MlmeAux.Channel <= 14)
7649 MinimumRate = RATE_1;
7651 MinimumRate = RATE_6;
7654 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7655 case PHY_11GN_MIXED:
7656 case PHY_11AGN_MIXED:
7657 case PHY_11AN_MIXED:
7659 ProperMlmeRate = RATE_24;
7660 MinimumRate = RATE_6;
7662 case PHY_11ABG_MIXED:
7663 ProperMlmeRate = RATE_24;
7664 if (pAd->MlmeAux.Channel <= 14)
7665 MinimumRate = RATE_1;
7667 MinimumRate = RATE_6;
7670 ProperMlmeRate = RATE_1;
7671 MinimumRate = RATE_1;
7675 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7677 for (j = 0; j < RateIdx; j++)
7679 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7681 if (j == ProperMlmeRate)
7693 if (bMatch == FALSE)
7695 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7697 for (j = 0; j < RateIdx; j++)
7699 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7701 if (j == ProperMlmeRate)
7714 if (bMatch == FALSE)
7716 ProperMlmeRate = MinimumRate;
7719 pAd->CommonCfg.MlmeRate = MinimumRate;
7720 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7721 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7723 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7724 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7725 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7726 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7730 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7731 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7732 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7733 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7736 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7740 IN PRTMP_ADAPTER pAd,
7747 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7752 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7754 larger = max(Rssi0, Rssi1);
7757 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7759 larger = max(larger, Rssi2);
7769 // Antenna divesity use GPIO3 and EESK pin for control
7770 // Antenna and EEPROM access are both using EESK pin,
7771 // Therefor we should avoid accessing EESK at the same time
7772 // Then restore antenna after EEPROM access
7774 IN PRTMP_ADAPTER pAd,
7781 if ((pAd->EepromAccess) ||
7782 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
7783 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
7784 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
7785 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
7790 // the antenna selection is through firmware and MAC register(GPIO3)
7794 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
7796 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
7798 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
7800 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
7801 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
7806 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
7808 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
7810 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
7813 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
7814 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
7821 ========================================================================
7822 Routine Description:
7823 Periodic evaluate antenna link status
7826 pAd - Adapter pointer
7831 ========================================================================
7833 VOID AsicEvaluateRxAnt(
7834 IN PRTMP_ADAPTER pAd)
7838 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7839 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7840 fRTMP_ADAPTER_RADIO_OFF |
7841 fRTMP_ADAPTER_NIC_NOT_EXIST |
7842 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
7843 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
7845 || (pAd->EepromAccess)
7852 //if (pAd->StaCfg.Psm == PWR_SAVE)
7856 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
7857 // one is antenna diversity:there is only one antenna can rx and tx
7858 // the other is failed antenna remove:two physical antenna can rx and tx
7859 if (pAd->NicConfig2.field.AntDiversity)
7861 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
7862 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
7864 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
7866 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
7867 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
7868 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
7870 // a one-shot timer to end the evalution
7871 // dynamic adjust antenna evaluation period according to the traffic
7872 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7873 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
7875 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7879 if (pAd->StaCfg.Psm == PWR_SAVE)
7882 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7884 if(pAd->Antenna.field.RxPath == 3)
7888 else if(pAd->Antenna.field.RxPath == 2)
7892 else if(pAd->Antenna.field.RxPath == 1)
7896 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7898 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7901 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7902 pAd->RalinkCounters.OneSecTxRetryOkCount +
7903 pAd->RalinkCounters.OneSecTxFailCount;
7905 // dynamic adjust antenna evaluation period according to the traffic
7906 if (TxTotalCnt > 50)
7908 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7909 pAd->Mlme.bLowThroughput = FALSE;
7913 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7914 pAd->Mlme.bLowThroughput = TRUE;
7921 ========================================================================
7922 Routine Description:
7923 After evaluation, check antenna link status
7926 pAd - Adapter pointer
7931 ========================================================================
7933 VOID AsicRxAntEvalTimeout(
7934 IN PVOID SystemSpecific1,
7935 IN PVOID FunctionContext,
7936 IN PVOID SystemSpecific2,
7937 IN PVOID SystemSpecific3)
7939 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7941 CHAR larger = -127, rssi0, rssi1, rssi2;
7943 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7944 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7945 fRTMP_ADAPTER_RADIO_OFF |
7946 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
7947 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
7949 || (pAd->EepromAccess)
7955 //if (pAd->StaCfg.Psm == PWR_SAVE)
7958 if (pAd->NicConfig2.field.AntDiversity)
7960 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
7965 // select PrimaryRxAntPair
7966 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
7967 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
7969 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
7970 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
7971 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
7973 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
7974 pAd->RxAnt.EvaluateStableCnt = 0;
7978 // if the evaluated antenna is not better than original, switch back to original antenna
7979 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
7980 pAd->RxAnt.EvaluateStableCnt ++;
7983 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
7985 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
7986 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
7990 if (pAd->StaCfg.Psm == PWR_SAVE)
7993 // if the traffic is low, use average rssi as the criteria
7994 if (pAd->Mlme.bLowThroughput == TRUE)
7996 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7997 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7998 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8002 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8003 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8004 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8007 if(pAd->Antenna.field.RxPath == 3)
8009 larger = max(rssi0, rssi1);
8011 if (larger > (rssi2 + 20))
8012 pAd->Mlme.RealRxPath = 2;
8014 pAd->Mlme.RealRxPath = 3;
8016 else if(pAd->Antenna.field.RxPath == 2)
8018 if (rssi0 > (rssi1 + 20))
8019 pAd->Mlme.RealRxPath = 1;
8021 pAd->Mlme.RealRxPath = 2;
8024 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8026 if(pAd->Mlme.RealRxPath == 3)
8030 else if(pAd->Mlme.RealRxPath == 2)
8034 else if(pAd->Mlme.RealRxPath == 1)
8038 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8045 VOID APSDPeriodicExec(
8046 IN PVOID SystemSpecific1,
8047 IN PVOID FunctionContext,
8048 IN PVOID SystemSpecific2,
8049 IN PVOID SystemSpecific3)
8051 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8053 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8056 pAd->CommonCfg.TriggerTimerCount++;
8058 // Driver should not send trigger frame, it should be send by application layer
8060 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8061 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8062 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8064 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8065 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8066 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8067 pAd->CommonCfg.TriggerTimerCount = 0;
8068 pAd->CommonCfg.bInServicePeriod = TRUE;
8073 ========================================================================
8074 Routine Description:
8075 Set/reset MAC registers according to bPiggyBack parameter
8078 pAd - Adapter pointer
8079 bPiggyBack - Enable / Disable Piggy-Back
8084 ========================================================================
8086 VOID RTMPSetPiggyBack(
8087 IN PRTMP_ADAPTER pAd,
8088 IN BOOLEAN bPiggyBack)
8090 TX_LINK_CFG_STRUC TxLinkCfg;
8092 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8094 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8095 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8099 ========================================================================
8100 Routine Description:
8101 check if this entry need to switch rate automatically
8111 ========================================================================
8113 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8114 IN PRTMP_ADAPTER pAd,
8115 IN PMAC_TABLE_ENTRY pEntry)
8117 BOOLEAN result = TRUE;
8120 // only associated STA counts
8121 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8123 result = pAd->StaCfg.bAutoTxRateSwitch;
8133 BOOLEAN RTMPAutoRateSwitchCheck(
8134 IN PRTMP_ADAPTER pAd)
8136 if (pAd->StaCfg.bAutoTxRateSwitch)
8144 ========================================================================
8145 Routine Description:
8146 check if this entry need to fix tx legacy rate
8156 ========================================================================
8158 UCHAR RTMPStaFixedTxMode(
8159 IN PRTMP_ADAPTER pAd,
8160 IN PMAC_TABLE_ENTRY pEntry)
8162 UCHAR tx_mode = FIXED_TXMODE_HT;
8165 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8172 ========================================================================
8173 Routine Description:
8174 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8184 ========================================================================
8186 VOID RTMPUpdateLegacyTxSetting(
8187 UCHAR fixed_tx_mode,
8188 PMAC_TABLE_ENTRY pEntry)
8190 HTTRANSMIT_SETTING TransmitSetting;
8192 if (fixed_tx_mode == FIXED_TXMODE_HT)
8195 TransmitSetting.word = 0;
8197 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8198 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8200 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8202 TransmitSetting.field.MODE = MODE_CCK;
8203 // CCK mode allow MCS 0~3
8204 if (TransmitSetting.field.MCS > MCS_3)
8205 TransmitSetting.field.MCS = MCS_3;
8209 TransmitSetting.field.MODE = MODE_OFDM;
8210 // OFDM mode allow MCS 0~7
8211 if (TransmitSetting.field.MCS > MCS_7)
8212 TransmitSetting.field.MCS = MCS_7;
8215 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8217 pEntry->HTPhyMode.word = TransmitSetting.word;
8218 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8219 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8224 ==========================================================================
8226 dynamic tune BBP R66 to find a balance between sensibility and
8229 IRQL = DISPATCH_LEVEL
8231 ==========================================================================
8233 VOID AsicStaBbpTuning(
8234 IN PRTMP_ADAPTER pAd)
8236 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8239 // 2860C did not support Fase CCA, therefore can't tune
8240 if (pAd->MACVersion == 0x28600100)
8246 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8249 if ((pAd->OpMode == OPMODE_STA)
8250 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8252 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8255 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8258 if (pAd->Antenna.field.RxPath > 1)
8259 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8261 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8263 if (pAd->LatchRfRegs.Channel <= 14)
8266 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8267 // Otherwise, it will have some throughput side effect when low RSSI
8270 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8272 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8273 if (OrigR66Value != R66)
8275 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8280 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8281 if (OrigR66Value != R66)
8283 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8290 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8292 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8293 if (OrigR66Value != R66)
8295 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8300 R66 = 0x2E + GET_LNA_GAIN(pAd);
8301 if (OrigR66Value != R66)
8303 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8311 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8313 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8315 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8316 if (OrigR66Value != R66)
8318 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8323 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8324 if (OrigR66Value != R66)
8326 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8332 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8334 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8335 if (OrigR66Value != R66)
8337 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8342 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8343 if (OrigR66Value != R66)
8345 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8355 VOID RTMPSetAGCInitValue(
8356 IN PRTMP_ADAPTER pAd,
8361 if (pAd->LatchRfRegs.Channel <= 14)
8363 R66 = 0x2E + GET_LNA_GAIN(pAd);
8364 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8368 if (BandWidth == BW_20)
8370 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8371 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8375 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8376 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8382 VOID AsicTurnOffRFClk(
8383 IN PRTMP_ADAPTER pAd,
8387 UINT32 R1 = 0, R2 = 0, R3 = 0;
8389 RTMP_RF_REGS *RFRegTable;
8392 // The RF programming sequence is difference between 3xxx and 2xxx
8395 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8400 RFRegTable = RF2850RegTable;
8402 switch (pAd->RfIcType)
8409 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8411 if (Channel == RFRegTable[index].Channel)
8413 R1 = RFRegTable[index].R1 & 0xffffdfff;
8414 R2 = RFRegTable[index].R2 & 0xfffbffff;
8415 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8417 RTMP_RF_IO_WRITE32(pAd, R1);
8418 RTMP_RF_IO_WRITE32(pAd, R2);
8420 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8421 // Set RF R2 bit18=0, R3 bit[18:19]=0
8422 //if (pAd->StaCfg.bRadio == FALSE)
8425 RTMP_RF_IO_WRITE32(pAd, R3);
8427 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8428 Channel, pAd->RfIcType, R2, R3));
8431 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8432 Channel, pAd->RfIcType, R2));
8448 VOID AsicTurnOnRFClk(
8449 IN PRTMP_ADAPTER pAd,
8453 UINT32 R1 = 0, R2 = 0, R3 = 0;
8455 RTMP_RF_REGS *RFRegTable;
8458 // The RF programming sequence is difference between 3xxx and 2xxx
8465 RFRegTable = RF2850RegTable;
8467 switch (pAd->RfIcType)
8474 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8476 if (Channel == RFRegTable[index].Channel)
8478 R3 = pAd->LatchRfRegs.R3;
8481 RTMP_RF_IO_WRITE32(pAd, R3);
8483 R1 = RFRegTable[index].R1;
8484 RTMP_RF_IO_WRITE32(pAd, R1);
8486 R2 = RFRegTable[index].R2;
8487 if (pAd->Antenna.field.TxPath == 1)
8489 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8492 if (pAd->Antenna.field.RxPath == 2)
8494 R2 |= 0x40; // write 1 to off Rxpath.
8496 else if (pAd->Antenna.field.RxPath == 1)
8498 R2 |= 0x20040; // write 1 to off RxPath
8500 RTMP_RF_IO_WRITE32(pAd, R2);