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,
246 0x05, 0x20, 20, 15, 30,
247 0x06, 0x20, 21, 8, 20,
248 0x07, 0x20, 22, 8, 20,
249 0x08, 0x20, 23, 8, 25,
250 0x09, 0x22, 23, 8, 25,
253 UCHAR RateSwitchTable11BGN2SForABand[] = {
254 // 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)
255 0x0b, 0x09, 0, 0, 0, // Initial used item after association
256 0x00, 0x21, 0, 30,101, //50
257 0x01, 0x21, 1, 20, 50,
258 0x02, 0x21, 2, 20, 50,
259 0x03, 0x21, 3, 15, 50,
260 0x04, 0x21, 4, 15, 30,
261 0x05, 0x21, 5, 15, 30,
262 0x06, 0x20, 12, 15, 30,
263 0x07, 0x20, 13, 8, 20,
264 0x08, 0x20, 14, 8, 20,
265 0x09, 0x20, 15, 8, 25,
266 0x0a, 0x22, 15, 8, 25,
269 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
270 // 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)
271 0x0c, 0x09, 0, 0, 0, // Initial used item after association
272 0x00, 0x21, 0, 30,101, //50
273 0x01, 0x21, 1, 20, 50,
274 0x02, 0x21, 2, 20, 50,
275 0x03, 0x21, 3, 15, 50,
276 0x04, 0x21, 4, 15, 30,
277 0x05, 0x21, 5, 15, 30,
278 0x06, 0x21, 12, 15, 30,
279 0x07, 0x20, 20, 15, 30,
280 0x08, 0x20, 21, 8, 20,
281 0x09, 0x20, 22, 8, 20,
282 0x0a, 0x20, 23, 8, 25,
283 0x0b, 0x22, 23, 8, 25,
286 PUCHAR ReasonString[] = {
288 /* 1 */ "Unspecified Reason",
289 /* 2 */ "Previous Auth no longer valid",
290 /* 3 */ "STA is leaving / has left",
291 /* 4 */ "DIS-ASSOC due to inactivity",
292 /* 5 */ "AP unable to hanle all associations",
293 /* 6 */ "class 2 error",
294 /* 7 */ "class 3 error",
295 /* 8 */ "STA is leaving / has left",
296 /* 9 */ "require auth before assoc/re-assoc",
300 /* 13 */ "invalid IE",
301 /* 14 */ "MIC error",
302 /* 15 */ "4-way handshake timeout",
303 /* 16 */ "2-way (group key) handshake timeout",
304 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
308 extern UCHAR OfdmRateToRxwiMCS[];
309 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
310 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
311 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
312 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
313 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
315 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
316 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
317 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
319 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
320 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
321 // clean environment.
322 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
323 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
325 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
326 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
328 UCHAR SsidIe = IE_SSID;
329 UCHAR SupRateIe = IE_SUPP_RATES;
330 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
331 UCHAR HtCapIe = IE_HT_CAP;
332 UCHAR AddHtInfoIe = IE_ADD_HT;
333 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
334 UCHAR ErpIe = IE_ERP;
335 UCHAR DsIe = IE_DS_PARM;
336 UCHAR TimIe = IE_TIM;
337 UCHAR WpaIe = IE_WPA;
338 UCHAR Wpa2Ie = IE_WPA2;
339 UCHAR IbssIe = IE_IBSS_PARM;
340 UCHAR Ccx2Ie = IE_CCX_V2;
341 UCHAR WapiIe = IE_WAPI;
343 extern UCHAR WPA_OUI[];
345 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
347 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
348 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
350 // Reset the RFIC setting to new series
351 RTMP_RF_REGS RF2850RegTable[] = {
352 // ch R1 R2 R3(TX0~4=0) R4
353 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
354 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
355 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
356 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
357 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
358 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
359 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
360 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
361 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
362 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
363 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
364 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
365 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
366 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
368 // 802.11 UNI / HyperLan 2
369 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
370 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
371 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
372 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
373 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
374 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
375 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
376 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
377 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
378 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
379 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
380 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
383 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
385 // 2008.04.30 modified
386 // The system team has AN to improve the EVM value
387 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
388 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
389 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
390 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
392 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
393 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
394 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
395 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
396 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
397 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
398 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
399 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
400 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
401 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
402 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
403 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
406 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
407 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
408 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
409 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
410 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
411 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
412 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
415 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
416 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
417 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
418 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
419 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
420 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
421 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
423 // still lack of MMAC(Japan) ch 34,38,42,46
425 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
427 FREQUENCY_ITEM FreqItems3020[] =
429 /**************************************************/
430 // ISM : 2.4 to 2.483 GHz //
431 /**************************************************/
433 /**************************************************/
434 //-CH---N-------R---K-----------
451 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
454 //2008/07/10:KH Modified to share this variable
455 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
459 ==========================================================================
461 initialize the MLME task and its data structure (queue, spinlock,
462 timer, state machines).
467 always return NDIS_STATUS_SUCCESS
469 ==========================================================================
471 NDIS_STATUS MlmeInit(
472 IN PRTMP_ADAPTER pAd)
474 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
476 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
480 Status = MlmeQueueInit(&pAd->Mlme.Queue);
481 if(Status != NDIS_STATUS_SUCCESS)
484 pAd->Mlme.bRunning = FALSE;
485 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
488 BssTableInit(&pAd->ScanTab);
490 // init STA state machines
491 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
492 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
493 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
494 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
495 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
496 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
498 // Since we are using switch/case to implement it, the init is different from the above
499 // state machine init
500 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
503 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
505 // Init mlme periodic timer
506 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
508 // Set mlme periodic timer
509 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
511 // software-based RX Antenna diversity
512 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
516 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
522 ==========================================================================
524 main loop of the MLME
526 Mlme has to be initialized, and there are something inside the queue
528 This function is invoked from MPSetInformation and MPReceive;
529 This task guarantee only one MlmeHandler will run.
531 IRQL = DISPATCH_LEVEL
533 ==========================================================================
536 IN PRTMP_ADAPTER pAd)
538 MLME_QUEUE_ELEM *Elem = NULL;
540 // Only accept MLME and Frame from peer side, no other (control/data) frame should
541 // get into this state machine
543 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
544 if(pAd->Mlme.bRunning)
546 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
551 pAd->Mlme.bRunning = TRUE;
553 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
555 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
557 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
558 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
559 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
561 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
565 //From message type, determine which state machine I should drive
566 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
569 if (Elem->MsgType == MT2_RESET_CONF)
571 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
572 MlmeRestartStateMachine(pAd);
573 Elem->Occupied = FALSE;
579 // if dequeue success
580 switch (Elem->Machine)
582 // STA state machines
583 case ASSOC_STATE_MACHINE:
584 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
586 case AUTH_STATE_MACHINE:
587 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
589 case AUTH_RSP_STATE_MACHINE:
590 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
592 case SYNC_STATE_MACHINE:
593 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
595 case MLME_CNTL_STATE_MACHINE:
596 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
598 case WPA_PSK_STATE_MACHINE:
599 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
601 case AIRONET_STATE_MACHINE:
602 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
604 case ACTION_STATE_MACHINE:
605 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
612 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
617 Elem->Occupied = FALSE;
622 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
626 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
627 pAd->Mlme.bRunning = FALSE;
628 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
632 ==========================================================================
634 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
636 Adapter - NIC Adapter pointer
638 The MLME task will no longer work properly
642 ==========================================================================
645 IN PRTMP_ADAPTER pAd)
649 UINT32 TxPinCfg = 0x00050F0F;
652 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
654 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
656 // disable BEACON generation and other BEACON related hardware timers
657 AsicDisableSync(pAd);
661 // Cancel pending timers
662 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
663 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
664 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
665 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
666 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
667 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
670 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
671 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
675 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
678 RTMPSetLED(pAd, LED_HALT);
679 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
682 LED_CFG_STRUC LedCfg;
683 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
684 LedCfg.field.LedPolar = 0;
685 LedCfg.field.RLedMode = 0;
686 LedCfg.field.GLedMode = 0;
687 LedCfg.field.YLedMode = 0;
688 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
695 if (IS_RT3070(pAd) || IS_RT3071(pAd))
697 TxPinCfg &= 0xFFFFF0F0;
698 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
703 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
705 MlmeQueueDestroy(&pAd->Mlme.Queue);
706 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
708 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
711 VOID MlmeResetRalinkCounters(
712 IN PRTMP_ADAPTER pAd)
714 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
715 // clear all OneSecxxx counters.
716 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
717 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
718 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
719 pAd->RalinkCounters.OneSecRxOkCnt = 0;
720 pAd->RalinkCounters.OneSecTxFailCount = 0;
721 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
722 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
723 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
725 // TODO: for debug only. to be removed
726 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
727 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
728 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
729 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
730 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
731 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
732 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
733 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
734 pAd->RalinkCounters.OneSecTxDoneCount = 0;
735 pAd->RalinkCounters.OneSecRxCount = 0;
736 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
737 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
742 unsigned long rx_AMSDU;
743 unsigned long rx_Total;
746 ==========================================================================
748 This routine is executed periodically to -
749 1. Decide if it's a right time to turn on PwrMgmt bit of all
751 2. Calculate ChannelQuality based on statistics of the last
752 period, so that TX rate won't toggling very frequently between a
753 successful TX and a failed TX.
754 3. If the calculated ChannelQuality indicated current connection not
755 healthy, then a ROAMing attempt is tried here.
757 IRQL = DISPATCH_LEVEL
759 ==========================================================================
761 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
762 VOID MlmePeriodicExec(
763 IN PVOID SystemSpecific1,
764 IN PVOID FunctionContext,
765 IN PVOID SystemSpecific2,
766 IN PVOID SystemSpecific3)
769 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
771 // Do nothing if the driver is starting halt state.
772 // This might happen when timer already been fired before cancel timer with mlmehalt
773 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
774 fRTMP_ADAPTER_RADIO_OFF |
775 fRTMP_ADAPTER_RADIO_MEASUREMENT |
776 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
779 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
782 // Do nothing if monitor mode is on
786 if (pAd->Mlme.PeriodicRound & 0x1)
788 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
789 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
790 (STA_TGN_WIFI_ON(pAd)) &&
791 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
794 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
795 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
797 else if ((STA_TGN_WIFI_ON(pAd)) &&
798 ((pAd->MACVersion & 0xffff) == 0x0101))
800 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
801 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
806 pAd->bUpdateBcnCntDone = FALSE;
808 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
809 pAd->Mlme.PeriodicRound ++;
812 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
813 NICUpdateFifoStaCounters(pAd);
815 // execute every 500ms
816 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
818 // perform dynamic tx rate switching based on past TX history
820 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
822 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
823 MlmeDynamicTxRateSwitching(pAd);
827 // Normal 1 second Mlme PeriodicExec.
828 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
830 pAd->Mlme.OneSecPeriodicRound ++;
840 // Media status changed, report to NDIS
841 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
843 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
844 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
846 pAd->IndicateMediaState = NdisMediaStateConnected;
847 RTMP_IndicateMediaState(pAd);
852 pAd->IndicateMediaState = NdisMediaStateDisconnected;
853 RTMP_IndicateMediaState(pAd);
857 NdisGetSystemUpTime(&pAd->Mlme.Now32);
859 // add the most up-to-date h/w raw counters into software variable, so that
860 // the dynamic tuning mechanism below are based on most up-to-date information
861 NICUpdateRawCounters(pAd);
864 RT2870_WatchDog(pAd);
867 // Need statistics after read counter. So put after NICUpdateRawCounters
868 ORIBATimerTimeout(pAd);
871 // The time period for checking antenna is according to traffic
872 if (pAd->Mlme.bEnableAutoAntennaCheck)
874 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
875 pAd->RalinkCounters.OneSecTxRetryOkCount +
876 pAd->RalinkCounters.OneSecTxFailCount;
878 // dynamic adjust antenna evaluation period according to the traffic
881 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
883 AsicEvaluateRxAnt(pAd);
888 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
890 AsicEvaluateRxAnt(pAd);
895 STAMlmePeriodicExec(pAd);
897 MlmeResetRalinkCounters(pAd);
901 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
902 // and sending CTS-to-self over and over.
903 // Software Patch Solution:
904 // 1. Polling debug state register 0x10F4 every one second.
905 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
906 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
910 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
911 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
913 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
915 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
917 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
922 RT28XX_MLME_HANDLER(pAd);
926 pAd->bUpdateBcnCntDone = FALSE;
929 VOID STAMlmePeriodicExec(
935 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
937 // WPA MIC error should block association attempt for 60 seconds
938 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
939 pAd->StaCfg.bBlockAssoc = FALSE;
942 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
944 if (pAd->IndicateMediaState == NdisMediaStateConnected)
946 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
948 pAd->PreMediaState = pAd->IndicateMediaState;
954 AsicStaBbpTuning(pAd);
956 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
957 pAd->RalinkCounters.OneSecTxRetryOkCount +
958 pAd->RalinkCounters.OneSecTxFailCount;
960 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
962 // update channel quality for Roaming and UI LinkQuality display
963 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
966 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
967 // Radio is currently in noisy environment
968 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
969 AsicAdjustTxPower(pAd);
973 // Is PSM bit consistent with user power management policy?
974 // This is the only place that will set PSM bit ON.
975 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
976 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
978 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
980 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
981 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
982 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
984 RTMPSetAGCInitValue(pAd, BW_20);
985 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
989 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
991 // When APSD is enabled, the period changes as 20 sec
992 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
993 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
997 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
998 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1000 if (pAd->CommonCfg.bWmmCapable)
1001 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1003 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1008 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1010 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1011 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1012 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1014 // Lost AP, send disconnect & link down event
1015 LinkDown(pAd, FALSE);
1018 union iwreq_data wrqu;
1019 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1020 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1023 MlmeAutoReconnectLastSSID(pAd);
1025 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1027 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1028 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1029 MlmeAutoReconnectLastSSID(pAd);
1032 // Add auto seamless roaming
1033 if (pAd->StaCfg.bFastRoaming)
1035 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1037 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));
1039 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1041 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1045 else if (ADHOC_ON(pAd))
1048 if ((pAd->CommonCfg.Channel > 14)
1049 && (pAd->CommonCfg.bIEEE80211H == 1)
1050 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1052 RadarDetectPeriodic(pAd);
1055 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1056 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1058 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1059 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1061 MLME_START_REQ_STRUCT StartReq;
1063 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1064 LinkDown(pAd, FALSE);
1066 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1067 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1068 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1071 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1073 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1075 if (pEntry->ValidAsCLI == FALSE)
1078 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1079 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1082 else // no INFRA nor ADHOC connection
1085 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1086 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1087 goto SKIP_AUTO_SCAN_CONN;
1089 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1091 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1092 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1093 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1095 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1097 MLME_SCAN_REQ_STRUCT ScanReq;
1099 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1101 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1102 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1103 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1104 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1105 // Reset Missed scan number
1106 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1108 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1109 MlmeAutoReconnectLastSSID(pAd);
1111 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1113 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1116 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1120 MlmeAutoReconnectLastSSID(pAd);
1126 SKIP_AUTO_SCAN_CONN:
1128 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1130 pAd->MacTab.fAnyBASession = TRUE;
1131 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1133 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1135 pAd->MacTab.fAnyBASession = FALSE;
1136 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1144 IN PVOID SystemSpecific1,
1145 IN PVOID FunctionContext,
1146 IN PVOID SystemSpecific2,
1147 IN PVOID SystemSpecific3)
1150 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1152 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1153 RTMP_IndicateMediaState(pAd);
1154 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1157 // IRQL = DISPATCH_LEVEL
1159 IN PRTMP_ADAPTER pAd)
1161 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1162 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1164 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1166 MLME_CNTL_STATE_MACHINE,
1167 OID_802_11_BSSID_LIST_SCAN,
1170 RT28XX_MLME_HANDLER(pAd);
1174 // IRQL = DISPATCH_LEVEL
1175 VOID MlmeAutoReconnectLastSSID(
1176 IN PRTMP_ADAPTER pAd)
1180 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1181 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1182 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1184 NDIS_802_11_SSID OidSsid;
1185 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1186 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1188 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1190 MLME_CNTL_STATE_MACHINE,
1192 sizeof(NDIS_802_11_SSID),
1194 RT28XX_MLME_HANDLER(pAd);
1199 ==========================================================================
1200 Validate SSID for connection try and rescan purpose
1201 Valid SSID will have visible chars only.
1202 The valid length is from 0 to 32.
1203 IRQL = DISPATCH_LEVEL
1204 ==========================================================================
1206 BOOLEAN MlmeValidateSSID(
1212 if (SsidLen > MAX_LEN_OF_SSID)
1215 // Check each character value
1216 for (index = 0; index < SsidLen; index++)
1218 if (pSsid[index] < 0x20)
1226 VOID MlmeSelectTxRateTable(
1227 IN PRTMP_ADAPTER pAd,
1228 IN PMAC_TABLE_ENTRY pEntry,
1230 IN PUCHAR pTableSize,
1231 IN PUCHAR pInitTxRateIdx)
1235 // decide the rate table for tuning
1236 if (pAd->CommonCfg.TxRateTableSize > 0)
1238 *ppTable = RateSwitchTable;
1239 *pTableSize = RateSwitchTable[0];
1240 *pInitTxRateIdx = RateSwitchTable[1];
1245 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1247 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1248 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1249 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1251 *ppTable = RateSwitchTable11N1S;
1252 *pTableSize = RateSwitchTable11N1S[0];
1253 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1256 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1257 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1258 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1259 (pAd->Antenna.field.TxPath == 2))
1261 if (pAd->LatchRfRegs.Channel <= 14)
1263 *ppTable = RateSwitchTable11N2S;
1264 *pTableSize = RateSwitchTable11N2S[0];
1265 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1269 *ppTable = RateSwitchTable11N2SForABand;
1270 *pTableSize = RateSwitchTable11N2SForABand[0];
1271 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1276 if ((pEntry->RateLen == 4)
1277 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1280 *ppTable = RateSwitchTable11B;
1281 *pTableSize = RateSwitchTable11B[0];
1282 *pInitTxRateIdx = RateSwitchTable11B[1];
1285 else if (pAd->LatchRfRegs.Channel <= 14)
1287 *ppTable = RateSwitchTable11BG;
1288 *pTableSize = RateSwitchTable11BG[0];
1289 *pInitTxRateIdx = RateSwitchTable11BG[1];
1294 *ppTable = RateSwitchTable11G;
1295 *pTableSize = RateSwitchTable11G[0];
1296 *pInitTxRateIdx = RateSwitchTable11G[1];
1302 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1303 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1305 *ppTable = RateSwitchTable11BGN1S;
1306 *pTableSize = RateSwitchTable11BGN1S[0];
1307 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1312 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1313 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1315 if (pAd->LatchRfRegs.Channel <= 14)
1317 *ppTable = RateSwitchTable11BGN2S;
1318 *pTableSize = RateSwitchTable11BGN2S[0];
1319 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1324 *ppTable = RateSwitchTable11BGN2SForABand;
1325 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1326 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1332 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1334 *ppTable = RateSwitchTable11N1S;
1335 *pTableSize = RateSwitchTable11N1S[0];
1336 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1341 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1343 if (pAd->LatchRfRegs.Channel <= 14)
1345 *ppTable = RateSwitchTable11N2S;
1346 *pTableSize = RateSwitchTable11N2S[0];
1347 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1351 *ppTable = RateSwitchTable11N2SForABand;
1352 *pTableSize = RateSwitchTable11N2SForABand[0];
1353 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1359 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1360 if ((pEntry->RateLen == 4)
1362 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1363 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1367 *ppTable = RateSwitchTable11B;
1368 *pTableSize = RateSwitchTable11B[0];
1369 *pInitTxRateIdx = RateSwitchTable11B[1];
1374 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1375 if ((pEntry->RateLen > 8)
1376 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1379 *ppTable = RateSwitchTable11BG;
1380 *pTableSize = RateSwitchTable11BG[0];
1381 *pInitTxRateIdx = RateSwitchTable11BG[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 = RateSwitchTable11G;
1392 *pTableSize = RateSwitchTable11G[0];
1393 *pInitTxRateIdx = RateSwitchTable11G[1];
1399 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1400 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1402 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1404 *ppTable = RateSwitchTable11B;
1405 *pTableSize = RateSwitchTable11B[0];
1406 *pInitTxRateIdx = RateSwitchTable11B[1];
1408 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1410 *ppTable = RateSwitchTable11G;
1411 *pTableSize = RateSwitchTable11G[0];
1412 *pInitTxRateIdx = RateSwitchTable11G[1];
1417 *ppTable = RateSwitchTable11BG;
1418 *pTableSize = RateSwitchTable11BG[0];
1419 *pInitTxRateIdx = RateSwitchTable11BG[1];
1424 if (pAd->LatchRfRegs.Channel <= 14)
1426 if (pAd->CommonCfg.TxStream == 1)
1428 *ppTable = RateSwitchTable11N1S;
1429 *pTableSize = RateSwitchTable11N1S[0];
1430 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1431 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1435 *ppTable = RateSwitchTable11N2S;
1436 *pTableSize = RateSwitchTable11N2S[0];
1437 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1438 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1443 if (pAd->CommonCfg.TxStream == 1)
1445 *ppTable = RateSwitchTable11N1S;
1446 *pTableSize = RateSwitchTable11N1S[0];
1447 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1448 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1452 *ppTable = RateSwitchTable11N2SForABand;
1453 *pTableSize = RateSwitchTable11N2SForABand[0];
1454 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1455 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1459 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1460 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1466 ==========================================================================
1468 This routine checks if there're other APs out there capable for
1469 roaming. Caller should call this routine only when Link up in INFRA mode
1470 and channel quality is below CQI_GOOD_THRESHOLD.
1472 IRQL = DISPATCH_LEVEL
1475 ==========================================================================
1477 VOID MlmeCheckForRoaming(
1478 IN PRTMP_ADAPTER pAd,
1482 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1485 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1486 // put all roaming candidates into RoamTab, and sort in RSSI order
1487 BssTableInit(pRoamTab);
1488 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1490 pBss = &pAd->ScanTab.BssEntry[i];
1492 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1493 continue; // AP disappear
1494 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1495 continue; // RSSI too weak. forget it.
1496 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1497 continue; // skip current AP
1498 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1499 continue; // only AP with stronger RSSI is eligible for roaming
1501 // AP passing all above rules is put into roaming candidate table
1502 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1503 pRoamTab->BssNr += 1;
1506 if (pRoamTab->BssNr > 0)
1508 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1509 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1511 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1512 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1513 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1514 RT28XX_MLME_HANDLER(pAd);
1517 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1521 ==========================================================================
1523 This routine checks if there're other APs out there capable for
1524 roaming. Caller should call this routine only when link up in INFRA mode
1525 and channel quality is below CQI_GOOD_THRESHOLD.
1527 IRQL = DISPATCH_LEVEL
1530 ==========================================================================
1532 VOID MlmeCheckForFastRoaming(
1533 IN PRTMP_ADAPTER pAd,
1537 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1540 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1541 // put all roaming candidates into RoamTab, and sort in RSSI order
1542 BssTableInit(pRoamTab);
1543 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1545 pBss = &pAd->ScanTab.BssEntry[i];
1547 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1548 continue; // RSSI too weak. forget it.
1549 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1550 continue; // skip current AP
1551 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1552 continue; // skip different SSID
1553 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1554 continue; // skip AP without better RSSI
1556 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));
1557 // AP passing all above rules is put into roaming candidate table
1558 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1559 pRoamTab->BssNr += 1;
1562 if (pRoamTab->BssNr > 0)
1564 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1565 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1567 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1568 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1569 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1570 RT28XX_MLME_HANDLER(pAd);
1573 // Maybe site survey required
1576 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1578 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1579 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1580 pAd->StaCfg.ScanCnt = 2;
1581 pAd->StaCfg.LastScanTime = Now;
1586 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1590 ==========================================================================
1592 This routine calculates TxPER, RxPER of the past N-sec period. And
1593 according to the calculation result, ChannelQuality is calculated here
1594 to decide if current AP is still doing the job.
1596 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1598 StaCfg.ChannelQuality - 0..100
1600 IRQL = DISPATCH_LEVEL
1602 NOTE: This routine decide channle quality based on RX CRC error ratio.
1603 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1604 is performed right before this routine, so that this routine can decide
1605 channel quality based on the most up-to-date information
1606 ==========================================================================
1608 VOID MlmeCalculateChannelQuality(
1609 IN PRTMP_ADAPTER pAd,
1612 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1616 ULONG BeaconLostTime = BEACON_LOST_TIME;
1618 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1621 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1623 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1624 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1632 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1633 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1637 // calculate RX PER - don't take RxPER into consideration if too few sample
1639 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1643 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1646 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1648 if (INFRA_ON(pAd) &&
1649 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1650 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1652 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1653 pAd->Mlme.ChannelQuality = 0;
1660 else if (MaxRssi < -90)
1663 NorRssi = (MaxRssi + 90) * 2;
1665 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1666 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1667 TX_WEIGHTING * (100 - TxPRR) +
1668 RX_WEIGHTING* (100 - RxPER)) / 100;
1669 if (pAd->Mlme.ChannelQuality >= 100)
1670 pAd->Mlme.ChannelQuality = 100;
1676 IN PRTMP_ADAPTER pAd,
1677 IN PMAC_TABLE_ENTRY pEntry,
1678 IN PRTMP_TX_RATE_SWITCH pTxRate)
1680 UCHAR MaxMode = MODE_OFDM;
1682 MaxMode = MODE_HTGREENFIELD;
1684 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1685 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1687 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1689 if (pTxRate->CurrMCS < MCS_AUTO)
1690 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1692 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1693 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1697 // If peer adhoc is b-only mode, we can't send 11g rate.
1698 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1699 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1702 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1704 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1705 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1706 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1708 // Patch speed error in status page
1709 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1713 if (pTxRate->Mode <= MaxMode)
1714 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1716 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1717 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1719 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1721 // Reexam each bandwidth's SGI support.
1722 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1724 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1725 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1726 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1727 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1730 // Turn RTS/CTS rate to 6Mbps.
1731 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1733 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1734 if (pAd->MacTab.fAnyBASession)
1736 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1740 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1743 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
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 != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1757 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1760 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1762 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1765 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1766 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1767 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1768 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1770 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1771 pAd->WIFItestbed.bGreenField)
1772 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1775 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1779 ==========================================================================
1781 This routine calculates the acumulated TxPER of eaxh TxRate. And
1782 according to the calculation result, change CommonCfg.TxRate which
1783 is the stable TX Rate we expect the Radio situation could sustained.
1785 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1789 IRQL = DISPATCH_LEVEL
1792 call this routine every second
1793 ==========================================================================
1795 VOID MlmeDynamicTxRateSwitching(
1796 IN PRTMP_ADAPTER pAd)
1798 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1799 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1800 ULONG TxErrorRatio = 0;
1801 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1802 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1804 UCHAR TableSize = 0;
1805 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1806 CHAR Rssi, RssiOffset = 0;
1807 TX_STA_CNT1_STRUC StaTx1;
1808 TX_STA_CNT0_STRUC TxStaCnt0;
1809 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1810 MAC_TABLE_ENTRY *pEntry;
1813 // walk through MAC table, see if need to change AP's TX rate toward each entry
1815 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1817 pEntry = &pAd->MacTab.Content[i];
1819 // check if this entry need to switch rate automatically
1820 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1823 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1825 Rssi = RTMPMaxRssi(pAd,
1826 pAd->StaCfg.RssiSample.AvgRssi0,
1827 pAd->StaCfg.RssiSample.AvgRssi1,
1828 pAd->StaCfg.RssiSample.AvgRssi2);
1830 // Update statistic counter
1831 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1832 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1833 pAd->bUpdateBcnCntDone = TRUE;
1834 TxRetransmit = StaTx1.field.TxRetransmit;
1835 TxSuccess = StaTx1.field.TxSuccess;
1836 TxFailCount = TxStaCnt0.field.TxFailCount;
1837 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1839 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1840 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1841 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1842 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1843 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1844 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1846 // if no traffic in the past 1-sec period, don't change TX rate,
1847 // but clear all bad history. because the bad history may affect the next
1848 // Chariot throughput test
1849 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1850 pAd->RalinkCounters.OneSecTxRetryOkCount +
1851 pAd->RalinkCounters.OneSecTxFailCount;
1854 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1858 if (INFRA_ON(pAd) && (i == 1))
1859 Rssi = RTMPMaxRssi(pAd,
1860 pAd->StaCfg.RssiSample.AvgRssi0,
1861 pAd->StaCfg.RssiSample.AvgRssi1,
1862 pAd->StaCfg.RssiSample.AvgRssi2);
1864 Rssi = RTMPMaxRssi(pAd,
1865 pEntry->RssiSample.AvgRssi0,
1866 pEntry->RssiSample.AvgRssi1,
1867 pEntry->RssiSample.AvgRssi2);
1869 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1870 pEntry->OneSecTxRetryOkCount +
1871 pEntry->OneSecTxFailCount;
1874 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1877 CurrRateIdx = pEntry->CurrTxRateIndex;
1879 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1881 if (CurrRateIdx >= TableSize)
1883 CurrRateIdx = TableSize - 1;
1886 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1887 // So need to sync here.
1888 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1889 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1890 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1894 // Need to sync Real Tx rate and our record.
1895 // Then return for next DRS.
1896 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1897 pEntry->CurrTxRateIndex = InitTxRateIdx;
1898 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1900 // reset all OneSecTx counters
1901 RESET_ONE_SEC_TX_CNT(pEntry);
1905 // decide the next upgrade rate and downgrade rate, if any
1906 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
1908 UpRateIdx = CurrRateIdx + 1;
1909 DownRateIdx = CurrRateIdx -1;
1911 else if (CurrRateIdx == 0)
1913 UpRateIdx = CurrRateIdx + 1;
1914 DownRateIdx = CurrRateIdx;
1916 else if (CurrRateIdx == (TableSize - 1))
1918 UpRateIdx = CurrRateIdx;
1919 DownRateIdx = CurrRateIdx - 1;
1922 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1924 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
1926 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
1927 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
1931 TrainUp = pCurrTxRate->TrainUp;
1932 TrainDown = pCurrTxRate->TrainDown;
1935 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
1938 // Keep the last time TxRateChangeAction status.
1940 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
1945 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
1946 // (criteria copied from RT2500 for Netopia case)
1948 if (TxTotalCnt <= 15)
1952 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1953 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
1954 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1955 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
1957 // check the existence and index of each needed MCS
1958 while (idx < pTable[0])
1960 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
1962 if (pCurrTxRate->CurrMCS == MCS_0)
1966 else if (pCurrTxRate->CurrMCS == MCS_1)
1970 else if (pCurrTxRate->CurrMCS == MCS_2)
1974 else if (pCurrTxRate->CurrMCS == MCS_3)
1978 else if (pCurrTxRate->CurrMCS == MCS_4)
1982 else if (pCurrTxRate->CurrMCS == MCS_5)
1986 else if (pCurrTxRate->CurrMCS == MCS_6)
1990 //else if (pCurrTxRate->CurrMCS == MCS_7)
1991 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
1995 else if (pCurrTxRate->CurrMCS == MCS_12)
1999 else if (pCurrTxRate->CurrMCS == MCS_13)
2003 else if (pCurrTxRate->CurrMCS == MCS_14)
2007 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
2011 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2015 else if (pCurrTxRate->CurrMCS == MCS_21)
2019 else if (pCurrTxRate->CurrMCS == MCS_22)
2023 else if (pCurrTxRate->CurrMCS == MCS_23)
2030 if (pAd->LatchRfRegs.Channel <= 14)
2032 if (pAd->NicConfig2.field.ExternalLNAForG)
2043 if (pAd->NicConfig2.field.ExternalLNAForA)
2054 if ((pTable == RateSwitchTable11BGN3S) ||
2055 (pTable == RateSwitchTable11N3S) ||
2056 (pTable == RateSwitchTable))
2057 {// N mode with 3 stream // 3*3
2058 if (MCS23 && (Rssi >= -70))
2060 else if (MCS22 && (Rssi >= -72))
2062 else if (MCS21 && (Rssi >= -76))
2064 else if (MCS20 && (Rssi >= -78))
2066 else if (MCS4 && (Rssi >= -82))
2068 else if (MCS3 && (Rssi >= -84))
2070 else if (MCS2 && (Rssi >= -86))
2072 else if (MCS1 && (Rssi >= -88))
2077 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2078 {// N mode with 2 stream
2079 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2081 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2083 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2085 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2087 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2089 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2091 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2093 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2098 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2099 {// N mode with 1 stream
2100 if (MCS7 && (Rssi > (-72+RssiOffset)))
2102 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2104 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2106 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2108 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2110 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2112 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2119 if (MCS7 && (Rssi > -70))
2121 else if (MCS6 && (Rssi > -74))
2123 else if (MCS5 && (Rssi > -78))
2125 else if (MCS4 && (Rssi > -82))
2127 else if (MCS4 == 0) // for B-only mode
2129 else if (MCS3 && (Rssi > -85))
2131 else if (MCS2 && (Rssi > -87))
2133 else if (MCS1 && (Rssi > -90))
2140 pEntry->CurrTxRateIndex = TxRateIdx;
2141 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2142 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2145 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2146 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2147 pEntry->fLastSecAccordingRSSI = TRUE;
2148 // reset all OneSecTx counters
2149 RESET_ONE_SEC_TX_CNT(pEntry);
2154 if (pEntry->fLastSecAccordingRSSI == TRUE)
2156 pEntry->fLastSecAccordingRSSI = FALSE;
2157 pEntry->LastSecTxRateChangeAction = 0;
2158 // reset all OneSecTx counters
2159 RESET_ONE_SEC_TX_CNT(pEntry);
2166 BOOLEAN bTrainUpDown = FALSE;
2168 pEntry->CurrTxRateStableTime ++;
2170 // downgrade TX quality if PER >= Rate-Down threshold
2171 if (TxErrorRatio >= TrainDown)
2173 bTrainUpDown = TRUE;
2174 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2176 // upgrade TX quality if PER <= Rate-Up threshold
2177 else if (TxErrorRatio <= TrainUp)
2179 bTrainUpDown = TRUE;
2180 bUpgradeQuality = TRUE;
2181 if (pEntry->TxQuality[CurrRateIdx])
2182 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2184 if (pEntry->TxRateUpPenalty)
2185 pEntry->TxRateUpPenalty --;
2186 else if (pEntry->TxQuality[UpRateIdx])
2187 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2190 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2194 // perform DRS - consider TxRate Down first, then rate up.
2195 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2197 pEntry->CurrTxRateIndex = DownRateIdx;
2199 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2201 pEntry->CurrTxRateIndex = UpRateIdx;
2206 // if rate-up happen, clear all bad history of all TX rates
2207 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2209 pEntry->CurrTxRateStableTime = 0;
2210 pEntry->TxRateUpPenalty = 0;
2211 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2212 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2213 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2216 // For TxRate fast train up
2218 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2220 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2222 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2224 bTxRateChanged = TRUE;
2226 // if rate-down happen, only clear DownRate's bad history
2227 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2229 pEntry->CurrTxRateStableTime = 0;
2230 pEntry->TxRateUpPenalty = 0; // no penalty
2231 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2232 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2233 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2236 // For TxRate fast train down
2238 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2240 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2242 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2244 bTxRateChanged = TRUE;
2248 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2249 bTxRateChanged = FALSE;
2252 pEntry->LastTxOkCount = TxSuccess;
2254 // reset all OneSecTx counters
2255 RESET_ONE_SEC_TX_CNT(pEntry);
2257 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2258 if (bTxRateChanged && pNextTxRate)
2260 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2266 ========================================================================
2267 Routine Description:
2268 Station side, Auto TxRate faster train up timer call back function.
2271 SystemSpecific1 - Not used.
2272 FunctionContext - Pointer to our Adapter context.
2273 SystemSpecific2 - Not used.
2274 SystemSpecific3 - Not used.
2279 ========================================================================
2281 VOID StaQuickResponeForRateUpExec(
2282 IN PVOID SystemSpecific1,
2283 IN PVOID FunctionContext,
2284 IN PVOID SystemSpecific2,
2285 IN PVOID SystemSpecific3)
2287 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2288 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2290 ULONG TxErrorRatio = 0;
2291 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2292 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2294 UCHAR TableSize = 0;
2295 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2296 TX_STA_CNT1_STRUC StaTx1;
2297 TX_STA_CNT0_STRUC TxStaCnt0;
2299 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2300 MAC_TABLE_ENTRY *pEntry;
2303 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2306 // walk through MAC table, see if need to change AP's TX rate toward each entry
2308 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2310 pEntry = &pAd->MacTab.Content[i];
2312 // check if this entry need to switch rate automatically
2313 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2316 if (INFRA_ON(pAd) && (i == 1))
2317 Rssi = RTMPMaxRssi(pAd,
2318 pAd->StaCfg.RssiSample.AvgRssi0,
2319 pAd->StaCfg.RssiSample.AvgRssi1,
2320 pAd->StaCfg.RssiSample.AvgRssi2);
2322 Rssi = RTMPMaxRssi(pAd,
2323 pEntry->RssiSample.AvgRssi0,
2324 pEntry->RssiSample.AvgRssi1,
2325 pEntry->RssiSample.AvgRssi2);
2327 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2329 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2331 // decide the next upgrade rate and downgrade rate, if any
2332 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2334 UpRateIdx = CurrRateIdx + 1;
2335 DownRateIdx = CurrRateIdx -1;
2337 else if (CurrRateIdx == 0)
2339 UpRateIdx = CurrRateIdx + 1;
2340 DownRateIdx = CurrRateIdx;
2342 else if (CurrRateIdx == (TableSize - 1))
2344 UpRateIdx = CurrRateIdx;
2345 DownRateIdx = CurrRateIdx - 1;
2348 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2350 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2352 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2353 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2357 TrainUp = pCurrTxRate->TrainUp;
2358 TrainDown = pCurrTxRate->TrainDown;
2361 if (pAd->MacTab.Size == 1)
2363 // Update statistic counter
2364 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2365 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2367 TxRetransmit = StaTx1.field.TxRetransmit;
2368 TxSuccess = StaTx1.field.TxSuccess;
2369 TxFailCount = TxStaCnt0.field.TxFailCount;
2370 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2372 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2373 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2374 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2375 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2376 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2377 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2380 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2384 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2385 pEntry->OneSecTxRetryOkCount +
2386 pEntry->OneSecTxFailCount;
2389 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2394 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2395 // (criteria copied from RT2500 for Netopia case)
2397 if (TxTotalCnt <= 12)
2399 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2400 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2402 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2404 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2405 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2407 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2409 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2412 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2418 ULONG OneSecTxNoRetryOKRationCount;
2420 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2425 // downgrade TX quality if PER >= Rate-Down threshold
2426 if (TxErrorRatio >= TrainDown)
2428 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2431 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2433 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2435 // perform DRS - consider TxRate Down first, then rate up.
2436 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2438 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2440 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2441 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2446 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2448 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2452 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2454 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2459 // if rate-up happen, clear all bad history of all TX rates
2460 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2462 pAd->DrsCounters.TxRateUpPenalty = 0;
2463 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2464 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2465 bTxRateChanged = TRUE;
2467 // if rate-down happen, only clear DownRate's bad history
2468 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2470 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2472 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2473 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2474 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2475 bTxRateChanged = TRUE;
2479 bTxRateChanged = FALSE;
2482 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2483 if (bTxRateChanged && pNextTxRate)
2485 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2491 ==========================================================================
2493 This routine is executed periodically inside MlmePeriodicExec() after
2494 association with an AP.
2495 It checks if StaCfg.Psm is consistent with user policy (recorded in
2496 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2497 there're some conditions to consider:
2498 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2499 the time when Mibss==TRUE
2500 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2501 if outgoing traffic available in TxRing or MgmtRing.
2503 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2505 IRQL = DISPATCH_LEVEL
2507 ==========================================================================
2509 VOID MlmeCheckPsmChange(
2510 IN PRTMP_ADAPTER pAd,
2516 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2517 // 2. user wants either MAX_PSP or FAST_PSP
2518 // 3. but current psm is not in PWR_SAVE
2519 // 4. CNTL state machine is not doing SCANning
2520 // 5. no TX SUCCESS event for the past 1-sec period
2521 #ifdef NDIS51_MINIPORT
2522 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2523 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2526 PowerMode = pAd->StaCfg.WindowsPowerMode;
2528 if (INFRA_ON(pAd) &&
2529 (PowerMode != Ndis802_11PowerModeCAM) &&
2530 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2532 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2534 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2535 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2536 MlmeSetPsmBit(pAd, PWR_SAVE);
2537 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2539 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2543 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2548 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2549 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2550 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2551 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2553 // add by johnli, use Rx OK data count per second to calculate throughput
2554 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2555 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2556 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2558 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2560 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2561 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2563 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2565 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2568 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2569 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2570 MlmeSetPsmBit(pAd, PWR_SAVE);
2571 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2573 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2577 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2584 // IRQL = PASSIVE_LEVEL
2585 // IRQL = DISPATCH_LEVEL
2587 IN PRTMP_ADAPTER pAd,
2590 AUTO_RSP_CFG_STRUC csr4;
2592 pAd->StaCfg.Psm = psm;
2593 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2594 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2595 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2597 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2601 // IRQL = DISPATCH_LEVEL
2602 VOID MlmeSetTxPreamble(
2603 IN PRTMP_ADAPTER pAd,
2604 IN USHORT TxPreamble)
2606 AUTO_RSP_CFG_STRUC csr4;
2609 // Always use Long preamble before verifiation short preamble functionality works well.
2610 // Todo: remove the following line if short preamble functionality works
2612 //TxPreamble = Rt802_11PreambleLong;
2614 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2615 if (TxPreamble == Rt802_11PreambleLong)
2617 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2618 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2619 csr4.field.AutoResponderPreamble = 0;
2623 // NOTE: 1Mbps should always use long preamble
2624 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2625 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2626 csr4.field.AutoResponderPreamble = 1;
2629 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2633 ==========================================================================
2635 Update basic rate bitmap
2636 ==========================================================================
2639 VOID UpdateBasicRateBitmap(
2640 IN PRTMP_ADAPTER pAdapter)
2643 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2644 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2645 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2646 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2647 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2650 /* if A mode, always use fix BasicRateBitMap */
2651 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2652 if (pAdapter->CommonCfg.Channel > 14)
2653 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2656 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2658 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2662 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2668 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2670 if (bitmap & (1 << i))
2672 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2674 if (sup_p[j] == rate[i])
2679 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2681 if (ext_p[j] == rate[i])
2687 } /* End of UpdateBasicRateBitmap */
2689 // IRQL = PASSIVE_LEVEL
2690 // IRQL = DISPATCH_LEVEL
2691 // bLinkUp is to identify the inital link speed.
2692 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2693 VOID MlmeUpdateTxRates(
2694 IN PRTMP_ADAPTER pAd,
2699 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2700 UCHAR MinSupport = RATE_54;
2701 ULONG BasicRateBitmap = 0;
2702 UCHAR CurrBasicRate = RATE_1;
2703 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2704 PHTTRANSMIT_SETTING pHtPhy = NULL;
2705 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2706 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2707 BOOLEAN *auto_rate_cur_p;
2708 UCHAR HtMcs = MCS_AUTO;
2710 // find max desired rate
2711 UpdateBasicRateBitmap(pAd);
2714 auto_rate_cur_p = NULL;
2715 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2717 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2719 case 2: Rate = RATE_1; num++; break;
2720 case 4: Rate = RATE_2; num++; break;
2721 case 11: Rate = RATE_5_5; num++; break;
2722 case 22: Rate = RATE_11; num++; break;
2723 case 12: Rate = RATE_6; num++; break;
2724 case 18: Rate = RATE_9; num++; break;
2725 case 24: Rate = RATE_12; num++; break;
2726 case 36: Rate = RATE_18; num++; break;
2727 case 48: Rate = RATE_24; num++; break;
2728 case 72: Rate = RATE_36; num++; break;
2729 case 96: Rate = RATE_48; num++; break;
2730 case 108: Rate = RATE_54; num++; break;
2731 //default: Rate = RATE_1; break;
2733 if (MaxDesire < Rate) MaxDesire = Rate;
2736 //===========================================================================
2737 //===========================================================================
2739 pHtPhy = &pAd->StaCfg.HTPhyMode;
2740 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2741 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2743 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2744 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2746 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2747 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2748 (MaxDesire > RATE_11))
2750 MaxDesire = RATE_11;
2754 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2755 pMinHtPhy->word = 0;
2756 pMaxHtPhy->word = 0;
2759 // Auto rate switching is enabled only if more than one DESIRED RATES are
2760 // specified; otherwise disabled
2763 *auto_rate_cur_p = FALSE;
2767 *auto_rate_cur_p = TRUE;
2771 if (HtMcs != MCS_AUTO)
2773 *auto_rate_cur_p = FALSE;
2777 *auto_rate_cur_p = TRUE;
2781 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2783 pSupRate = &pAd->StaActive.SupRate[0];
2784 pExtRate = &pAd->StaActive.ExtRate[0];
2785 SupRateLen = pAd->StaActive.SupRateLen;
2786 ExtRateLen = pAd->StaActive.ExtRateLen;
2790 pSupRate = &pAd->CommonCfg.SupRate[0];
2791 pExtRate = &pAd->CommonCfg.ExtRate[0];
2792 SupRateLen = pAd->CommonCfg.SupRateLen;
2793 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2796 // find max supported rate
2797 for (i=0; i<SupRateLen; i++)
2799 switch (pSupRate[i] & 0x7f)
2801 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2802 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2803 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2804 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2805 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2806 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2807 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2808 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2809 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2810 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2811 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2812 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2813 default: Rate = RATE_1; break;
2815 if (MaxSupport < Rate) MaxSupport = Rate;
2817 if (MinSupport > Rate) MinSupport = Rate;
2820 for (i=0; i<ExtRateLen; i++)
2822 switch (pExtRate[i] & 0x7f)
2824 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2825 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2826 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2827 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2828 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2829 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2830 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2831 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2832 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2833 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2834 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2835 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2836 default: Rate = RATE_1; break;
2838 if (MaxSupport < Rate) MaxSupport = Rate;
2840 if (MinSupport > Rate) MinSupport = Rate;
2843 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2845 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2846 // the DURATION field of outgoing uniicast DATA/MGMT frame
2847 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2849 if (BasicRateBitmap & (0x01 << i))
2850 CurrBasicRate = (UCHAR)i;
2851 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2854 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2855 // max tx rate = min {max desire rate, max supported rate}
2856 if (MaxSupport < MaxDesire)
2857 pAd->CommonCfg.MaxTxRate = MaxSupport;
2859 pAd->CommonCfg.MaxTxRate = MaxDesire;
2861 pAd->CommonCfg.MinTxRate = MinSupport;
2862 if (*auto_rate_cur_p)
2866 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2868 if (bLinkUp == TRUE)
2869 pAd->CommonCfg.TxRate = RATE_24;
2871 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2874 pAd->CommonCfg.TxRate = RATE_11;
2876 pAd->CommonCfg.TxRate = RATE_24;
2878 // should never exceed MaxTxRate (consider 11B-only mode)
2879 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2880 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2882 pAd->CommonCfg.TxRateIndex = 0;
2886 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2887 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2888 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2890 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2891 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2892 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2893 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
2896 if (pAd->CommonCfg.TxRate <= RATE_11)
2898 pMaxHtPhy->field.MODE = MODE_CCK;
2899 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
2900 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
2904 pMaxHtPhy->field.MODE = MODE_OFDM;
2905 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
2906 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
2907 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
2909 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
2912 pHtPhy->word = (pMaxHtPhy->word);
2913 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
2915 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
2916 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
2917 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
2921 switch (pAd->CommonCfg.PhyMode)
2923 case PHY_11BG_MIXED:
2925 case PHY_11BGN_MIXED:
2926 pAd->CommonCfg.MlmeRate = RATE_1;
2927 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2928 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2930 pAd->CommonCfg.RtsRate = RATE_11;
2934 case PHY_11AGN_MIXED:
2935 case PHY_11GN_MIXED:
2937 case PHY_11AN_MIXED:
2939 pAd->CommonCfg.MlmeRate = RATE_6;
2940 pAd->CommonCfg.RtsRate = RATE_6;
2941 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2942 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2944 case PHY_11ABG_MIXED:
2945 case PHY_11ABGN_MIXED:
2946 if (pAd->CommonCfg.Channel <= 14)
2948 pAd->CommonCfg.MlmeRate = RATE_1;
2949 pAd->CommonCfg.RtsRate = RATE_1;
2950 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2951 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2955 pAd->CommonCfg.MlmeRate = RATE_6;
2956 pAd->CommonCfg.RtsRate = RATE_6;
2957 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2958 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2962 pAd->CommonCfg.MlmeRate = RATE_6;
2963 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2964 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2965 pAd->CommonCfg.RtsRate = RATE_1;
2969 // Keep Basic Mlme Rate.
2971 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
2972 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
2973 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
2975 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
2976 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
2979 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
2980 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
2981 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
2982 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
2983 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
2984 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
2985 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 ));
2989 ==========================================================================
2991 This function update HT Rate setting.
2992 Input Wcid value is valid for 2 case :
2993 1. it's used for Station in infra mode that copy AP rate to Mactable.
2994 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
2996 IRQL = DISPATCH_LEVEL
2998 ==========================================================================
3000 VOID MlmeUpdateHtTxRates(
3001 IN PRTMP_ADAPTER pAd,
3004 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3006 RT_HT_CAPABILITY *pRtHtCap = NULL;
3007 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3010 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3011 PHTTRANSMIT_SETTING pHtPhy = NULL;
3012 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3013 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3014 BOOLEAN *auto_rate_cur_p;
3016 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3018 auto_rate_cur_p = NULL;
3021 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3022 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3023 pHtPhy = &pAd->StaCfg.HTPhyMode;
3024 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3025 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3027 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3030 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3032 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3035 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3036 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3037 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3038 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3039 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3040 pMaxHtPhy->field.STBC = STBC_USE;
3042 pMaxHtPhy->field.STBC = STBC_NONE;
3046 if (pDesireHtPhy->bHtEnable == FALSE)
3049 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3050 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3051 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.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;
3058 // Decide MAX ht rate.
3059 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3060 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3062 pMaxHtPhy->field.MODE = MODE_HTMIX;
3064 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3065 pMaxHtPhy->field.BW = BW_40;
3067 pMaxHtPhy->field.BW = BW_20;
3069 if (pMaxHtPhy->field.BW == BW_20)
3070 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3072 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3074 for (i=23; i>=0; i--) // 3*3
3077 bitmask = (1<<(i-(j*8)));
3079 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3081 pMaxHtPhy->field.MCS = i;
3089 // Copy MIN ht rate. rt2860???
3090 pMinHtPhy->field.BW = BW_20;
3091 pMinHtPhy->field.MCS = 0;
3092 pMinHtPhy->field.STBC = 0;
3093 pMinHtPhy->field.ShortGI = 0;
3094 //If STA assigns fixed rate. update to fixed here.
3095 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3097 if (pDesireHtPhy->MCSSet[4] != 0)
3099 pMaxHtPhy->field.MCS = 32;
3100 pMinHtPhy->field.MCS = 32;
3101 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3104 for (i=23; (CHAR)i >= 0; i--) // 3*3
3107 bitmask = (1<<(i-(j*8)));
3108 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3110 pMaxHtPhy->field.MCS = i;
3111 pMinHtPhy->field.MCS = i;
3120 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3121 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3122 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3123 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3124 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3126 // use default now. rt2860
3127 if (pDesireHtPhy->MCSSet[0] != 0xff)
3128 *auto_rate_cur_p = FALSE;
3130 *auto_rate_cur_p = TRUE;
3132 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3133 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3134 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3135 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3138 // IRQL = DISPATCH_LEVEL
3140 IN PRTMP_ADAPTER pAd)
3142 RT28XX_MLME_RADIO_OFF(pAd);
3145 // IRQL = DISPATCH_LEVEL
3147 IN PRTMP_ADAPTER pAd)
3149 RT28XX_MLME_RADIO_ON(pAd);
3152 // ===========================================================================================
3154 // ===========================================================================================
3157 /*! \brief initialize BSS table
3158 * \param p_tab pointer to the table
3163 IRQL = PASSIVE_LEVEL
3164 IRQL = DISPATCH_LEVEL
3173 Tab->BssOverlapNr = 0;
3174 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3176 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3177 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3182 IN PRTMP_ADAPTER pAd,
3187 Tab->numAsOriginator = 0;
3188 Tab->numAsRecipient = 0;
3189 NdisAllocateSpinLock(&pAd->BATabLock);
3190 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3192 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3193 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3195 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3197 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3201 /*! \brief search the BSS table by SSID
3202 * \param p_tab pointer to the bss table
3203 * \param ssid SSID string
3204 * \return index of the table, BSS_NOT_FOUND if not in the table
3207 * \note search by sequential search
3209 IRQL = DISPATCH_LEVEL
3212 ULONG BssTableSearch(
3219 for (i = 0; i < Tab->BssNr; i++)
3222 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3223 // We should distinguish this case.
3225 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3226 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3227 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3232 return (ULONG)BSS_NOT_FOUND;
3235 ULONG BssSsidTableSearch(
3244 for (i = 0; i < Tab->BssNr; i++)
3247 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3248 // We should distinguish this case.
3250 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3251 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3252 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3253 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3258 return (ULONG)BSS_NOT_FOUND;
3261 ULONG BssTableSearchWithSSID(
3270 for (i = 0; i < Tab->BssNr; i++)
3272 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3273 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3274 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3275 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3276 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3277 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3282 return (ULONG)BSS_NOT_FOUND;
3285 // IRQL = DISPATCH_LEVEL
3286 VOID BssTableDeleteEntry(
3287 IN OUT BSS_TABLE *Tab,
3293 for (i = 0; i < Tab->BssNr; i++)
3295 if ((Tab->BssEntry[i].Channel == Channel) &&
3296 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3298 for (j = i; j < Tab->BssNr - 1; j++)
3300 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3302 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3310 ========================================================================
3311 Routine Description:
3312 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3315 // IRQL = DISPATCH_LEVEL
3316 ========================================================================
3318 VOID BATableDeleteORIEntry(
3319 IN OUT PRTMP_ADAPTER pAd,
3320 IN BA_ORI_ENTRY *pBAORIEntry)
3323 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3325 NdisAcquireSpinLock(&pAd->BATabLock);
3326 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3328 pAd->BATable.numAsOriginator -= 1;
3329 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3330 // Erase Bitmap flag.
3332 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3333 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3334 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3335 pBAORIEntry->Token = 1;
3336 // Not clear Sequence here.
3337 NdisReleaseSpinLock(&pAd->BATabLock);
3347 IRQL = DISPATCH_LEVEL
3351 IN PRTMP_ADAPTER pAd,
3352 OUT BSS_ENTRY *pBss,
3357 IN USHORT BeaconPeriod,
3358 IN PCF_PARM pCfParm,
3360 IN USHORT CapabilityInfo,
3362 IN UCHAR SupRateLen,
3364 IN UCHAR ExtRateLen,
3365 IN HT_CAPABILITY_IE *pHtCapability,
3366 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3367 IN UCHAR HtCapabilityLen,
3368 IN UCHAR AddHtInfoLen,
3369 IN UCHAR NewExtChanOffset,
3372 IN LARGE_INTEGER TimeStamp,
3374 IN PEDCA_PARM pEdcaParm,
3375 IN PQOS_CAPABILITY_PARM pQosCapability,
3376 IN PQBSS_LOAD_PARM pQbssLoad,
3377 IN USHORT LengthVIE,
3378 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3380 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3381 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3385 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3386 // Or send beacon /probe response with SSID len matching real SSID length,
3387 // but SSID is all zero. such as "00-00-00-00" with length 4.
3388 // We have to prevent this case overwrite correct table
3389 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3391 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3392 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3393 pBss->SsidLen = SsidLen;
3399 pBss->BssType = BssType;
3400 pBss->BeaconPeriod = BeaconPeriod;
3401 if (BssType == BSS_INFRA)
3403 if (pCfParm->bValid)
3405 pBss->CfpCount = pCfParm->CfpCount;
3406 pBss->CfpPeriod = pCfParm->CfpPeriod;
3407 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3408 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3413 pBss->AtimWin = AtimWin;
3416 pBss->CapabilityInfo = CapabilityInfo;
3417 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3418 // Combine with AuthMode, they will decide the connection methods.
3419 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3420 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3421 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3422 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3424 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3425 pBss->SupRateLen = SupRateLen;
3426 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3427 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3428 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3429 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3430 pBss->NewExtChanOffset = NewExtChanOffset;
3431 pBss->ExtRateLen = ExtRateLen;
3432 pBss->Channel = Channel;
3433 pBss->CentralChannel = Channel;
3435 // Update CkipFlag. if not exists, the value is 0x0
3436 pBss->CkipFlag = CkipFlag;
3438 // New for microsoft Fixed IEs
3439 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3440 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3441 pBss->FixIEs.Capabilities = CapabilityInfo;
3443 // New for microsoft Variable IEs
3446 pBss->VarIELen = LengthVIE;
3447 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3454 pBss->AddHtInfoLen = 0;
3455 pBss->HtCapabilityLen = 0;
3457 if (HtCapabilityLen> 0)
3459 pBss->HtCapabilityLen = HtCapabilityLen;
3460 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3461 if (AddHtInfoLen > 0)
3463 pBss->AddHtInfoLen = AddHtInfoLen;
3464 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3466 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3468 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3470 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3472 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3477 BssCipherParse(pBss);
3481 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3483 pBss->EdcaParm.bValid = FALSE;
3485 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3487 pBss->QosCapability.bValid = FALSE;
3489 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3491 pBss->QbssLoad.bValid = FALSE;
3498 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3499 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3501 pEid = (PEID_STRUCT) pVIE;
3503 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3508 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3510 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3512 pBss->WpaIE.IELen = 0;
3515 pBss->WpaIE.IELen = pEid->Len + 2;
3516 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3520 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3522 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3524 pBss->RsnIE.IELen = 0;
3527 pBss->RsnIE.IELen = pEid->Len + 2;
3528 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3532 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3533 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3539 * \brief insert an entry into the bss table
3540 * \param p_tab The BSS table
3541 * \param Bssid BSSID
3543 * \param ssid_len Length of SSID
3545 * \param beacon_period
3552 * \param channel_idx
3556 * \note If SSID is identical, the old entry will be replaced by the new one
3558 IRQL = DISPATCH_LEVEL
3561 ULONG BssTableSetEntry(
3562 IN PRTMP_ADAPTER pAd,
3568 IN USHORT BeaconPeriod,
3571 IN USHORT CapabilityInfo,
3573 IN UCHAR SupRateLen,
3575 IN UCHAR ExtRateLen,
3576 IN HT_CAPABILITY_IE *pHtCapability,
3577 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3578 IN UCHAR HtCapabilityLen,
3579 IN UCHAR AddHtInfoLen,
3580 IN UCHAR NewExtChanOffset,
3583 IN LARGE_INTEGER TimeStamp,
3585 IN PEDCA_PARM pEdcaParm,
3586 IN PQOS_CAPABILITY_PARM pQosCapability,
3587 IN PQBSS_LOAD_PARM pQbssLoad,
3588 IN USHORT LengthVIE,
3589 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3593 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3594 if (Idx == BSS_NOT_FOUND)
3596 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3599 // It may happen when BSS Table was full.
3600 // The desired AP will not be added into BSS Table
3601 // In this case, if we found the desired AP then overwrite BSS Table.
3603 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3605 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3606 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3608 Idx = Tab->BssOverlapNr;
3609 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3610 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3611 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3612 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3618 return BSS_NOT_FOUND;
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);
3630 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3631 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3632 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3635 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3636 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3637 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3639 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3640 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3641 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3649 // IRQL = DISPATCH_LEVEL
3650 VOID BssTableSsidSort(
3651 IN PRTMP_ADAPTER pAd,
3652 OUT BSS_TABLE *OutTab,
3657 BssTableInit(OutTab);
3659 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3661 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3662 BOOLEAN bIsHiddenApIncluded = FALSE;
3664 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3665 (pAd->MlmeAux.Channel > 14) &&
3666 RadarChannelCheck(pAd, pInBss->Channel))
3670 bIsHiddenApIncluded = TRUE;
3673 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3674 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3676 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3678 // 2.4G/5G N only mode
3679 if ((pInBss->HtCapabilityLen == 0) &&
3680 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3682 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3687 // Check the Authmode first
3688 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3690 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3691 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3695 // Check cipher suite, AP must have more secured cipher than station setting
3696 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3698 // If it's not mixed mode, we should only let BSS pass with the same encryption
3699 if (pInBss->WPA.bMixMode == FALSE)
3700 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3703 // check group cipher
3705 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3706 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3707 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3710 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3714 // check pairwise cipher, skip if none matched
3715 // If profile set to AES, let it pass without question.
3716 // If profile set to TKIP, we must find one mateched
3717 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3718 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3719 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3722 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3724 // If it's not mixed mode, we should only let BSS pass with the same encryption
3725 if (pInBss->WPA2.bMixMode == FALSE)
3726 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3729 // check group cipher
3731 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3732 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3733 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3736 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3740 // check pairwise cipher, skip if none matched
3741 // If profile set to AES, let it pass without question.
3742 // If profile set to TKIP, we must find one mateched
3743 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3744 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3745 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3749 // Bss Type matched, SSID matched.
3750 // We will check wepstatus for qualification Bss
3751 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3753 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3755 // For the SESv2 case, we will not qualify WepStatus.
3761 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3762 // It definitely will fail. So, skip it.
3763 // CCX also require not even try to connect it!!
3767 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3768 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3769 if ((pInBss->CentralChannel != pInBss->Channel) &&
3770 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3772 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3774 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3776 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3780 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3787 // copy matching BSS from InTab to OutTab
3788 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3792 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3794 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3796 // 2.4G/5G N only mode
3797 if ((pInBss->HtCapabilityLen == 0) &&
3798 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3800 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3805 // Check the Authmode first
3806 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3808 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3809 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3813 // Check cipher suite, AP must have more secured cipher than station setting
3814 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3816 // If it's not mixed mode, we should only let BSS pass with the same encryption
3817 if (pInBss->WPA.bMixMode == FALSE)
3818 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3821 // check group cipher
3822 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3825 // check pairwise cipher, skip if none matched
3826 // If profile set to AES, let it pass without question.
3827 // If profile set to TKIP, we must find one mateched
3828 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3829 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3830 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3833 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3835 // If it's not mixed mode, we should only let BSS pass with the same encryption
3836 if (pInBss->WPA2.bMixMode == FALSE)
3837 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3840 // check group cipher
3841 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3844 // check pairwise cipher, skip if none matched
3845 // If profile set to AES, let it pass without question.
3846 // If profile set to TKIP, we must find one mateched
3847 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3848 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3849 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3853 // Bss Type matched, SSID matched.
3854 // We will check wepstatus for qualification Bss
3855 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3858 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3859 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3860 if ((pInBss->CentralChannel != pInBss->Channel) &&
3861 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3863 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3865 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3867 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3871 // copy matching BSS from InTab to OutTab
3872 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3877 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3881 BssTableSortByRssi(OutTab);
3885 // IRQL = DISPATCH_LEVEL
3886 VOID BssTableSortByRssi(
3887 IN OUT BSS_TABLE *OutTab)
3892 for (i = 0; i < OutTab->BssNr - 1; i++)
3894 for (j = i+1; j < OutTab->BssNr; j++)
3896 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
3898 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
3899 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
3900 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
3906 VOID BssCipherParse(
3907 IN OUT PBSS_ENTRY pBss)
3911 PRSN_IE_HEADER_STRUCT pRsnHeader;
3912 PCIPHER_SUITE_STRUCT pCipher;
3913 PAKM_SUITE_STRUCT pAKM;
3916 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
3919 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
3923 pBss->WepStatus = Ndis802_11WEPEnabled;
3927 pBss->WepStatus = Ndis802_11WEPDisabled;
3929 // Set default to disable & open authentication before parsing variable IE
3930 pBss->AuthMode = Ndis802_11AuthModeOpen;
3931 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
3934 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
3935 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
3936 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
3937 pBss->WPA.RsnCapability = 0;
3938 pBss->WPA.bMixMode = FALSE;
3940 // Init WPA2 setting
3941 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
3942 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
3943 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
3944 pBss->WPA2.RsnCapability = 0;
3945 pBss->WPA2.bMixMode = FALSE;
3948 Length = (INT) pBss->VarIELen;
3952 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
3953 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
3954 pEid = (PEID_STRUCT) pTmp;
3958 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
3959 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
3965 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3966 pBss->WepStatus = Ndis802_11Encryption1Enabled;
3967 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3968 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3971 pBss->WepStatus = Ndis802_11Encryption2Enabled;
3972 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3973 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3976 pBss->WepStatus = Ndis802_11Encryption3Enabled;
3977 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3978 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3984 // if Cisco IE_WPA, break
3987 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
3992 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
3994 // if unsupported vendor specific IE
3997 // Skip OUI, version, and multicast suite
3998 // This part should be improved in the future when AP supported multiple cipher suite.
3999 // For now, it's OK since almost all APs have fixed cipher suite supported.
4000 // pTmp = (PUCHAR) pEid->Octet;
4003 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4011 // Parse group cipher
4016 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4019 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4022 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4023 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4027 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4030 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4035 // number of unicast suite
4038 // skip all unicast cipher suites
4039 //Count = *(PUSHORT) pTmp;
4040 Count = (pTmp[1]<<8) + pTmp[0];
4041 pTmp += sizeof(USHORT);
4043 // Parsing all unicast cipher suite
4048 TmpCipher = Ndis802_11WEPDisabled;
4052 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4053 TmpCipher = Ndis802_11Encryption1Enabled;
4056 TmpCipher = Ndis802_11Encryption2Enabled;
4059 TmpCipher = Ndis802_11Encryption3Enabled;
4064 if (TmpCipher > pBss->WPA.PairCipher)
4066 // Move the lower cipher suite to PairCipherAux
4067 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4068 pBss->WPA.PairCipher = TmpCipher;
4072 pBss->WPA.PairCipherAux = TmpCipher;
4078 // 4. get AKM suite counts
4079 //Count = *(PUSHORT) pTmp;
4080 Count = (pTmp[1]<<8) + pTmp[0];
4081 pTmp += sizeof(USHORT);
4087 // Set AP support WPA mode
4088 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4089 pBss->AuthMode = Ndis802_11AuthModeWPA;
4091 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4094 // Set AP support WPA mode
4095 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4096 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4098 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4105 // Fixed for WPA-None
4106 if (pBss->BssType == BSS_ADHOC)
4108 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4109 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4110 pBss->WepStatus = pBss->WPA.GroupCipher;
4111 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4112 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4115 pBss->WepStatus = pBss->WPA.PairCipher;
4117 // Check the Pair & Group, if different, turn on mixed mode flag
4118 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4119 pBss->WPA.bMixMode = TRUE;
4124 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4126 // 0. Version must be 1
4127 if (le2cpu16(pRsnHeader->Version) != 1)
4129 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4131 // 1. Check group cipher
4132 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4133 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4136 // Parse group cipher
4137 switch (pCipher->Type)
4141 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4144 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4147 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4148 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4152 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4155 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4160 // set to correct offset for next parsing
4161 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4163 // 2. Get pairwise cipher counts
4164 //Count = *(PUSHORT) pTmp;
4165 Count = (pTmp[1]<<8) + pTmp[0];
4166 pTmp += sizeof(USHORT);
4168 // 3. Get pairwise cipher
4169 // Parsing all unicast cipher suite
4173 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4174 TmpCipher = Ndis802_11WEPDisabled;
4175 switch (pCipher->Type)
4178 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4179 TmpCipher = Ndis802_11Encryption1Enabled;
4182 TmpCipher = Ndis802_11Encryption2Enabled;
4185 TmpCipher = Ndis802_11Encryption3Enabled;
4190 if (TmpCipher > pBss->WPA2.PairCipher)
4192 // Move the lower cipher suite to PairCipherAux
4193 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4194 pBss->WPA2.PairCipher = TmpCipher;
4198 pBss->WPA2.PairCipherAux = TmpCipher;
4200 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4204 // 4. get AKM suite counts
4205 //Count = *(PUSHORT) pTmp;
4206 Count = (pTmp[1]<<8) + pTmp[0];
4207 pTmp += sizeof(USHORT);
4209 // 5. Get AKM ciphers
4210 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4211 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4217 // Set AP support WPA mode
4218 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4219 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4221 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4224 // Set AP support WPA mode
4225 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4226 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4228 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4233 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4235 // Fixed for WPA-None
4236 if (pBss->BssType == BSS_ADHOC)
4238 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4239 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4240 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4241 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4242 pBss->WepStatus = pBss->WPA.GroupCipher;
4243 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4244 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4246 pBss->WepStatus = pBss->WPA2.PairCipher;
4248 // 6. Get RSN capability
4249 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4250 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4251 pTmp += sizeof(USHORT);
4253 // Check the Pair & Group, if different, turn on mixed mode flag
4254 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4255 pBss->WPA2.bMixMode = TRUE;
4261 Length -= (pEid->Len + 2);
4265 // ===========================================================================================
4267 // ===========================================================================================
4269 /*! \brief generates a random mac address value for IBSS BSSID
4270 * \param Addr the bssid location
4275 VOID MacAddrRandomBssid(
4276 IN PRTMP_ADAPTER pAd,
4281 for (i = 0; i < MAC_ADDR_LEN; i++)
4283 pAddr[i] = RandomByte(pAd);
4286 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4289 /*! \brief init the management mac frame header
4290 * \param p_hdr mac header
4291 * \param subtype subtype of the frame
4292 * \param p_ds destination address, don't care if it is a broadcast address
4294 * \pre the station has the following information in the pAd->StaCfg
4298 * \note this function initializes the following field
4300 IRQL = PASSIVE_LEVEL
4301 IRQL = DISPATCH_LEVEL
4304 VOID MgtMacHeaderInit(
4305 IN PRTMP_ADAPTER pAd,
4306 IN OUT PHEADER_802_11 pHdr80211,
4312 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4314 pHdr80211->FC.Type = BTYPE_MGMT;
4315 pHdr80211->FC.SubType = SubType;
4316 pHdr80211->FC.ToDs = ToDs;
4317 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4319 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4321 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4324 // ===========================================================================================
4326 // ===========================================================================================
4328 /*!***************************************************************************
4329 * This routine build an outgoing frame, and fill all information specified
4330 * in argument list to the frame body. The actual frame size is the summation
4333 * Buffer - pointer to a pre-allocated memory segment
4334 * args - a list of <int arg_size, arg> pairs.
4335 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4336 * function will FAIL!!!
4338 * Size of the buffer
4340 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4342 IRQL = PASSIVE_LEVEL
4343 IRQL = DISPATCH_LEVEL
4345 ****************************************************************************/
4346 ULONG MakeOutgoingFrame(
4348 OUT ULONG *FrameLen, ...)
4355 // calculates the total length
4357 va_start(Args, FrameLen);
4360 leng = va_arg(Args, int);
4361 if (leng == END_OF_ARGS)
4365 p = va_arg(Args, PVOID);
4366 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4367 TotLeng = TotLeng + leng;
4370 va_end(Args); /* clean up */
4371 *FrameLen = TotLeng;
4375 // ===========================================================================================
4377 // ===========================================================================================
4379 /*! \brief Initialize The MLME Queue, used by MLME Functions
4380 * \param *Queue The MLME Queue
4381 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4384 * \note Because this is done only once (at the init stage), no need to be locked
4386 IRQL = PASSIVE_LEVEL
4389 NDIS_STATUS MlmeQueueInit(
4390 IN MLME_QUEUE *Queue)
4394 NdisAllocateSpinLock(&Queue->Lock);
4400 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4402 Queue->Entry[i].Occupied = FALSE;
4403 Queue->Entry[i].MsgLen = 0;
4404 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4407 return NDIS_STATUS_SUCCESS;
4410 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4411 * \param *Queue The MLME Queue
4412 * \param Machine The State Machine Id
4413 * \param MsgType The Message Type
4414 * \param MsgLen The Message length
4415 * \param *Msg The message pointer
4416 * \return TRUE if enqueue is successful, FALSE if the queue is full
4419 * \note The message has to be initialized
4421 IRQL = PASSIVE_LEVEL
4422 IRQL = DISPATCH_LEVEL
4425 BOOLEAN MlmeEnqueue(
4426 IN PRTMP_ADAPTER pAd,
4433 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4435 // Do nothing if the driver is starting halt state.
4436 // This might happen when timer already been fired before cancel timer with mlmehalt
4437 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4440 // First check the size, it MUST not exceed the mlme queue size
4441 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4443 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4447 if (MlmeQueueFull(Queue))
4452 NdisAcquireSpinLock(&(Queue->Lock));
4456 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4461 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4462 Queue->Entry[Tail].Occupied = TRUE;
4463 Queue->Entry[Tail].Machine = Machine;
4464 Queue->Entry[Tail].MsgType = MsgType;
4465 Queue->Entry[Tail].MsgLen = MsgLen;
4469 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4472 NdisReleaseSpinLock(&(Queue->Lock));
4476 /*! \brief This function is used when Recv gets a MLME message
4477 * \param *Queue The MLME Queue
4478 * \param TimeStampHigh The upper 32 bit of timestamp
4479 * \param TimeStampLow The lower 32 bit of timestamp
4480 * \param Rssi The receiving RSSI strength
4481 * \param MsgLen The length of the message
4482 * \param *Msg The message pointer
4483 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4487 IRQL = DISPATCH_LEVEL
4490 BOOLEAN MlmeEnqueueForRecv(
4491 IN PRTMP_ADAPTER pAd,
4493 IN ULONG TimeStampHigh,
4494 IN ULONG TimeStampLow,
4503 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4505 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4507 // Do nothing if the driver is starting halt state.
4508 // This might happen when timer already been fired before cancel timer with mlmehalt
4509 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4511 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4515 // First check the size, it MUST not exceed the mlme queue size
4516 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4518 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4522 if (MlmeQueueFull(Queue))
4528 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4530 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4535 // OK, we got all the informations, it is time to put things into queue
4536 NdisAcquireSpinLock(&(Queue->Lock));
4540 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4544 Queue->Entry[Tail].Occupied = TRUE;
4545 Queue->Entry[Tail].Machine = Machine;
4546 Queue->Entry[Tail].MsgType = MsgType;
4547 Queue->Entry[Tail].MsgLen = MsgLen;
4548 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4549 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4550 Queue->Entry[Tail].Rssi0 = Rssi0;
4551 Queue->Entry[Tail].Rssi1 = Rssi1;
4552 Queue->Entry[Tail].Rssi2 = Rssi2;
4553 Queue->Entry[Tail].Signal = Signal;
4554 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4556 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4560 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4563 NdisReleaseSpinLock(&(Queue->Lock));
4565 RT28XX_MLME_HANDLER(pAd);
4571 /*! \brief Dequeue a message from the MLME Queue
4572 * \param *Queue The MLME Queue
4573 * \param *Elem The message dequeued from MLME Queue
4574 * \return TRUE if the Elem contains something, FALSE otherwise
4578 IRQL = DISPATCH_LEVEL
4581 BOOLEAN MlmeDequeue(
4582 IN MLME_QUEUE *Queue,
4583 OUT MLME_QUEUE_ELEM **Elem)
4585 NdisAcquireSpinLock(&(Queue->Lock));
4586 *Elem = &(Queue->Entry[Queue->Head]);
4589 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4593 NdisReleaseSpinLock(&(Queue->Lock));
4597 // IRQL = DISPATCH_LEVEL
4598 VOID MlmeRestartStateMachine(
4599 IN PRTMP_ADAPTER pAd)
4603 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4606 // Cancel all timer events
4607 // Be careful to cancel new added timer
4608 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4609 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4610 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4611 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4612 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4613 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4616 // Change back to original channel in case of doing scan
4617 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4618 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4620 // Resume MSDU which is turned off durning scan
4621 RTMPResumeMsduTransmission(pAd);
4624 // Set all state machines back IDLE
4625 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4626 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4627 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4628 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4629 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4630 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4634 /*! \brief test if the MLME Queue is empty
4635 * \param *Queue The MLME Queue
4636 * \return TRUE if the Queue is empty, FALSE otherwise
4640 IRQL = DISPATCH_LEVEL
4643 BOOLEAN MlmeQueueEmpty(
4644 IN MLME_QUEUE *Queue)
4648 NdisAcquireSpinLock(&(Queue->Lock));
4649 Ans = (Queue->Num == 0);
4650 NdisReleaseSpinLock(&(Queue->Lock));
4655 /*! \brief test if the MLME Queue is full
4656 * \param *Queue The MLME Queue
4657 * \return TRUE if the Queue is empty, FALSE otherwise
4661 IRQL = PASSIVE_LEVEL
4662 IRQL = DISPATCH_LEVEL
4665 BOOLEAN MlmeQueueFull(
4666 IN MLME_QUEUE *Queue)
4670 NdisAcquireSpinLock(&(Queue->Lock));
4671 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4672 NdisReleaseSpinLock(&(Queue->Lock));
4677 /*! \brief The destructor of MLME Queue
4682 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4684 IRQL = PASSIVE_LEVEL
4687 VOID MlmeQueueDestroy(
4688 IN MLME_QUEUE *pQueue)
4690 NdisAcquireSpinLock(&(pQueue->Lock));
4694 NdisReleaseSpinLock(&(pQueue->Lock));
4695 NdisFreeSpinLock(&(pQueue->Lock));
4698 /*! \brief To substitute the message type if the message is coming from external
4699 * \param pFrame The frame received
4700 * \param *Machine The state machine
4701 * \param *MsgType the message type for the state machine
4702 * \return TRUE if the substitution is successful, FALSE otherwise
4706 IRQL = DISPATCH_LEVEL
4709 BOOLEAN MsgTypeSubst(
4710 IN PRTMP_ADAPTER pAd,
4711 IN PFRAME_802_11 pFrame,
4719 // Pointer to start of data frames including SNAP header
4720 pData = (PUCHAR) pFrame + LENGTH_802_11;
4722 // The only data type will pass to this function is EAPOL frame
4723 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4725 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4727 // Cisco Aironet SNAP header
4728 *Machine = AIRONET_STATE_MACHINE;
4729 *MsgType = MT2_AIRONET_MSG;
4733 *Machine = WPA_PSK_STATE_MACHINE;
4734 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4735 return(WpaMsgTypeSubst(EAPType, MsgType));
4739 switch (pFrame->Hdr.FC.SubType)
4741 case SUBTYPE_ASSOC_REQ:
4742 *Machine = ASSOC_STATE_MACHINE;
4743 *MsgType = MT2_PEER_ASSOC_REQ;
4745 case SUBTYPE_ASSOC_RSP:
4746 *Machine = ASSOC_STATE_MACHINE;
4747 *MsgType = MT2_PEER_ASSOC_RSP;
4749 case SUBTYPE_REASSOC_REQ:
4750 *Machine = ASSOC_STATE_MACHINE;
4751 *MsgType = MT2_PEER_REASSOC_REQ;
4753 case SUBTYPE_REASSOC_RSP:
4754 *Machine = ASSOC_STATE_MACHINE;
4755 *MsgType = MT2_PEER_REASSOC_RSP;
4757 case SUBTYPE_PROBE_REQ:
4758 *Machine = SYNC_STATE_MACHINE;
4759 *MsgType = MT2_PEER_PROBE_REQ;
4761 case SUBTYPE_PROBE_RSP:
4762 *Machine = SYNC_STATE_MACHINE;
4763 *MsgType = MT2_PEER_PROBE_RSP;
4765 case SUBTYPE_BEACON:
4766 *Machine = SYNC_STATE_MACHINE;
4767 *MsgType = MT2_PEER_BEACON;
4770 *Machine = SYNC_STATE_MACHINE;
4771 *MsgType = MT2_PEER_ATIM;
4773 case SUBTYPE_DISASSOC:
4774 *Machine = ASSOC_STATE_MACHINE;
4775 *MsgType = MT2_PEER_DISASSOC_REQ;
4778 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4779 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4780 if (Seq == 1 || Seq == 3)
4782 *Machine = AUTH_RSP_STATE_MACHINE;
4783 *MsgType = MT2_PEER_AUTH_ODD;
4785 else if (Seq == 2 || Seq == 4)
4787 *Machine = AUTH_STATE_MACHINE;
4788 *MsgType = MT2_PEER_AUTH_EVEN;
4795 case SUBTYPE_DEAUTH:
4796 *Machine = AUTH_RSP_STATE_MACHINE;
4797 *MsgType = MT2_PEER_DEAUTH;
4799 case SUBTYPE_ACTION:
4800 *Machine = ACTION_STATE_MACHINE;
4801 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4802 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4804 *MsgType = MT2_ACT_INVALID;
4808 *MsgType = (pFrame->Octet[0]&0x7F);
4819 // ===========================================================================================
4821 // ===========================================================================================
4823 /*! \brief Initialize the state machine.
4824 * \param *S pointer to the state machine
4825 * \param Trans State machine transition function
4826 * \param StNr number of states
4827 * \param MsgNr number of messages
4828 * \param DefFunc default function, when there is invalid state/message combination
4829 * \param InitState initial state of the state machine
4830 * \param Base StateMachine base, internal use only
4831 * \pre p_sm should be a legal pointer
4834 IRQL = PASSIVE_LEVEL
4837 VOID StateMachineInit(
4838 IN STATE_MACHINE *S,
4839 IN STATE_MACHINE_FUNC Trans[],
4842 IN STATE_MACHINE_FUNC DefFunc,
4848 // set number of states and messages
4853 S->TransFunc = Trans;
4855 // init all state transition to default function
4856 for (i = 0; i < StNr; i++)
4858 for (j = 0; j < MsgNr; j++)
4860 S->TransFunc[i * MsgNr + j] = DefFunc;
4864 // set the starting state
4865 S->CurrState = InitState;
4868 /*! \brief This function fills in the function pointer into the cell in the state machine
4869 * \param *S pointer to the state machine
4871 * \param Msg incoming message
4872 * \param f the function to be executed when (state, message) combination occurs at the state machine
4873 * \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
4876 IRQL = PASSIVE_LEVEL
4879 VOID StateMachineSetAction(
4880 IN STATE_MACHINE *S,
4883 IN STATE_MACHINE_FUNC Func)
4887 MsgIdx = Msg - S->Base;
4889 if (St < S->NrState && MsgIdx < S->NrMsg)
4891 // boundary checking before setting the action
4892 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
4896 /*! \brief This function does the state transition
4897 * \param *Adapter the NIC adapter pointer
4898 * \param *S the state machine
4899 * \param *Elem the message to be executed
4902 IRQL = DISPATCH_LEVEL
4905 VOID StateMachinePerformAction(
4906 IN PRTMP_ADAPTER pAd,
4907 IN STATE_MACHINE *S,
4908 IN MLME_QUEUE_ELEM *Elem)
4910 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
4914 ==========================================================================
4916 The drop function, when machine executes this, the message is simply
4917 ignored. This function does nothing, the message is freed in
4918 StateMachinePerformAction()
4919 ==========================================================================
4922 IN PRTMP_ADAPTER pAd,
4923 IN MLME_QUEUE_ELEM *Elem)
4927 // ===========================================================================================
4929 // ===========================================================================================
4932 ==========================================================================
4935 IRQL = PASSIVE_LEVEL
4937 ==========================================================================
4940 IN PRTMP_ADAPTER pAd,
4944 pAd->Mlme.ShiftReg = 1;
4946 pAd->Mlme.ShiftReg = Seed;
4950 ==========================================================================
4952 ==========================================================================
4955 IN PRTMP_ADAPTER pAd)
4962 if (pAd->Mlme.ShiftReg == 0)
4963 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
4965 for (i = 0; i < 8; i++)
4967 if (pAd->Mlme.ShiftReg & 0x00000001)
4969 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
4974 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
4977 R = (R << 1) | Result;
4983 VOID AsicUpdateAutoFallBackTable(
4984 IN PRTMP_ADAPTER pAd,
4985 IN PUCHAR pRateTable)
4988 HT_FBK_CFG0_STRUC HtCfg0;
4989 HT_FBK_CFG1_STRUC HtCfg1;
4990 LG_FBK_CFG0_STRUC LgCfg0;
4991 LG_FBK_CFG1_STRUC LgCfg1;
4992 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
4994 // set to initial value
4995 HtCfg0.word = 0x65432100;
4996 HtCfg1.word = 0xedcba988;
4997 LgCfg0.word = 0xedcba988;
4998 LgCfg1.word = 0x00002100;
5000 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5001 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5003 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5004 switch (pCurrTxRate->Mode)
5010 switch(pCurrTxRate->CurrMCS)
5013 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5016 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5019 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5022 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5025 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5028 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5031 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5034 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5042 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5044 switch(pCurrTxRate->CurrMCS)
5047 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5050 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5053 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5056 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5059 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5062 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5065 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5068 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5071 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5074 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5077 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5080 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5083 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5086 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5089 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5092 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5095 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5102 pNextTxRate = pCurrTxRate;
5105 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5106 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5107 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5108 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5112 ========================================================================
5114 Routine Description:
5115 Set MAC register value according operation mode.
5116 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5117 If MM or GF mask is not set, those passing argument doesn't not take effect.
5119 Operation mode meaning:
5120 = 0 : Pure HT, no preotection.
5121 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5122 = 0x10: No Transmission in 40M is protected.
5123 = 0x11: Transmission in both 40M and 20M shall be protected
5125 we should choose not to use GF. But still set correct ASIC registers.
5126 ========================================================================
5128 VOID AsicUpdateProtect(
5129 IN PRTMP_ADAPTER pAd,
5130 IN USHORT OperationMode,
5132 IN BOOLEAN bDisableBGProtect,
5133 IN BOOLEAN bNonGFExist)
5135 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5141 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5146 if (pAd->BATable.numAsOriginator)
5149 // enable the RTS/CTS to avoid channel collision
5151 SetMask = ALLN_SETPROTECT;
5155 // Config ASIC RTS threshold register
5156 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5157 MacReg &= 0xFF0000FF;
5159 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5161 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5162 (pAd->CommonCfg.bAggregationCapable == TRUE))
5163 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5165 MacReg |= (0x1000 << 8);
5169 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5172 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5174 // Initial common protection settings
5175 RTMPZeroMemory(Protect, sizeof(Protect));
5178 ProtCfg.field.TxopAllowGF40 = 1;
5179 ProtCfg.field.TxopAllowGF20 = 1;
5180 ProtCfg.field.TxopAllowMM40 = 1;
5181 ProtCfg.field.TxopAllowMM20 = 1;
5182 ProtCfg.field.TxopAllowOfdm = 1;
5183 ProtCfg.field.TxopAllowCck = 1;
5184 ProtCfg.field.RTSThEn = 1;
5185 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5187 // update PHY mode and rate
5188 if (pAd->CommonCfg.Channel > 14)
5189 ProtCfg.field.ProtectRate = 0x4000;
5190 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5192 // Handle legacy(B/G) protection
5193 if (bDisableBGProtect)
5195 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5196 ProtCfg.field.ProtectCtrl = 0;
5197 Protect[0] = ProtCfg.word;
5198 Protect[1] = ProtCfg.word;
5202 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5203 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5204 Protect[0] = ProtCfg.word;
5205 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5206 Protect[1] = ProtCfg.word;
5209 // Decide HT frame protection.
5210 if ((SetMask & ALLN_SETPROTECT) != 0)
5212 switch(OperationMode)
5216 // 1.All STAs in the BSS are 20/40 MHz HT
5217 // 2. in ai 20/40MHz BSS
5218 // 3. all STAs are 20MHz in a 20MHz BSS
5219 // Pure HT. no protection.
5223 // PROT_TXOP(25:20) -- 010111
5224 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5225 // PROT_CTRL(17:16) -- 00 (None)
5226 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5227 Protect[2] = 0x01744004;
5231 // PROT_TXOP(25:20) -- 111111
5232 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5233 // PROT_CTRL(17:16) -- 00 (None)
5234 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5235 Protect[3] = 0x03f44084;
5239 // PROT_TXOP(25:20) -- 010111
5240 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5241 // PROT_CTRL(17:16) -- 00 (None)
5242 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5243 Protect[4] = 0x01744004;
5247 // PROT_TXOP(25:20) -- 111111
5248 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5249 // PROT_CTRL(17:16) -- 00 (None)
5250 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5251 Protect[5] = 0x03f44084;
5255 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5256 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5257 Protect[4] = 0x01754004;
5258 Protect[5] = 0x03f54084;
5260 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5264 // This is "HT non-member protection mode."
5265 // If there may be non-HT STAs my BSS
5266 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5267 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5268 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5270 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5271 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5273 //Assign Protection method for 20&40 MHz packets
5274 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5275 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5276 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5277 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5278 Protect[2] = ProtCfg.word;
5279 Protect[3] = ProtCfg4.word;
5280 Protect[4] = ProtCfg.word;
5281 Protect[5] = ProtCfg4.word;
5282 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5286 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5287 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5288 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5290 //Assign Protection method for 40MHz packets
5291 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5292 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5293 Protect[2] = ProtCfg.word;
5294 Protect[3] = ProtCfg4.word;
5297 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5298 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5300 Protect[4] = ProtCfg.word;
5301 Protect[5] = ProtCfg4.word;
5303 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5307 // HT mixed mode. PROTECT ALL!
5309 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5310 ProtCfg4.word = 0x03f44084;
5311 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5312 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5314 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5315 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5317 //Assign Protection method for 20&40 MHz packets
5318 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5319 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5320 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5321 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5322 Protect[2] = ProtCfg.word;
5323 Protect[3] = ProtCfg4.word;
5324 Protect[4] = ProtCfg.word;
5325 Protect[5] = ProtCfg4.word;
5326 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5330 // Special on for Atheros problem n chip.
5331 Protect[2] = 0x01754004;
5332 Protect[3] = 0x03f54084;
5333 Protect[4] = 0x01754004;
5334 Protect[5] = 0x03f54084;
5335 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5340 offset = CCK_PROT_CFG;
5341 for (i = 0;i < 6;i++)
5343 if ((SetMask & (1<< i)))
5345 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5353 ========================================================================
5355 Routine Description: Write RT30xx RF register through MAC
5365 ========================================================================
5367 NTSTATUS RT30xxWriteRFRegister(
5368 IN PRTMP_ADAPTER pAd,
5372 RF_CSR_CFG_STRUC rfcsr;
5377 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5379 if (!rfcsr.field.RF_CSR_KICK)
5383 while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
5385 if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
5387 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
5388 return STATUS_UNSUCCESSFUL;
5391 rfcsr.field.RF_CSR_WR = 1;
5392 rfcsr.field.RF_CSR_KICK = 1;
5393 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5394 rfcsr.field.RF_CSR_DATA = Value;
5396 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5398 return STATUS_SUCCESS;
5403 ========================================================================
5405 Routine Description: Read RT30xx RF register through MAC
5415 ========================================================================
5417 NTSTATUS RT30xxReadRFRegister(
5418 IN PRTMP_ADAPTER pAd,
5422 RF_CSR_CFG_STRUC rfcsr;
5425 for (i=0; i<MAX_BUSY_COUNT; i++)
5427 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5429 if (rfcsr.field.RF_CSR_KICK == BUSY)
5434 rfcsr.field.RF_CSR_WR = 0;
5435 rfcsr.field.RF_CSR_KICK = 1;
5436 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5437 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5438 for (k=0; k<MAX_BUSY_COUNT; k++)
5440 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5442 if (rfcsr.field.RF_CSR_KICK == IDLE)
5445 if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
5446 (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
5448 *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
5452 if (rfcsr.field.RF_CSR_KICK == BUSY)
5454 DBGPRINT_ERR(("RF read R%d=0x%x fail, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
5455 return STATUS_UNSUCCESSFUL;
5458 return STATUS_SUCCESS;
5463 // add by johnli, RF power sequence setup
5465 ==========================================================================
5468 Load RF normal operation-mode setup
5470 ==========================================================================
5472 VOID RT30xxLoadRFNormalModeSetup(
5473 IN PRTMP_ADAPTER pAd)
5477 // 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
5478 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5479 RFValue = (RFValue & (~0x0C)) | 0x31;
5480 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5482 // TX_LO2_en, RF R15 register Bit 3 to 0
5483 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5485 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5487 // TX_LO1_en, RF R17 register Bit 3 to 0
5488 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5490 // to fix rx long range issue
5491 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5495 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5497 // RX_LO1_en, RF R20 register Bit 3 to 0
5498 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5500 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5502 // RX_LO2_en, RF R21 register Bit 3 to 0
5503 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5505 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5507 // LDORF_VC, RF R27 register Bit 2 to 0
5508 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5509 if ((pAd->MACVersion & 0xffff) < 0x0211)
5510 RFValue = (RFValue & (~0x77)) | 0x3;
5512 RFValue = (RFValue & (~0x77));
5513 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5518 ==========================================================================
5521 Load RF sleep-mode setup
5523 ==========================================================================
5525 VOID RT30xxLoadRFSleepModeSetup(
5526 IN PRTMP_ADAPTER pAd)
5531 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5532 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5534 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5536 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5537 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5539 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5541 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5542 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5544 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5546 // RX_CTB_en, RF R21 register Bit 7 to 0
5547 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5549 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5551 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5552 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5554 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5556 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5557 MACValue |= 0x1D000000;
5558 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5562 ==========================================================================
5565 Reverse RF sleep-mode setup
5567 ==========================================================================
5569 VOID RT30xxReverseRFSleepModeSetup(
5570 IN PRTMP_ADAPTER pAd)
5575 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5576 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5578 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5580 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5581 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5583 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5585 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5586 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5588 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5590 // RX_CTB_en, RF R21 register Bit 7 to 1
5591 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5593 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5595 // LDORF_VC, RF R27 register Bit 2 to 0
5596 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5597 if ((pAd->MACVersion & 0xffff) < 0x0211)
5598 RFValue = (RFValue & (~0x77)) | 0x3;
5600 RFValue = (RFValue & (~0x77));
5601 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5603 // RT3071 version E has fixed this issue
5604 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5606 // patch tx EVM issue temporarily
5607 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5608 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5609 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5613 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5614 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5615 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5622 ==========================================================================
5625 IRQL = PASSIVE_LEVEL
5626 IRQL = DISPATCH_LEVEL
5628 ==========================================================================
5630 VOID AsicSwitchChannel(
5631 IN PRTMP_ADAPTER pAd,
5635 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5636 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5638 UINT32 Value = 0; //BbpReg, Value;
5639 RTMP_RF_REGS *RFRegTable;
5641 // Search Tx power value
5643 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5644 // in ChannelList, so use TxPower array instead.
5646 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5648 if (Channel == pAd->TxPower[index].Channel)
5650 TxPwer = pAd->TxPower[index].Power;
5651 TxPwer2 = pAd->TxPower[index].Power2;
5657 for (index = 0; index < pAd->ChannelListNum; index++)
5659 if (Channel == pAd->ChannelList[index].Channel)
5661 TxPwer = pAd->ChannelList[index].Power;
5662 TxPwer2 = pAd->ChannelList[index].Power2;
5668 if (index == MAX_NUM_OF_CHANNELS)
5671 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5674 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5679 // The RF programming sequence is difference between 3xxx and 2xxx
5681 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5682 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5685 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5688 /* modify by WY for Read RF Reg. error */
5691 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5693 if (Channel == FreqItems3020[index].Channel)
5695 // Programming channel parameters
5696 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5697 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5700 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5701 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5702 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5705 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5706 RFValue = (RFValue & 0xE0) | TxPwer;
5707 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5710 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5711 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5712 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5715 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5716 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5717 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5720 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5721 RFValue = (RFValue & 0xE0) | TxPwer;
5722 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5725 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5726 RFValue = (RFValue & 0xE0) | TxPwer2;
5727 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5729 // Tx/Rx Stream setting
5730 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5731 //if (IS_RT3090(pAd))
5732 // RFValue |= 0x01; // Enable RF block.
5733 RFValue &= 0x03; //clear bit[7~2]
5734 if (pAd->Antenna.field.TxPath == 1)
5736 else if (pAd->Antenna.field.TxPath == 2)
5738 if (pAd->Antenna.field.RxPath == 1)
5740 else if (pAd->Antenna.field.RxPath == 2)
5742 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5745 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5746 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5747 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5750 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5752 RFValue = pAd->Mlme.CaliBW40RfR24;
5753 //DISABLE_11N_CHECK(pAd);
5757 RFValue = pAd->Mlme.CaliBW20RfR24;
5760 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5763 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5764 RFValue = RFValue | 0x1;
5765 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5767 // latch channel for future usage.
5768 pAd->LatchRfRegs.Channel = Channel;
5771 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5772 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5775 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5776 RFValue = RFValue | 0x1;
5777 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5779 // latch channel for future usage.
5780 pAd->LatchRfRegs.Channel = Channel;
5782 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5787 pAd->Antenna.field.TxPath,
5788 FreqItems3020[index].N,
5789 FreqItems3020[index].K,
5790 FreqItems3020[index].R));
5797 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5802 pAd->Antenna.field.TxPath,
5803 FreqItems3020[index].N,
5804 FreqItems3020[index].K,
5805 FreqItems3020[index].R));
5811 RFRegTable = RF2850RegTable;
5813 switch (pAd->RfIcType)
5820 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5822 if (Channel == RFRegTable[index].Channel)
5824 R2 = RFRegTable[index].R2;
5825 if (pAd->Antenna.field.TxPath == 1)
5827 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5830 if (pAd->Antenna.field.RxPath == 2)
5832 R2 |= 0x40; // write 1 to off Rxpath.
5834 else if (pAd->Antenna.field.RxPath == 1)
5836 R2 |= 0x20040; // write 1 to off RxPath
5841 // initialize R3, R4
5842 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5843 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5845 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5847 if ((TxPwer >= -7) && (TxPwer < 0))
5849 TxPwer = (7+TxPwer);
5850 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5851 R3 |= (TxPwer << 10);
5852 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5856 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5857 R3 |= (TxPwer << 10) | (1 << 9);
5861 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5863 TxPwer2 = (7+TxPwer2);
5864 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5865 R4 |= (TxPwer2 << 7);
5866 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5870 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5871 R4 |= (TxPwer2 << 7) | (1 << 6);
5876 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5877 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5880 // Based on BBP current mode before changing RF channel.
5881 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5887 pAd->LatchRfRegs.Channel = Channel;
5888 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5889 pAd->LatchRfRegs.R2 = R2;
5890 pAd->LatchRfRegs.R3 = R3;
5891 pAd->LatchRfRegs.R4 = R4;
5893 // Set RF value 1's set R3[bit2] = [0]
5894 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5895 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5896 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5897 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5901 // Set RF value 2's set R3[bit2] = [1]
5902 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5903 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5904 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5905 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5909 // Set RF value 3's set R3[bit2] = [0]
5910 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5911 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5912 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5913 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5925 // Change BBP setting during siwtch from a->g, g->a
5928 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5930 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5931 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5932 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5933 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.
5934 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5936 // Rx High power VGA offset for LNA select
5937 if (pAd->NicConfig2.field.ExternalLNAForG)
5939 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5940 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5944 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5945 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5948 // 5G band selection PIN, bit1 and bit2 are complement
5949 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5952 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5954 // Turn off unused PA or LNA when only 1T or 1R
5955 if (pAd->Antenna.field.TxPath == 1)
5957 TxPinCfg &= 0xFFFFFFF3;
5959 if (pAd->Antenna.field.RxPath == 1)
5961 TxPinCfg &= 0xFFFFF3FF;
5964 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5968 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5970 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5971 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5972 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5973 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.
5974 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5976 // Rx High power VGA offset for LNA select
5977 if (pAd->NicConfig2.field.ExternalLNAForA)
5979 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5983 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5986 // 5G band selection PIN, bit1 and bit2 are complement
5987 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5990 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5992 // Turn off unused PA or LNA when only 1T or 1R
5993 if (pAd->Antenna.field.TxPath == 1)
5995 TxPinCfg &= 0xFFFFFFF3;
5997 if (pAd->Antenna.field.RxPath == 1)
5999 TxPinCfg &= 0xFFFFF3FF;
6002 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6005 // R66 should be set according to Channel and use 20MHz when scanning
6006 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6008 RTMPSetAGCInitValue(pAd, BW_20);
6010 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6013 // On 11A, We should delay and wait RF/BBP to be stable
6014 // and the appropriate time should be 1000 micro seconds
6015 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6017 RTMPusecDelay(1000);
6019 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",
6022 (R3 & 0x00003e00) >> 9,
6023 (R4 & 0x000007c0) >> 6,
6024 pAd->Antenna.field.TxPath,
6025 pAd->LatchRfRegs.R1,
6026 pAd->LatchRfRegs.R2,
6027 pAd->LatchRfRegs.R3,
6028 pAd->LatchRfRegs.R4));
6032 ==========================================================================
6034 This function is required for 2421 only, and should not be used during
6035 site survey. It's only required after NIC decided to stay at a channel
6036 for a longer period.
6037 When this function is called, it's always after AsicSwitchChannel().
6039 IRQL = PASSIVE_LEVEL
6040 IRQL = DISPATCH_LEVEL
6042 ==========================================================================
6044 VOID AsicLockChannel(
6045 IN PRTMP_ADAPTER pAd,
6051 ==========================================================================
6054 IRQL = PASSIVE_LEVEL
6055 IRQL = DISPATCH_LEVEL
6057 ==========================================================================
6059 VOID AsicAntennaSelect(
6060 IN PRTMP_ADAPTER pAd,
6064 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6066 // patch for AsicSetRxAnt failed
6067 pAd->RxAnt.EvaluatePeriod = 0;
6069 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6070 // valid indication of the distance between this AP and its clients.
6071 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6075 // if no traffic then reset average rssi to trigger evaluation
6076 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6078 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6079 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6080 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6083 pAd->StaCfg.NumOfAvgRssiSample = 0;
6084 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6086 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6088 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6089 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6091 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6092 AsicEvaluateRxAnt(pAd);
6097 // if not connected, always switch antenna to try to connect
6100 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6101 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6102 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6104 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6106 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6113 ========================================================================
6115 Routine Description:
6116 Antenna miscellaneous setting.
6119 pAd Pointer to our adapter
6120 BandState Indicate current Band State.
6125 IRQL <= DISPATCH_LEVEL
6128 1.) Frame End type control
6129 only valid for G only (RF_2527 & RF_2529)
6130 0: means DPDT, set BBP R4 bit 5 to 1
6131 1: means SPDT, set BBP R4 bit 5 to 0
6134 ========================================================================
6136 VOID AsicAntennaSetting(
6137 IN PRTMP_ADAPTER pAd,
6138 IN ABGBAND_STATE BandState)
6142 VOID AsicRfTuningExec(
6143 IN PVOID SystemSpecific1,
6144 IN PVOID FunctionContext,
6145 IN PVOID SystemSpecific2,
6146 IN PVOID SystemSpecific3)
6151 ==========================================================================
6153 Gives CCK TX rate 2 more dB TX power.
6154 This routine works only in LINK UP in INFRASTRUCTURE mode.
6156 calculate desired Tx power in RF R3.Tx0~5, should consider -
6157 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6158 1. TxPowerPercentage
6159 2. auto calibration based on TSSI feedback
6160 3. extra 2 db for CCK
6161 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6163 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6164 it should be called AFTER MlmeDynamicTxRatSwitching()
6165 ==========================================================================
6167 VOID AsicAdjustTxPower(
6168 IN PRTMP_ADAPTER pAd)
6172 BOOLEAN bAutoTxAgc = FALSE;
6173 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6174 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6175 PCHAR pTxAgcCompensate;
6179 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6181 if (pAd->CommonCfg.CentralChannel > 14)
6183 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6184 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6185 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6186 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6187 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6191 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6192 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6193 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6194 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6195 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6200 if (pAd->CommonCfg.Channel > 14)
6202 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6203 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6204 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6205 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6206 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6210 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6211 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6212 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6213 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6214 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6218 // TX power compensation for temperature variation based on TSSI. try every 4 second
6219 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6221 if (pAd->CommonCfg.Channel <= 14)
6224 bAutoTxAgc = pAd->bAutoTxAgcG;
6225 TssiRef = pAd->TssiRefG;
6226 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6227 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6228 TxAgcStep = pAd->TxAgcStepG;
6229 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6234 bAutoTxAgc = pAd->bAutoTxAgcA;
6235 TssiRef = pAd->TssiRefA;
6236 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6237 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6238 TxAgcStep = pAd->TxAgcStepA;
6239 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6244 /* BbpR1 is unsigned char */
6245 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6247 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6248 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6249 /* step value is defined in pAd->TxAgcStepG for tx power value */
6251 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6252 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6253 above value are examined in mass factory production */
6254 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6256 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6257 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6258 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6260 if (BbpR49 > pTssiMinusBoundary[1])
6262 // Reading is larger than the reference value
6263 // check for how large we need to decrease the Tx power
6264 for (idx = 1; idx < 5; idx++)
6266 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6269 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6270 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6272 DeltaPwr += (*pTxAgcCompensate);
6273 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6274 BbpR49, TssiRef, TxAgcStep, idx-1));
6276 else if (BbpR49 < pTssiPlusBoundary[1])
6278 // Reading is smaller than the reference value
6279 // check for how large we need to increase the Tx power
6280 for (idx = 1; idx < 5; idx++)
6282 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6285 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6286 *pTxAgcCompensate = TxAgcStep * (idx-1);
6287 DeltaPwr += (*pTxAgcCompensate);
6288 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6289 BbpR49, TssiRef, TxAgcStep, idx-1));
6293 *pTxAgcCompensate = 0;
6294 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6295 BbpR49, TssiRef, TxAgcStep, 0));
6301 if (pAd->CommonCfg.Channel <= 14)
6303 bAutoTxAgc = pAd->bAutoTxAgcG;
6304 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6308 bAutoTxAgc = pAd->bAutoTxAgcA;
6309 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6313 DeltaPwr += (*pTxAgcCompensate);
6316 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6319 /* calculate delta power based on the percentage specified from UI */
6320 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6321 // We lower TX power here according to the percentage specified from UI
6322 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6324 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6326 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6330 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6334 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6338 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6343 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6348 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6350 /* reset different new tx power for different TX rate */
6353 if (TxPwr[i] != 0xffffffff)
6357 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6359 if ((Value + DeltaPwr) < 0)
6361 Value = 0; /* min */
6363 else if ((Value + DeltaPwr) > 0xF)
6365 Value = 0xF; /* max */
6369 Value += DeltaPwr; /* temperature compensation */
6372 /* fill new value to CSR offset */
6373 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6376 /* write tx power value to CSR */
6377 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6378 TX power for OFDM 6M/9M
6379 TX power for CCK5.5M/11M
6380 TX power for CCK1M/2M */
6381 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6382 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6389 ==========================================================================
6391 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6392 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6393 the wakeup timer timeout. Driver has to issue a separate command to wake
6396 IRQL = DISPATCH_LEVEL
6398 ==========================================================================
6400 VOID AsicSleepThenAutoWakeup(
6401 IN PRTMP_ADAPTER pAd,
6402 IN USHORT TbttNumToNextWakeUp)
6404 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6408 ==========================================================================
6410 AsicForceWakeup() is used whenever manual wakeup is required
6411 AsicForceSleep() should only be used when not in INFRA BSS. When
6412 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6413 ==========================================================================
6415 VOID AsicForceSleep(
6416 IN PRTMP_ADAPTER pAd)
6422 ==========================================================================
6424 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6427 IRQL = PASSIVE_LEVEL
6428 IRQL = DISPATCH_LEVEL
6429 ==========================================================================
6431 VOID AsicForceWakeup(
6432 IN PRTMP_ADAPTER pAd,
6435 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6436 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6440 ==========================================================================
6444 IRQL = DISPATCH_LEVEL
6446 ==========================================================================
6449 IN PRTMP_ADAPTER pAd,
6453 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6454 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6456 Addr4 = (ULONG)(pBssid[0]) |
6457 (ULONG)(pBssid[1] << 8) |
6458 (ULONG)(pBssid[2] << 16) |
6459 (ULONG)(pBssid[3] << 24);
6460 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6463 // always one BSSID in STA mode
6464 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6466 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6469 VOID AsicSetMcastWC(
6470 IN PRTMP_ADAPTER pAd)
6472 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6475 pEntry->Sst = SST_ASSOC;
6476 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6477 pEntry->PsMode = PWR_ACTIVE;
6478 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6479 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6483 ==========================================================================
6486 IRQL = DISPATCH_LEVEL
6488 ==========================================================================
6490 VOID AsicDelWcidTab(
6491 IN PRTMP_ADAPTER pAd,
6494 ULONG Addr0 = 0x0, Addr1 = 0x0;
6497 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6498 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6499 RTMP_IO_WRITE32(pAd, offset, Addr0);
6501 RTMP_IO_WRITE32(pAd, offset, Addr1);
6505 ==========================================================================
6508 IRQL = DISPATCH_LEVEL
6510 ==========================================================================
6513 IN PRTMP_ADAPTER pAd)
6515 TX_LINK_CFG_STRUC TxLinkCfg;
6518 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6519 TxLinkCfg.field.TxRDGEn = 1;
6520 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6522 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6525 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6527 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6531 ==========================================================================
6534 IRQL = DISPATCH_LEVEL
6536 ==========================================================================
6538 VOID AsicDisableRDG(
6539 IN PRTMP_ADAPTER pAd)
6541 TX_LINK_CFG_STRUC TxLinkCfg;
6545 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6546 TxLinkCfg.field.TxRDGEn = 0;
6547 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6549 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6552 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6553 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6556 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6557 if (pAd->CommonCfg.bEnableTxBurst)
6560 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6564 ==========================================================================
6567 IRQL = PASSIVE_LEVEL
6568 IRQL = DISPATCH_LEVEL
6570 ==========================================================================
6572 VOID AsicDisableSync(
6573 IN PRTMP_ADAPTER pAd)
6575 BCN_TIME_CFG_STRUC csr;
6577 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6579 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6580 // that NIC will never wakes up because TSF stops and no more
6582 pAd->TbttTickCount = 0;
6583 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6584 csr.field.bBeaconGen = 0;
6585 csr.field.bTBTTEnable = 0;
6586 csr.field.TsfSyncMode = 0;
6587 csr.field.bTsfTicking = 0;
6588 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6593 ==========================================================================
6596 IRQL = DISPATCH_LEVEL
6598 ==========================================================================
6600 VOID AsicEnableBssSync(
6601 IN PRTMP_ADAPTER pAd)
6603 BCN_TIME_CFG_STRUC csr;
6605 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6607 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6610 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6611 csr.field.bTsfTicking = 1;
6612 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6613 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6614 csr.field.bTBTTEnable = 1;
6617 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6621 ==========================================================================
6624 BEACON frame in shared memory should be built ok before this routine
6625 can be called. Otherwise, a garbage frame maybe transmitted out every
6628 IRQL = DISPATCH_LEVEL
6630 ==========================================================================
6632 VOID AsicEnableIbssSync(
6633 IN PRTMP_ADAPTER pAd)
6635 BCN_TIME_CFG_STRUC csr9;
6639 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6641 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6642 csr9.field.bBeaconGen = 0;
6643 csr9.field.bTBTTEnable = 0;
6644 csr9.field.bTsfTicking = 0;
6645 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6649 // move BEACON TXD and frame content to on-chip memory
6650 ptr = (PUCHAR)&pAd->BeaconTxWI;
6651 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6653 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6657 // start right after the 16-byte TXWI field
6658 ptr = pAd->BeaconBuf;
6659 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6661 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6666 // start sending BEACON
6667 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6668 csr9.field.bTsfTicking = 1;
6669 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6670 csr9.field.bTBTTEnable = 1;
6671 csr9.field.bBeaconGen = 1;
6672 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6676 ==========================================================================
6679 IRQL = PASSIVE_LEVEL
6680 IRQL = DISPATCH_LEVEL
6682 ==========================================================================
6684 VOID AsicSetEdcaParm(
6685 IN PRTMP_ADAPTER pAd,
6686 IN PEDCA_PARM pEdcaParm)
6688 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6689 AC_TXOP_CSR0_STRUC csr0;
6690 AC_TXOP_CSR1_STRUC csr1;
6691 AIFSN_CSR_STRUC AifsnCsr;
6692 CWMIN_CSR_STRUC CwminCsr;
6693 CWMAX_CSR_STRUC CwmaxCsr;
6700 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6702 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6703 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6704 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6706 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6707 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6710 //========================================================
6711 // MAC Register has a copy .
6712 //========================================================
6713 if( pAd->CommonCfg.bEnableTxBurst )
6715 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6716 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6719 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6720 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6721 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6722 Ac0Cfg.field.Aifsn = 2;
6723 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6725 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6726 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6727 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6728 Ac1Cfg.field.Aifsn = 2;
6729 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6731 if (pAd->CommonCfg.PhyMode == PHY_11B)
6733 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6734 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6738 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6739 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6741 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6742 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6743 Ac2Cfg.field.Aifsn = 2;
6744 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6745 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6746 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6747 Ac3Cfg.field.Aifsn = 2;
6748 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6750 //========================================================
6751 // DMA Register has a copy too.
6752 //========================================================
6753 csr0.field.Ac0Txop = 0; // QID_AC_BE
6754 csr0.field.Ac1Txop = 0; // QID_AC_BK
6755 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6756 if (pAd->CommonCfg.PhyMode == PHY_11B)
6758 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6759 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6763 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6764 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6766 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6769 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6770 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6771 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6772 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6773 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6776 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6777 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6778 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6779 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6780 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6782 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6784 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6788 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6789 //========================================================
6790 // MAC Register has a copy.
6791 //========================================================
6793 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6794 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6796 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6798 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6799 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6800 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6801 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6803 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6804 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6805 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6806 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6808 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6809 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6810 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6811 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6814 // Tuning for Wi-Fi WMM S06
6815 if (pAd->CommonCfg.bWiFiTest &&
6816 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6817 Ac2Cfg.field.Aifsn -= 1;
6819 // Tuning for TGn Wi-Fi 5.2.32
6820 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6821 if (STA_TGN_WIFI_ON(pAd) &&
6822 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6824 Ac0Cfg.field.Aifsn = 3;
6825 Ac2Cfg.field.AcTxop = 5;
6829 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6831 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6832 Ac2Cfg.field.Aifsn = 5;
6837 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6838 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6839 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6840 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6843 if (pAd->CommonCfg.bWiFiTest)
6845 if (Ac3Cfg.field.AcTxop == 102)
6847 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6848 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6849 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6850 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6851 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6854 //#endif // WIFI_TEST //
6856 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6857 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6858 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6859 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6862 //========================================================
6863 // DMA Register has a copy too.
6864 //========================================================
6865 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6866 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6867 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6869 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6870 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6871 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6874 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6875 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6876 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6878 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6880 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6883 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6884 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6885 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6886 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6887 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6890 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6891 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6892 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6895 // Tuning for Wi-Fi WMM S06
6896 if (pAd->CommonCfg.bWiFiTest &&
6897 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6898 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6900 // Tuning for TGn Wi-Fi 5.2.32
6901 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6902 if (STA_TGN_WIFI_ON(pAd) &&
6903 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6905 AifsnCsr.field.Aifsn0 = 3;
6906 AifsnCsr.field.Aifsn2 = 7;
6910 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6913 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6915 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6916 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
6919 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6921 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6924 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6925 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6926 pEdcaParm->Aifsn[0],
6927 pEdcaParm->Cwmin[0],
6928 pEdcaParm->Cwmax[0],
6929 pEdcaParm->Txop[0]<<5,
6930 pEdcaParm->bACM[0]));
6931 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6932 pEdcaParm->Aifsn[1],
6933 pEdcaParm->Cwmin[1],
6934 pEdcaParm->Cwmax[1],
6935 pEdcaParm->Txop[1]<<5,
6936 pEdcaParm->bACM[1]));
6937 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6938 pEdcaParm->Aifsn[2],
6939 pEdcaParm->Cwmin[2],
6940 pEdcaParm->Cwmax[2],
6941 pEdcaParm->Txop[2]<<5,
6942 pEdcaParm->bACM[2]));
6943 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6944 pEdcaParm->Aifsn[3],
6945 pEdcaParm->Cwmin[3],
6946 pEdcaParm->Cwmax[3],
6947 pEdcaParm->Txop[3]<<5,
6948 pEdcaParm->bACM[3]));
6954 ==========================================================================
6957 IRQL = PASSIVE_LEVEL
6958 IRQL = DISPATCH_LEVEL
6960 ==========================================================================
6962 VOID AsicSetSlotTime(
6963 IN PRTMP_ADAPTER pAd,
6964 IN BOOLEAN bUseShortSlotTime)
6967 UINT32 RegValue = 0;
6969 if (pAd->CommonCfg.Channel > 14)
6970 bUseShortSlotTime = TRUE;
6972 if (bUseShortSlotTime)
6973 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6975 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6977 SlotTime = (bUseShortSlotTime)? 9 : 20;
6981 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6982 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6983 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6986 // In this case, we will think it is doing Wi-Fi test
6987 // And we will not set to short slot when bEnableTxBurst is TRUE.
6989 else if (pAd->CommonCfg.bEnableTxBurst)
6992 if (pAd->CommonCfg.bEnableTxBurst)
6998 // For some reasons, always set it to short slot time.
7000 // ToDo: Should consider capability with 11B
7002 if (pAd->StaCfg.BssType == BSS_ADHOC)
7005 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7006 RegValue = RegValue & 0xFFFFFF00;
7008 RegValue |= SlotTime;
7010 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7014 ========================================================================
7016 Add Shared key information into ASIC.
7017 Update shared key, TxMic and RxMic to Asic Shared key table
7018 Update its cipherAlg to Asic Shared key Mode.
7021 ========================================================================
7023 VOID AsicAddSharedKeyEntry(
7024 IN PRTMP_ADAPTER pAd,
7032 ULONG offset; //, csr0;
7033 SHAREDKEY_MODE_STRUC csr1;
7035 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7036 //============================================================================================
7038 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7039 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7040 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]));
7043 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7044 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7048 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7049 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7051 //============================================================================================
7053 // fill key material - key + TX MIC + RX MIC
7058 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7059 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7061 offset += MAX_LEN_OF_SHARE_KEY;
7064 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7070 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7076 // Update cipher algorithm. WSTA always use BSS0
7078 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7079 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7080 if ((BssIndex%2) == 0)
7083 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7084 else if (KeyIdx == 1)
7085 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7086 else if (KeyIdx == 2)
7087 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7089 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7094 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7095 else if (KeyIdx == 1)
7096 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7097 else if (KeyIdx == 2)
7098 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7100 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7102 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7103 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7107 // IRQL = DISPATCH_LEVEL
7108 VOID AsicRemoveSharedKeyEntry(
7109 IN PRTMP_ADAPTER pAd,
7114 SHAREDKEY_MODE_STRUC csr1;
7116 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7118 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7119 if ((BssIndex%2) == 0)
7122 csr1.field.Bss0Key0CipherAlg = 0;
7123 else if (KeyIdx == 1)
7124 csr1.field.Bss0Key1CipherAlg = 0;
7125 else if (KeyIdx == 2)
7126 csr1.field.Bss0Key2CipherAlg = 0;
7128 csr1.field.Bss0Key3CipherAlg = 0;
7133 csr1.field.Bss1Key0CipherAlg = 0;
7134 else if (KeyIdx == 1)
7135 csr1.field.Bss1Key1CipherAlg = 0;
7136 else if (KeyIdx == 2)
7137 csr1.field.Bss1Key2CipherAlg = 0;
7139 csr1.field.Bss1Key3CipherAlg = 0;
7141 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7142 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7143 ASSERT(BssIndex < 4);
7149 VOID AsicUpdateWCIDAttribute(
7150 IN PRTMP_ADAPTER pAd,
7154 IN BOOLEAN bUsePairewiseKeyTable)
7156 ULONG WCIDAttri = 0, offset;
7159 // Update WCID attribute.
7160 // Only TxKey could update WCID attribute.
7162 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7163 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7164 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7167 VOID AsicUpdateWCIDIVEIV(
7168 IN PRTMP_ADAPTER pAd,
7175 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7177 RTMP_IO_WRITE32(pAd, offset, uIV);
7178 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7181 VOID AsicUpdateRxWCIDTable(
7182 IN PRTMP_ADAPTER pAd,
7189 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7190 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7191 RTMP_IO_WRITE32(pAd, offset, Addr);
7192 Addr = pAddr[4] + (pAddr[5] << 8);
7193 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7198 ========================================================================
7200 Routine Description:
7201 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7204 pAd Pointer to our adapter
7205 WCID WCID Entry number.
7206 BssIndex BSSID index, station or none multiple BSSID support
7207 this value should be 0.
7208 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7209 pCipherKey Pointer to Cipher Key.
7210 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7211 otherwise PairewiseKey table
7212 bTxKey This is the transmit key if enabled.
7218 This routine will set the relative key stuff to Asic including WCID attribute,
7219 Cipher Key, Cipher algorithm and IV/EIV.
7221 IV/EIV will be update if this CipherKey is the transmission key because
7222 ASIC will base on IV's KeyID value to select Cipher Key.
7224 If bTxKey sets to FALSE, this is not the TX key, but it could be
7227 For AP mode bTxKey must be always set to TRUE.
7228 ========================================================================
7230 VOID AsicAddKeyEntry(
7231 IN PRTMP_ADAPTER pAd,
7235 IN PCIPHER_KEY pCipherKey,
7236 IN BOOLEAN bUsePairewiseKeyTable,
7241 PUCHAR pKey = pCipherKey->Key;
7242 PUCHAR pTxMic = pCipherKey->TxMic;
7243 PUCHAR pRxMic = pCipherKey->RxMic;
7244 PUCHAR pTxtsc = pCipherKey->TxTsc;
7245 UCHAR CipherAlg = pCipherKey->CipherAlg;
7246 SHAREDKEY_MODE_STRUC csr1;
7248 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7250 // 1.) decide key table offset
7252 if (bUsePairewiseKeyTable)
7253 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7255 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7258 // 2.) Set Key to Asic
7260 //for (i = 0; i < KeyLen; i++)
7263 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7264 offset += MAX_LEN_OF_PEER_KEY;
7267 // 3.) Set MIC key if available
7271 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7273 offset += LEN_TKIP_TXMICK;
7277 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7282 // 4.) Modify IV/EIV if needs
7283 // This will force Asic to use this key ID by setting IV.
7294 IV4 = (KeyIdx << 6);
7295 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7296 IV4 |= 0x20; // turn on extension bit means EIV existence
7298 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7299 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7305 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7307 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7310 if (!bUsePairewiseKeyTable)
7313 // Only update the shared key security mode
7315 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7316 if ((BssIndex % 2) == 0)
7319 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7320 else if (KeyIdx == 1)
7321 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7322 else if (KeyIdx == 2)
7323 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7325 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7330 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7331 else if (KeyIdx == 1)
7332 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7333 else if (KeyIdx == 2)
7334 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7336 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7338 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7341 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7346 ========================================================================
7348 Add Pair-wise key material into ASIC.
7349 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7352 ========================================================================
7354 VOID AsicAddPairwiseKeyEntry(
7355 IN PRTMP_ADAPTER pAd,
7358 IN CIPHER_KEY *pCipherKey)
7362 PUCHAR pKey = pCipherKey->Key;
7363 PUCHAR pTxMic = pCipherKey->TxMic;
7364 PUCHAR pRxMic = pCipherKey->RxMic;
7366 UCHAR CipherAlg = pCipherKey->CipherAlg;
7370 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7372 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7374 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7377 RTMP_IO_READ32(pAd, offset + i, &Value);
7380 offset += MAX_LEN_OF_PEER_KEY;
7386 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7393 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7397 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7398 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7399 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]));
7402 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7403 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7407 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7408 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7412 ========================================================================
7414 Remove Pair-wise key material from ASIC.
7417 ========================================================================
7419 VOID AsicRemovePairwiseKeyEntry(
7420 IN PRTMP_ADAPTER pAd,
7427 // re-set the entry's WCID attribute as OPEN-NONE.
7428 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7429 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7430 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7433 BOOLEAN AsicSendCommandToMcu(
7434 IN PRTMP_ADAPTER pAd,
7440 HOST_CMD_CSR_STRUC H2MCmd;
7441 H2M_MAILBOX_STRUC H2MMailbox;
7445 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7446 if (H2MMailbox.field.Owner == 0)
7455 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7461 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7462 H2MMailbox.field.CmdToken = Token;
7463 H2MMailbox.field.HighByte = Arg1;
7464 H2MMailbox.field.LowByte = Arg0;
7465 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7468 H2MCmd.field.HostCommand = Command;
7469 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7471 if (Command != 0x80)
7480 ========================================================================
7482 Routine Description:
7483 Verify the support rate for different PHY type
7486 pAd Pointer to our adapter
7491 IRQL = PASSIVE_LEVEL
7493 ========================================================================
7495 VOID RTMPCheckRates(
7496 IN PRTMP_ADAPTER pAd,
7497 IN OUT UCHAR SupRate[],
7498 IN OUT UCHAR *SupRateLen)
7500 UCHAR RateIdx, i, j;
7501 UCHAR NewRate[12], NewRateLen;
7505 if (pAd->CommonCfg.PhyMode == PHY_11B)
7510 // Check for support rates exclude basic rate bit
7511 for (i = 0; i < *SupRateLen; i++)
7512 for (j = 0; j < RateIdx; j++)
7513 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7514 NewRate[NewRateLen++] = SupRate[i];
7516 *SupRateLen = NewRateLen;
7517 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7520 BOOLEAN RTMPCheckChannel(
7521 IN PRTMP_ADAPTER pAd,
7522 IN UCHAR CentralChannel,
7526 UCHAR UpperChannel = 0, LowerChannel = 0;
7527 UCHAR NoEffectChannelinList = 0;
7529 // Find upper and lower channel according to 40MHz current operation.
7530 if (CentralChannel < Channel)
7532 UpperChannel = Channel;
7533 if (CentralChannel > 2)
7534 LowerChannel = CentralChannel - 2;
7538 else if (CentralChannel > Channel)
7540 UpperChannel = CentralChannel + 2;
7541 LowerChannel = Channel;
7544 for (k = 0;k < pAd->ChannelListNum;k++)
7546 if (pAd->ChannelList[k].Channel == UpperChannel)
7548 NoEffectChannelinList ++;
7550 if (pAd->ChannelList[k].Channel == LowerChannel)
7552 NoEffectChannelinList ++;
7556 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7557 if (NoEffectChannelinList == 2)
7564 ========================================================================
7566 Routine Description:
7567 Verify the support rate for HT phy type
7570 pAd Pointer to our adapter
7573 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7575 IRQL = PASSIVE_LEVEL
7577 ========================================================================
7579 BOOLEAN RTMPCheckHt(
7580 IN PRTMP_ADAPTER pAd,
7582 IN HT_CAPABILITY_IE *pHtCapability,
7583 IN ADD_HT_INFO_IE *pAddHtInfo)
7585 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7588 // If use AMSDU, set flag.
7589 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7590 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7591 // Save Peer Capability
7592 if (pHtCapability->HtCapInfo.ShortGIfor20)
7593 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7594 if (pHtCapability->HtCapInfo.ShortGIfor40)
7595 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7596 if (pHtCapability->HtCapInfo.TxSTBC)
7597 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7598 if (pHtCapability->HtCapInfo.RxSTBC)
7599 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7600 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7602 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7605 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7607 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7610 // Will check ChannelWidth for MCSSet[4] below
7611 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7612 switch (pAd->CommonCfg.RxStream)
7615 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7616 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7617 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7618 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7621 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7622 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7623 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7624 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7627 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7628 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7629 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7630 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7634 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7636 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7637 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7638 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7640 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7642 // Send Assoc Req with my HT capability.
7643 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7644 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7645 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7646 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7647 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7648 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7649 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7650 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7651 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7652 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7653 if (pAd->CommonCfg.bRdg)
7655 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7656 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7659 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7660 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7662 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7667 ========================================================================
7669 Routine Description:
7670 Verify the support rate for different PHY type
7673 pAd Pointer to our adapter
7678 IRQL = PASSIVE_LEVEL
7680 ========================================================================
7682 VOID RTMPUpdateMlmeRate(
7683 IN PRTMP_ADAPTER pAd)
7686 UCHAR ProperMlmeRate; //= RATE_54;
7687 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7688 BOOLEAN bMatch = FALSE;
7690 switch (pAd->CommonCfg.PhyMode)
7693 ProperMlmeRate = RATE_11;
7694 MinimumRate = RATE_1;
7696 case PHY_11BG_MIXED:
7697 case PHY_11ABGN_MIXED:
7698 case PHY_11BGN_MIXED:
7699 if ((pAd->MlmeAux.SupRateLen == 4) &&
7700 (pAd->MlmeAux.ExtRateLen == 0))
7702 ProperMlmeRate = RATE_11;
7704 ProperMlmeRate = RATE_24;
7706 if (pAd->MlmeAux.Channel <= 14)
7707 MinimumRate = RATE_1;
7709 MinimumRate = RATE_6;
7712 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7713 case PHY_11GN_MIXED:
7714 case PHY_11AGN_MIXED:
7715 case PHY_11AN_MIXED:
7717 ProperMlmeRate = RATE_24;
7718 MinimumRate = RATE_6;
7720 case PHY_11ABG_MIXED:
7721 ProperMlmeRate = RATE_24;
7722 if (pAd->MlmeAux.Channel <= 14)
7723 MinimumRate = RATE_1;
7725 MinimumRate = RATE_6;
7728 ProperMlmeRate = RATE_1;
7729 MinimumRate = RATE_1;
7733 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7735 for (j = 0; j < RateIdx; j++)
7737 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7739 if (j == ProperMlmeRate)
7751 if (bMatch == FALSE)
7753 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7755 for (j = 0; j < RateIdx; j++)
7757 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7759 if (j == ProperMlmeRate)
7772 if (bMatch == FALSE)
7774 ProperMlmeRate = MinimumRate;
7777 pAd->CommonCfg.MlmeRate = MinimumRate;
7778 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7779 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7781 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7782 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7783 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7784 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7788 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7789 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7790 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7791 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7794 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7798 IN PRTMP_ADAPTER pAd,
7805 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7810 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7812 larger = max(Rssi0, Rssi1);
7815 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7817 larger = max(larger, Rssi2);
7827 // Antenna divesity use GPIO3 and EESK pin for control
7828 // Antenna and EEPROM access are both using EESK pin,
7829 // Therefor we should avoid accessing EESK at the same time
7830 // Then restore antenna after EEPROM access
7832 IN PRTMP_ADAPTER pAd,
7839 if ((pAd->EepromAccess) ||
7840 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
7841 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
7842 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
7843 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
7848 // the antenna selection is through firmware and MAC register(GPIO3)
7852 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
7854 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
7856 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
7858 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
7859 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
7864 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
7866 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
7868 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
7871 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
7872 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
7879 ========================================================================
7880 Routine Description:
7881 Periodic evaluate antenna link status
7884 pAd - Adapter pointer
7889 ========================================================================
7891 VOID AsicEvaluateRxAnt(
7892 IN PRTMP_ADAPTER pAd)
7898 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7899 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7900 fRTMP_ADAPTER_RADIO_OFF |
7901 fRTMP_ADAPTER_NIC_NOT_EXIST |
7902 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7905 if (pAd->StaCfg.Psm == PWR_SAVE)
7909 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7911 if(pAd->Antenna.field.RxPath == 3)
7915 else if(pAd->Antenna.field.RxPath == 2)
7919 else if(pAd->Antenna.field.RxPath == 1)
7923 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7925 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7928 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7929 pAd->RalinkCounters.OneSecTxRetryOkCount +
7930 pAd->RalinkCounters.OneSecTxFailCount;
7932 if (TxTotalCnt > 50)
7934 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7935 pAd->Mlme.bLowThroughput = FALSE;
7939 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7940 pAd->Mlme.bLowThroughput = TRUE;
7945 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7946 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7947 fRTMP_ADAPTER_RADIO_OFF |
7948 fRTMP_ADAPTER_NIC_NOT_EXIST |
7949 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
7950 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
7952 || (pAd->EepromAccess)
7959 //if (pAd->StaCfg.Psm == PWR_SAVE)
7963 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
7964 // one is antenna diversity:there is only one antenna can rx and tx
7965 // the other is failed antenna remove:two physical antenna can rx and tx
7966 if (pAd->NicConfig2.field.AntDiversity)
7968 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
7969 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
7971 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
7973 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
7974 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
7975 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
7977 // a one-shot timer to end the evalution
7978 // dynamic adjust antenna evaluation period according to the traffic
7979 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7980 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
7982 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7986 if (pAd->StaCfg.Psm == PWR_SAVE)
7989 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7991 if(pAd->Antenna.field.RxPath == 3)
7995 else if(pAd->Antenna.field.RxPath == 2)
7999 else if(pAd->Antenna.field.RxPath == 1)
8003 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8005 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8008 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8009 pAd->RalinkCounters.OneSecTxRetryOkCount +
8010 pAd->RalinkCounters.OneSecTxFailCount;
8012 // dynamic adjust antenna evaluation period according to the traffic
8013 if (TxTotalCnt > 50)
8015 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8016 pAd->Mlme.bLowThroughput = FALSE;
8020 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8021 pAd->Mlme.bLowThroughput = TRUE;
8029 ========================================================================
8030 Routine Description:
8031 After evaluation, check antenna link status
8034 pAd - Adapter pointer
8039 ========================================================================
8041 VOID AsicRxAntEvalTimeout(
8042 IN PVOID SystemSpecific1,
8043 IN PVOID FunctionContext,
8044 IN PVOID SystemSpecific2,
8045 IN PVOID SystemSpecific3)
8047 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8049 CHAR larger = -127, rssi0, rssi1, rssi2;
8053 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8054 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8055 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8056 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8059 if (pAd->StaCfg.Psm == PWR_SAVE)
8063 // if the traffic is low, use average rssi as the criteria
8064 if (pAd->Mlme.bLowThroughput == TRUE)
8066 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8067 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8068 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8072 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8073 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8074 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8077 if(pAd->Antenna.field.RxPath == 3)
8079 larger = max(rssi0, rssi1);
8081 if (larger > (rssi2 + 20))
8082 pAd->Mlme.RealRxPath = 2;
8084 pAd->Mlme.RealRxPath = 3;
8086 else if(pAd->Antenna.field.RxPath == 2)
8088 if (rssi0 > (rssi1 + 20))
8089 pAd->Mlme.RealRxPath = 1;
8091 pAd->Mlme.RealRxPath = 2;
8094 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8096 if(pAd->Mlme.RealRxPath == 3)
8100 else if(pAd->Mlme.RealRxPath == 2)
8104 else if(pAd->Mlme.RealRxPath == 1)
8108 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8112 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8113 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8114 fRTMP_ADAPTER_RADIO_OFF |
8115 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8116 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8118 || (pAd->EepromAccess)
8124 //if (pAd->StaCfg.Psm == PWR_SAVE)
8127 if (pAd->NicConfig2.field.AntDiversity)
8129 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8134 // select PrimaryRxAntPair
8135 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8136 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8138 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8139 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8140 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8142 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8143 pAd->RxAnt.EvaluateStableCnt = 0;
8147 // if the evaluated antenna is not better than original, switch back to original antenna
8148 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8149 pAd->RxAnt.EvaluateStableCnt ++;
8152 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8154 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8155 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8159 if (pAd->StaCfg.Psm == PWR_SAVE)
8162 // if the traffic is low, use average rssi as the criteria
8163 if (pAd->Mlme.bLowThroughput == TRUE)
8165 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8166 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8167 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8171 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8172 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8173 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8176 if(pAd->Antenna.field.RxPath == 3)
8178 larger = max(rssi0, rssi1);
8180 if (larger > (rssi2 + 20))
8181 pAd->Mlme.RealRxPath = 2;
8183 pAd->Mlme.RealRxPath = 3;
8185 else if(pAd->Antenna.field.RxPath == 2)
8187 if (rssi0 > (rssi1 + 20))
8188 pAd->Mlme.RealRxPath = 1;
8190 pAd->Mlme.RealRxPath = 2;
8193 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8195 if(pAd->Mlme.RealRxPath == 3)
8199 else if(pAd->Mlme.RealRxPath == 2)
8203 else if(pAd->Mlme.RealRxPath == 1)
8207 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8215 VOID APSDPeriodicExec(
8216 IN PVOID SystemSpecific1,
8217 IN PVOID FunctionContext,
8218 IN PVOID SystemSpecific2,
8219 IN PVOID SystemSpecific3)
8221 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8223 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8226 pAd->CommonCfg.TriggerTimerCount++;
8231 ========================================================================
8232 Routine Description:
8233 Set/reset MAC registers according to bPiggyBack parameter
8236 pAd - Adapter pointer
8237 bPiggyBack - Enable / Disable Piggy-Back
8242 ========================================================================
8244 VOID RTMPSetPiggyBack(
8245 IN PRTMP_ADAPTER pAd,
8246 IN BOOLEAN bPiggyBack)
8248 TX_LINK_CFG_STRUC TxLinkCfg;
8250 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8252 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8253 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8257 ========================================================================
8258 Routine Description:
8259 check if this entry need to switch rate automatically
8269 ========================================================================
8271 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8272 IN PRTMP_ADAPTER pAd,
8273 IN PMAC_TABLE_ENTRY pEntry)
8275 BOOLEAN result = TRUE;
8278 // only associated STA counts
8279 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8281 result = pAd->StaCfg.bAutoTxRateSwitch;
8291 BOOLEAN RTMPAutoRateSwitchCheck(
8292 IN PRTMP_ADAPTER pAd)
8294 if (pAd->StaCfg.bAutoTxRateSwitch)
8302 ========================================================================
8303 Routine Description:
8304 check if this entry need to fix tx legacy rate
8314 ========================================================================
8316 UCHAR RTMPStaFixedTxMode(
8317 IN PRTMP_ADAPTER pAd,
8318 IN PMAC_TABLE_ENTRY pEntry)
8320 UCHAR tx_mode = FIXED_TXMODE_HT;
8323 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8330 ========================================================================
8331 Routine Description:
8332 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8342 ========================================================================
8344 VOID RTMPUpdateLegacyTxSetting(
8345 UCHAR fixed_tx_mode,
8346 PMAC_TABLE_ENTRY pEntry)
8348 HTTRANSMIT_SETTING TransmitSetting;
8350 if (fixed_tx_mode == FIXED_TXMODE_HT)
8353 TransmitSetting.word = 0;
8355 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8356 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8358 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8360 TransmitSetting.field.MODE = MODE_CCK;
8361 // CCK mode allow MCS 0~3
8362 if (TransmitSetting.field.MCS > MCS_3)
8363 TransmitSetting.field.MCS = MCS_3;
8367 TransmitSetting.field.MODE = MODE_OFDM;
8368 // OFDM mode allow MCS 0~7
8369 if (TransmitSetting.field.MCS > MCS_7)
8370 TransmitSetting.field.MCS = MCS_7;
8373 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8375 pEntry->HTPhyMode.word = TransmitSetting.word;
8376 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8377 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8382 ==========================================================================
8384 dynamic tune BBP R66 to find a balance between sensibility and
8387 IRQL = DISPATCH_LEVEL
8389 ==========================================================================
8391 VOID AsicStaBbpTuning(
8392 IN PRTMP_ADAPTER pAd)
8394 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8397 // 2860C did not support Fase CCA, therefore can't tune
8398 if (pAd->MACVersion == 0x28600100)
8404 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8407 if ((pAd->OpMode == OPMODE_STA)
8408 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8410 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8413 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8416 if (pAd->Antenna.field.RxPath > 1)
8417 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8419 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8421 if (pAd->LatchRfRegs.Channel <= 14)
8424 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8425 // Otherwise, it will have some throughput side effect when low RSSI
8433 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8435 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8436 if (OrigR66Value != R66)
8439 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8442 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8448 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8449 if (OrigR66Value != R66)
8452 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8455 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8463 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8465 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8466 if (OrigR66Value != R66)
8468 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8473 R66 = 0x2E + GET_LNA_GAIN(pAd);
8474 if (OrigR66Value != R66)
8476 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8483 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8485 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8487 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8488 if (OrigR66Value != R66)
8490 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8495 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8496 if (OrigR66Value != R66)
8498 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8504 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8506 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8507 if (OrigR66Value != R66)
8509 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8514 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8515 if (OrigR66Value != R66)
8517 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8527 VOID RTMPSetAGCInitValue(
8528 IN PRTMP_ADAPTER pAd,
8533 if (pAd->LatchRfRegs.Channel <= 14)
8535 R66 = 0x2E + GET_LNA_GAIN(pAd);
8536 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8540 if (BandWidth == BW_20)
8542 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8543 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8547 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8548 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8554 VOID AsicTurnOffRFClk(
8555 IN PRTMP_ADAPTER pAd,
8559 UINT32 R1 = 0, R2 = 0, R3 = 0;
8561 RTMP_RF_REGS *RFRegTable;
8564 // The RF programming sequence is difference between 3xxx and 2xxx
8567 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8572 RFRegTable = RF2850RegTable;
8574 switch (pAd->RfIcType)
8581 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8583 if (Channel == RFRegTable[index].Channel)
8585 R1 = RFRegTable[index].R1 & 0xffffdfff;
8586 R2 = RFRegTable[index].R2 & 0xfffbffff;
8587 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8589 RTMP_RF_IO_WRITE32(pAd, R1);
8590 RTMP_RF_IO_WRITE32(pAd, R2);
8592 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8593 // Set RF R2 bit18=0, R3 bit[18:19]=0
8594 //if (pAd->StaCfg.bRadio == FALSE)
8597 RTMP_RF_IO_WRITE32(pAd, R3);
8599 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8600 Channel, pAd->RfIcType, R2, R3));
8603 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8604 Channel, pAd->RfIcType, R2));
8620 VOID AsicTurnOnRFClk(
8621 IN PRTMP_ADAPTER pAd,
8625 UINT32 R1 = 0, R2 = 0, R3 = 0;
8627 RTMP_RF_REGS *RFRegTable;
8630 // The RF programming sequence is difference between 3xxx and 2xxx
8637 RFRegTable = RF2850RegTable;
8639 switch (pAd->RfIcType)
8646 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8648 if (Channel == RFRegTable[index].Channel)
8650 R3 = pAd->LatchRfRegs.R3;
8653 RTMP_RF_IO_WRITE32(pAd, R3);
8655 R1 = RFRegTable[index].R1;
8656 RTMP_RF_IO_WRITE32(pAd, R1);
8658 R2 = RFRegTable[index].R2;
8659 if (pAd->Antenna.field.TxPath == 1)
8661 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8664 if (pAd->Antenna.field.RxPath == 2)
8666 R2 |= 0x40; // write 1 to off Rxpath.
8668 else if (pAd->Antenna.field.RxPath == 1)
8670 R2 |= 0x20040; // write 1 to off RxPath
8672 RTMP_RF_IO_WRITE32(pAd, R2);
8684 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",