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-----------
450 //2008/07/10:KH Modified to share this variable
451 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
454 ==========================================================================
456 initialize the MLME task and its data structure (queue, spinlock,
457 timer, state machines).
462 always return NDIS_STATUS_SUCCESS
464 ==========================================================================
466 NDIS_STATUS MlmeInit(
467 IN PRTMP_ADAPTER pAd)
469 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
471 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
475 Status = MlmeQueueInit(&pAd->Mlme.Queue);
476 if(Status != NDIS_STATUS_SUCCESS)
479 pAd->Mlme.bRunning = FALSE;
480 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
483 BssTableInit(&pAd->ScanTab);
485 // init STA state machines
486 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
487 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
488 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
489 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
490 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
491 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
493 // Since we are using switch/case to implement it, the init is different from the above
494 // state machine init
495 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
498 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
500 // Init mlme periodic timer
501 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
503 // Set mlme periodic timer
504 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
506 // software-based RX Antenna diversity
507 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
510 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
516 ==========================================================================
518 main loop of the MLME
520 Mlme has to be initialized, and there are something inside the queue
522 This function is invoked from MPSetInformation and MPReceive;
523 This task guarantee only one MlmeHandler will run.
525 IRQL = DISPATCH_LEVEL
527 ==========================================================================
530 IN PRTMP_ADAPTER pAd)
532 MLME_QUEUE_ELEM *Elem = NULL;
534 // Only accept MLME and Frame from peer side, no other (control/data) frame should
535 // get into this state machine
537 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
538 if(pAd->Mlme.bRunning)
540 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
545 pAd->Mlme.bRunning = TRUE;
547 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
549 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
551 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
552 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
553 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
555 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
559 //From message type, determine which state machine I should drive
560 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
563 if (Elem->MsgType == MT2_RESET_CONF)
565 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
566 MlmeRestartStateMachine(pAd);
567 Elem->Occupied = FALSE;
573 // if dequeue success
574 switch (Elem->Machine)
576 // STA state machines
577 case ASSOC_STATE_MACHINE:
578 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
580 case AUTH_STATE_MACHINE:
581 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
583 case AUTH_RSP_STATE_MACHINE:
584 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
586 case SYNC_STATE_MACHINE:
587 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
589 case MLME_CNTL_STATE_MACHINE:
590 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
592 case WPA_PSK_STATE_MACHINE:
593 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
595 case AIRONET_STATE_MACHINE:
596 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
598 case ACTION_STATE_MACHINE:
599 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
606 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
611 Elem->Occupied = FALSE;
616 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
620 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
621 pAd->Mlme.bRunning = FALSE;
622 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
626 ==========================================================================
628 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
630 Adapter - NIC Adapter pointer
632 The MLME task will no longer work properly
636 ==========================================================================
639 IN PRTMP_ADAPTER pAd)
643 UINT32 TxPinCfg = 0x00050F0F;
646 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
648 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
650 // disable BEACON generation and other BEACON related hardware timers
651 AsicDisableSync(pAd);
655 // Cancel pending timers
656 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
657 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
658 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
659 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
660 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
661 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
664 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
665 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
669 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
672 RTMPSetLED(pAd, LED_HALT);
673 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
676 LED_CFG_STRUC LedCfg;
677 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
678 LedCfg.field.LedPolar = 0;
679 LedCfg.field.RLedMode = 0;
680 LedCfg.field.GLedMode = 0;
681 LedCfg.field.YLedMode = 0;
682 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
689 if (IS_RT3070(pAd) || IS_RT3071(pAd))
691 TxPinCfg &= 0xFFFFF0F0;
692 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
697 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
699 MlmeQueueDestroy(&pAd->Mlme.Queue);
700 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
702 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
705 VOID MlmeResetRalinkCounters(
706 IN PRTMP_ADAPTER pAd)
708 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
709 // clear all OneSecxxx counters.
710 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
711 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
712 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
713 pAd->RalinkCounters.OneSecRxOkCnt = 0;
714 pAd->RalinkCounters.OneSecTxFailCount = 0;
715 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
716 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
717 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
719 // TODO: for debug only. to be removed
720 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
721 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
722 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
723 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
724 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
725 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
726 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
727 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
728 pAd->RalinkCounters.OneSecTxDoneCount = 0;
729 pAd->RalinkCounters.OneSecRxCount = 0;
730 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
731 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
736 unsigned long rx_AMSDU;
737 unsigned long rx_Total;
740 ==========================================================================
742 This routine is executed periodically to -
743 1. Decide if it's a right time to turn on PwrMgmt bit of all
745 2. Calculate ChannelQuality based on statistics of the last
746 period, so that TX rate won't toggling very frequently between a
747 successful TX and a failed TX.
748 3. If the calculated ChannelQuality indicated current connection not
749 healthy, then a ROAMing attempt is tried here.
751 IRQL = DISPATCH_LEVEL
753 ==========================================================================
755 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
756 VOID MlmePeriodicExec(
757 IN PVOID SystemSpecific1,
758 IN PVOID FunctionContext,
759 IN PVOID SystemSpecific2,
760 IN PVOID SystemSpecific3)
763 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
765 // Do nothing if the driver is starting halt state.
766 // This might happen when timer already been fired before cancel timer with mlmehalt
767 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
768 fRTMP_ADAPTER_RADIO_OFF |
769 fRTMP_ADAPTER_RADIO_MEASUREMENT |
770 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
773 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
776 // Do nothing if monitor mode is on
780 if (pAd->Mlme.PeriodicRound & 0x1)
782 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
783 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
784 (STA_TGN_WIFI_ON(pAd)) &&
785 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
788 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
789 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
791 else if ((STA_TGN_WIFI_ON(pAd)) &&
792 ((pAd->MACVersion & 0xffff) == 0x0101))
794 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
795 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
800 pAd->bUpdateBcnCntDone = FALSE;
802 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
803 pAd->Mlme.PeriodicRound ++;
806 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
807 NICUpdateFifoStaCounters(pAd);
809 // execute every 500ms
810 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
812 // perform dynamic tx rate switching based on past TX history
814 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
816 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
817 MlmeDynamicTxRateSwitching(pAd);
821 // Normal 1 second Mlme PeriodicExec.
822 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
824 pAd->Mlme.OneSecPeriodicRound ++;
834 // Media status changed, report to NDIS
835 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
837 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
838 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
840 pAd->IndicateMediaState = NdisMediaStateConnected;
841 RTMP_IndicateMediaState(pAd);
846 pAd->IndicateMediaState = NdisMediaStateDisconnected;
847 RTMP_IndicateMediaState(pAd);
851 NdisGetSystemUpTime(&pAd->Mlme.Now32);
853 // add the most up-to-date h/w raw counters into software variable, so that
854 // the dynamic tuning mechanism below are based on most up-to-date information
855 NICUpdateRawCounters(pAd);
858 RT2870_WatchDog(pAd);
861 // Need statistics after read counter. So put after NICUpdateRawCounters
862 ORIBATimerTimeout(pAd);
864 // The time period for checking antenna is according to traffic
866 if (pAd->Mlme.bEnableAutoAntennaCheck)
868 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
869 pAd->RalinkCounters.OneSecTxRetryOkCount +
870 pAd->RalinkCounters.OneSecTxFailCount;
872 // dynamic adjust antenna evaluation period according to the traffic
875 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
877 AsicEvaluateRxAnt(pAd);
882 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
884 AsicEvaluateRxAnt(pAd);
890 STAMlmePeriodicExec(pAd);
892 MlmeResetRalinkCounters(pAd);
896 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
897 // and sending CTS-to-self over and over.
898 // Software Patch Solution:
899 // 1. Polling debug state register 0x10F4 every one second.
900 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
901 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
905 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
906 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
908 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
910 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
912 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
917 RT28XX_MLME_HANDLER(pAd);
921 pAd->bUpdateBcnCntDone = FALSE;
924 VOID STAMlmePeriodicExec(
930 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
932 // WPA MIC error should block association attempt for 60 seconds
933 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
934 pAd->StaCfg.bBlockAssoc = FALSE;
937 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
939 if (pAd->IndicateMediaState == NdisMediaStateConnected)
941 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
943 pAd->PreMediaState = pAd->IndicateMediaState;
949 AsicStaBbpTuning(pAd);
951 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
952 pAd->RalinkCounters.OneSecTxRetryOkCount +
953 pAd->RalinkCounters.OneSecTxFailCount;
955 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
957 // update channel quality for Roaming and UI LinkQuality display
958 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
961 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
962 // Radio is currently in noisy environment
963 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
964 AsicAdjustTxPower(pAd);
968 // Is PSM bit consistent with user power management policy?
969 // This is the only place that will set PSM bit ON.
970 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
971 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
973 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
975 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
976 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
977 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
979 RTMPSetAGCInitValue(pAd, BW_20);
980 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
984 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
986 // When APSD is enabled, the period changes as 20 sec
987 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
988 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
992 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
993 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
995 if (pAd->CommonCfg.bWmmCapable)
996 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
998 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1003 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1005 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1006 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1007 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1009 // Lost AP, send disconnect & link down event
1010 LinkDown(pAd, FALSE);
1013 union iwreq_data wrqu;
1014 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1015 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1018 MlmeAutoReconnectLastSSID(pAd);
1020 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1022 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1023 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1024 MlmeAutoReconnectLastSSID(pAd);
1027 // Add auto seamless roaming
1028 if (pAd->StaCfg.bFastRoaming)
1030 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1032 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));
1034 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1036 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1040 else if (ADHOC_ON(pAd))
1043 if ((pAd->CommonCfg.Channel > 14)
1044 && (pAd->CommonCfg.bIEEE80211H == 1)
1045 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1047 RadarDetectPeriodic(pAd);
1050 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1051 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1053 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1054 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1056 MLME_START_REQ_STRUCT StartReq;
1058 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1059 LinkDown(pAd, FALSE);
1061 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1062 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1063 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1066 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1068 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1070 if (pEntry->ValidAsCLI == FALSE)
1073 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1074 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1077 else // no INFRA nor ADHOC connection
1080 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1081 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1082 goto SKIP_AUTO_SCAN_CONN;
1084 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1086 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1087 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1088 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1090 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1092 MLME_SCAN_REQ_STRUCT ScanReq;
1094 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1096 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1097 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1098 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1099 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1100 // Reset Missed scan number
1101 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1103 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1104 MlmeAutoReconnectLastSSID(pAd);
1106 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1108 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1111 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1115 MlmeAutoReconnectLastSSID(pAd);
1121 SKIP_AUTO_SCAN_CONN:
1123 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1125 pAd->MacTab.fAnyBASession = TRUE;
1126 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1128 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1130 pAd->MacTab.fAnyBASession = FALSE;
1131 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1139 IN PVOID SystemSpecific1,
1140 IN PVOID FunctionContext,
1141 IN PVOID SystemSpecific2,
1142 IN PVOID SystemSpecific3)
1145 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1147 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1148 RTMP_IndicateMediaState(pAd);
1149 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1152 // IRQL = DISPATCH_LEVEL
1154 IN PRTMP_ADAPTER pAd)
1156 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1157 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1159 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1161 MLME_CNTL_STATE_MACHINE,
1162 OID_802_11_BSSID_LIST_SCAN,
1165 RT28XX_MLME_HANDLER(pAd);
1169 // IRQL = DISPATCH_LEVEL
1170 VOID MlmeAutoReconnectLastSSID(
1171 IN PRTMP_ADAPTER pAd)
1175 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1176 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1177 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1179 NDIS_802_11_SSID OidSsid;
1180 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1181 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1183 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1185 MLME_CNTL_STATE_MACHINE,
1187 sizeof(NDIS_802_11_SSID),
1189 RT28XX_MLME_HANDLER(pAd);
1194 ==========================================================================
1195 Validate SSID for connection try and rescan purpose
1196 Valid SSID will have visible chars only.
1197 The valid length is from 0 to 32.
1198 IRQL = DISPATCH_LEVEL
1199 ==========================================================================
1201 BOOLEAN MlmeValidateSSID(
1207 if (SsidLen > MAX_LEN_OF_SSID)
1210 // Check each character value
1211 for (index = 0; index < SsidLen; index++)
1213 if (pSsid[index] < 0x20)
1221 VOID MlmeSelectTxRateTable(
1222 IN PRTMP_ADAPTER pAd,
1223 IN PMAC_TABLE_ENTRY pEntry,
1225 IN PUCHAR pTableSize,
1226 IN PUCHAR pInitTxRateIdx)
1230 // decide the rate table for tuning
1231 if (pAd->CommonCfg.TxRateTableSize > 0)
1233 *ppTable = RateSwitchTable;
1234 *pTableSize = RateSwitchTable[0];
1235 *pInitTxRateIdx = RateSwitchTable[1];
1240 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1242 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1243 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1244 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1246 *ppTable = RateSwitchTable11N1S;
1247 *pTableSize = RateSwitchTable11N1S[0];
1248 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1251 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1252 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1253 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1254 (pAd->Antenna.field.TxPath == 2))
1256 if (pAd->LatchRfRegs.Channel <= 14)
1258 *ppTable = RateSwitchTable11N2S;
1259 *pTableSize = RateSwitchTable11N2S[0];
1260 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1264 *ppTable = RateSwitchTable11N2SForABand;
1265 *pTableSize = RateSwitchTable11N2SForABand[0];
1266 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1271 if ((pEntry->RateLen == 4)
1272 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1275 *ppTable = RateSwitchTable11B;
1276 *pTableSize = RateSwitchTable11B[0];
1277 *pInitTxRateIdx = RateSwitchTable11B[1];
1280 else if (pAd->LatchRfRegs.Channel <= 14)
1282 *ppTable = RateSwitchTable11BG;
1283 *pTableSize = RateSwitchTable11BG[0];
1284 *pInitTxRateIdx = RateSwitchTable11BG[1];
1289 *ppTable = RateSwitchTable11G;
1290 *pTableSize = RateSwitchTable11G[0];
1291 *pInitTxRateIdx = RateSwitchTable11G[1];
1297 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1298 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1300 *ppTable = RateSwitchTable11BGN1S;
1301 *pTableSize = RateSwitchTable11BGN1S[0];
1302 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1307 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1308 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1310 if (pAd->LatchRfRegs.Channel <= 14)
1312 *ppTable = RateSwitchTable11BGN2S;
1313 *pTableSize = RateSwitchTable11BGN2S[0];
1314 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1319 *ppTable = RateSwitchTable11BGN2SForABand;
1320 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1321 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1327 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1329 *ppTable = RateSwitchTable11N1S;
1330 *pTableSize = RateSwitchTable11N1S[0];
1331 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1336 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1338 if (pAd->LatchRfRegs.Channel <= 14)
1340 *ppTable = RateSwitchTable11N2S;
1341 *pTableSize = RateSwitchTable11N2S[0];
1342 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1346 *ppTable = RateSwitchTable11N2SForABand;
1347 *pTableSize = RateSwitchTable11N2SForABand[0];
1348 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1354 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1355 if ((pEntry->RateLen == 4)
1356 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1357 // && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1360 *ppTable = RateSwitchTable11B;
1361 *pTableSize = RateSwitchTable11B[0];
1362 *pInitTxRateIdx = RateSwitchTable11B[1];
1367 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1368 if ((pEntry->RateLen > 8)
1369 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1372 *ppTable = RateSwitchTable11BG;
1373 *pTableSize = RateSwitchTable11BG[0];
1374 *pInitTxRateIdx = RateSwitchTable11BG[1];
1379 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1380 if ((pEntry->RateLen == 8)
1381 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1384 *ppTable = RateSwitchTable11G;
1385 *pTableSize = RateSwitchTable11G[0];
1386 *pInitTxRateIdx = RateSwitchTable11G[1];
1392 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1393 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1395 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1397 *ppTable = RateSwitchTable11B;
1398 *pTableSize = RateSwitchTable11B[0];
1399 *pInitTxRateIdx = RateSwitchTable11B[1];
1401 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1403 *ppTable = RateSwitchTable11G;
1404 *pTableSize = RateSwitchTable11G[0];
1405 *pInitTxRateIdx = RateSwitchTable11G[1];
1410 *ppTable = RateSwitchTable11BG;
1411 *pTableSize = RateSwitchTable11BG[0];
1412 *pInitTxRateIdx = RateSwitchTable11BG[1];
1417 if (pAd->LatchRfRegs.Channel <= 14)
1419 if (pAd->CommonCfg.TxStream == 1)
1421 *ppTable = RateSwitchTable11N1S;
1422 *pTableSize = RateSwitchTable11N1S[0];
1423 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1424 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1428 *ppTable = RateSwitchTable11N2S;
1429 *pTableSize = RateSwitchTable11N2S[0];
1430 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1431 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1436 if (pAd->CommonCfg.TxStream == 1)
1438 *ppTable = RateSwitchTable11N1S;
1439 *pTableSize = RateSwitchTable11N1S[0];
1440 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1441 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1445 *ppTable = RateSwitchTable11N2SForABand;
1446 *pTableSize = RateSwitchTable11N2SForABand[0];
1447 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1448 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1452 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1453 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1459 ==========================================================================
1461 This routine checks if there're other APs out there capable for
1462 roaming. Caller should call this routine only when Link up in INFRA mode
1463 and channel quality is below CQI_GOOD_THRESHOLD.
1465 IRQL = DISPATCH_LEVEL
1468 ==========================================================================
1470 VOID MlmeCheckForRoaming(
1471 IN PRTMP_ADAPTER pAd,
1475 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1478 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1479 // put all roaming candidates into RoamTab, and sort in RSSI order
1480 BssTableInit(pRoamTab);
1481 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1483 pBss = &pAd->ScanTab.BssEntry[i];
1485 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1486 continue; // AP disappear
1487 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1488 continue; // RSSI too weak. forget it.
1489 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1490 continue; // skip current AP
1491 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1492 continue; // only AP with stronger RSSI is eligible for roaming
1494 // AP passing all above rules is put into roaming candidate table
1495 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1496 pRoamTab->BssNr += 1;
1499 if (pRoamTab->BssNr > 0)
1501 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1502 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1504 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1505 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1506 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1507 RT28XX_MLME_HANDLER(pAd);
1510 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1514 ==========================================================================
1516 This routine checks if there're other APs out there capable for
1517 roaming. Caller should call this routine only when link up in INFRA mode
1518 and channel quality is below CQI_GOOD_THRESHOLD.
1520 IRQL = DISPATCH_LEVEL
1523 ==========================================================================
1525 VOID MlmeCheckForFastRoaming(
1526 IN PRTMP_ADAPTER pAd,
1530 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1533 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1534 // put all roaming candidates into RoamTab, and sort in RSSI order
1535 BssTableInit(pRoamTab);
1536 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1538 pBss = &pAd->ScanTab.BssEntry[i];
1540 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1541 continue; // RSSI too weak. forget it.
1542 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1543 continue; // skip current AP
1544 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1545 continue; // skip different SSID
1546 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1547 continue; // skip AP without better RSSI
1549 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));
1550 // AP passing all above rules is put into roaming candidate table
1551 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1552 pRoamTab->BssNr += 1;
1555 if (pRoamTab->BssNr > 0)
1557 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1558 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1560 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1561 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1562 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1563 RT28XX_MLME_HANDLER(pAd);
1566 // Maybe site survey required
1569 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1571 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1572 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1573 pAd->StaCfg.ScanCnt = 2;
1574 pAd->StaCfg.LastScanTime = Now;
1579 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1583 ==========================================================================
1585 This routine calculates TxPER, RxPER of the past N-sec period. And
1586 according to the calculation result, ChannelQuality is calculated here
1587 to decide if current AP is still doing the job.
1589 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1591 StaCfg.ChannelQuality - 0..100
1593 IRQL = DISPATCH_LEVEL
1595 NOTE: This routine decide channle quality based on RX CRC error ratio.
1596 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1597 is performed right before this routine, so that this routine can decide
1598 channel quality based on the most up-to-date information
1599 ==========================================================================
1601 VOID MlmeCalculateChannelQuality(
1602 IN PRTMP_ADAPTER pAd,
1605 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1609 ULONG BeaconLostTime = BEACON_LOST_TIME;
1611 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1614 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1616 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1617 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1625 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1626 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1630 // calculate RX PER - don't take RxPER into consideration if too few sample
1632 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1636 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1639 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1641 if (INFRA_ON(pAd) &&
1642 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1643 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1645 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1646 pAd->Mlme.ChannelQuality = 0;
1653 else if (MaxRssi < -90)
1656 NorRssi = (MaxRssi + 90) * 2;
1658 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1659 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1660 TX_WEIGHTING * (100 - TxPRR) +
1661 RX_WEIGHTING* (100 - RxPER)) / 100;
1662 if (pAd->Mlme.ChannelQuality >= 100)
1663 pAd->Mlme.ChannelQuality = 100;
1669 IN PRTMP_ADAPTER pAd,
1670 IN PMAC_TABLE_ENTRY pEntry,
1671 IN PRTMP_TX_RATE_SWITCH pTxRate)
1673 UCHAR MaxMode = MODE_OFDM;
1675 MaxMode = MODE_HTGREENFIELD;
1677 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1678 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1680 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1682 if (pTxRate->CurrMCS < MCS_AUTO)
1683 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1685 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1686 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1690 // If peer adhoc is b-only mode, we can't send 11g rate.
1691 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1692 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1695 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1697 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1698 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1699 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1701 // Patch speed error in status page
1702 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1706 if (pTxRate->Mode <= MaxMode)
1707 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1709 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1710 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1712 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1714 // Reexam each bandwidth's SGI support.
1715 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1717 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1718 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1719 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1720 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1723 // Turn RTS/CTS rate to 6Mbps.
1724 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1726 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1727 if (pAd->MacTab.fAnyBASession)
1729 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1733 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1736 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1738 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1739 if (pAd->MacTab.fAnyBASession)
1741 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1745 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1748 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1750 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1753 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1755 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1758 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1759 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1760 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1761 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1763 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1764 pAd->WIFItestbed.bGreenField)
1765 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1768 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1772 ==========================================================================
1774 This routine calculates the acumulated TxPER of eaxh TxRate. And
1775 according to the calculation result, change CommonCfg.TxRate which
1776 is the stable TX Rate we expect the Radio situation could sustained.
1778 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1782 IRQL = DISPATCH_LEVEL
1785 call this routine every second
1786 ==========================================================================
1788 VOID MlmeDynamicTxRateSwitching(
1789 IN PRTMP_ADAPTER pAd)
1791 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1792 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1793 ULONG TxErrorRatio = 0;
1794 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1795 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1797 UCHAR TableSize = 0;
1798 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1799 CHAR Rssi, RssiOffset = 0;
1800 TX_STA_CNT1_STRUC StaTx1;
1801 TX_STA_CNT0_STRUC TxStaCnt0;
1802 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1803 MAC_TABLE_ENTRY *pEntry;
1806 // walk through MAC table, see if need to change AP's TX rate toward each entry
1808 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1810 pEntry = &pAd->MacTab.Content[i];
1812 // check if this entry need to switch rate automatically
1813 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1816 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1818 Rssi = RTMPMaxRssi(pAd,
1819 pAd->StaCfg.RssiSample.AvgRssi0,
1820 pAd->StaCfg.RssiSample.AvgRssi1,
1821 pAd->StaCfg.RssiSample.AvgRssi2);
1823 // Update statistic counter
1824 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1825 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1826 pAd->bUpdateBcnCntDone = TRUE;
1827 TxRetransmit = StaTx1.field.TxRetransmit;
1828 TxSuccess = StaTx1.field.TxSuccess;
1829 TxFailCount = TxStaCnt0.field.TxFailCount;
1830 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1832 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1833 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1834 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1835 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1836 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1837 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1839 // if no traffic in the past 1-sec period, don't change TX rate,
1840 // but clear all bad history. because the bad history may affect the next
1841 // Chariot throughput test
1842 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1843 pAd->RalinkCounters.OneSecTxRetryOkCount +
1844 pAd->RalinkCounters.OneSecTxFailCount;
1847 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1851 if (INFRA_ON(pAd) && (i == 1))
1852 Rssi = RTMPMaxRssi(pAd,
1853 pAd->StaCfg.RssiSample.AvgRssi0,
1854 pAd->StaCfg.RssiSample.AvgRssi1,
1855 pAd->StaCfg.RssiSample.AvgRssi2);
1857 Rssi = RTMPMaxRssi(pAd,
1858 pEntry->RssiSample.AvgRssi0,
1859 pEntry->RssiSample.AvgRssi1,
1860 pEntry->RssiSample.AvgRssi2);
1862 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1863 pEntry->OneSecTxRetryOkCount +
1864 pEntry->OneSecTxFailCount;
1867 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1870 CurrRateIdx = pEntry->CurrTxRateIndex;
1872 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1874 if (CurrRateIdx >= TableSize)
1876 CurrRateIdx = TableSize - 1;
1879 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1880 // So need to sync here.
1881 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1882 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1883 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1887 // Need to sync Real Tx rate and our record.
1888 // Then return for next DRS.
1889 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1890 pEntry->CurrTxRateIndex = InitTxRateIdx;
1891 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1893 // reset all OneSecTx counters
1894 RESET_ONE_SEC_TX_CNT(pEntry);
1898 // decide the next upgrade rate and downgrade rate, if any
1899 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
1901 UpRateIdx = CurrRateIdx + 1;
1902 DownRateIdx = CurrRateIdx -1;
1904 else if (CurrRateIdx == 0)
1906 UpRateIdx = CurrRateIdx + 1;
1907 DownRateIdx = CurrRateIdx;
1909 else if (CurrRateIdx == (TableSize - 1))
1911 UpRateIdx = CurrRateIdx;
1912 DownRateIdx = CurrRateIdx - 1;
1915 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1917 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
1919 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
1920 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
1924 TrainUp = pCurrTxRate->TrainUp;
1925 TrainDown = pCurrTxRate->TrainDown;
1928 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
1931 // Keep the last time TxRateChangeAction status.
1933 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
1938 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
1939 // (criteria copied from RT2500 for Netopia case)
1941 if (TxTotalCnt <= 15)
1945 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1946 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
1947 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1948 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
1950 // check the existence and index of each needed MCS
1951 while (idx < pTable[0])
1953 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
1955 if (pCurrTxRate->CurrMCS == MCS_0)
1959 else if (pCurrTxRate->CurrMCS == MCS_1)
1963 else if (pCurrTxRate->CurrMCS == MCS_2)
1967 else if (pCurrTxRate->CurrMCS == MCS_3)
1971 else if (pCurrTxRate->CurrMCS == MCS_4)
1975 else if (pCurrTxRate->CurrMCS == MCS_5)
1979 else if (pCurrTxRate->CurrMCS == MCS_6)
1983 //else if (pCurrTxRate->CurrMCS == MCS_7)
1984 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
1988 else if (pCurrTxRate->CurrMCS == MCS_12)
1992 else if (pCurrTxRate->CurrMCS == MCS_13)
1996 else if (pCurrTxRate->CurrMCS == MCS_14)
2000 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800))
2004 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2008 else if (pCurrTxRate->CurrMCS == MCS_21)
2012 else if (pCurrTxRate->CurrMCS == MCS_22)
2016 else if (pCurrTxRate->CurrMCS == MCS_23)
2023 if (pAd->LatchRfRegs.Channel <= 14)
2025 if (pAd->NicConfig2.field.ExternalLNAForG)
2036 if (pAd->NicConfig2.field.ExternalLNAForA)
2047 if ((pTable == RateSwitchTable11BGN3S) ||
2048 (pTable == RateSwitchTable11N3S) ||
2049 (pTable == RateSwitchTable))
2050 {// N mode with 3 stream // 3*3
2051 if (MCS23 && (Rssi >= -70))
2053 else if (MCS22 && (Rssi >= -72))
2055 else if (MCS21 && (Rssi >= -76))
2057 else if (MCS20 && (Rssi >= -78))
2059 else if (MCS4 && (Rssi >= -82))
2061 else if (MCS3 && (Rssi >= -84))
2063 else if (MCS2 && (Rssi >= -86))
2065 else if (MCS1 && (Rssi >= -88))
2070 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2071 {// N mode with 2 stream
2072 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2074 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2076 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2078 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2080 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2082 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2084 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2086 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2091 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2092 {// N mode with 1 stream
2093 if (MCS7 && (Rssi > (-72+RssiOffset)))
2095 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2097 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2099 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2101 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2103 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2105 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2112 if (MCS7 && (Rssi > -70))
2114 else if (MCS6 && (Rssi > -74))
2116 else if (MCS5 && (Rssi > -78))
2118 else if (MCS4 && (Rssi > -82))
2120 else if (MCS4 == 0) // for B-only mode
2122 else if (MCS3 && (Rssi > -85))
2124 else if (MCS2 && (Rssi > -87))
2126 else if (MCS1 && (Rssi > -90))
2133 pEntry->CurrTxRateIndex = TxRateIdx;
2134 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2135 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2138 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2139 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2140 pEntry->fLastSecAccordingRSSI = TRUE;
2141 // reset all OneSecTx counters
2142 RESET_ONE_SEC_TX_CNT(pEntry);
2147 if (pEntry->fLastSecAccordingRSSI == TRUE)
2149 pEntry->fLastSecAccordingRSSI = FALSE;
2150 pEntry->LastSecTxRateChangeAction = 0;
2151 // reset all OneSecTx counters
2152 RESET_ONE_SEC_TX_CNT(pEntry);
2159 BOOLEAN bTrainUpDown = FALSE;
2161 pEntry->CurrTxRateStableTime ++;
2163 // downgrade TX quality if PER >= Rate-Down threshold
2164 if (TxErrorRatio >= TrainDown)
2166 bTrainUpDown = TRUE;
2167 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2169 // upgrade TX quality if PER <= Rate-Up threshold
2170 else if (TxErrorRatio <= TrainUp)
2172 bTrainUpDown = TRUE;
2173 bUpgradeQuality = TRUE;
2174 if (pEntry->TxQuality[CurrRateIdx])
2175 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2177 if (pEntry->TxRateUpPenalty)
2178 pEntry->TxRateUpPenalty --;
2179 else if (pEntry->TxQuality[UpRateIdx])
2180 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2183 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2187 // perform DRS - consider TxRate Down first, then rate up.
2188 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2190 pEntry->CurrTxRateIndex = DownRateIdx;
2192 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2194 pEntry->CurrTxRateIndex = UpRateIdx;
2199 // if rate-up happen, clear all bad history of all TX rates
2200 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2202 pEntry->CurrTxRateStableTime = 0;
2203 pEntry->TxRateUpPenalty = 0;
2204 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2205 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2206 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2209 // For TxRate fast train up
2211 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2213 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2215 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2217 bTxRateChanged = TRUE;
2219 // if rate-down happen, only clear DownRate's bad history
2220 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2222 pEntry->CurrTxRateStableTime = 0;
2223 pEntry->TxRateUpPenalty = 0; // no penalty
2224 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2225 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2226 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2229 // For TxRate fast train down
2231 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2233 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2235 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2237 bTxRateChanged = TRUE;
2241 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2242 bTxRateChanged = FALSE;
2245 pEntry->LastTxOkCount = TxSuccess;
2247 // reset all OneSecTx counters
2248 RESET_ONE_SEC_TX_CNT(pEntry);
2250 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2251 if (bTxRateChanged && pNextTxRate)
2253 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2259 ========================================================================
2260 Routine Description:
2261 Station side, Auto TxRate faster train up timer call back function.
2264 SystemSpecific1 - Not used.
2265 FunctionContext - Pointer to our Adapter context.
2266 SystemSpecific2 - Not used.
2267 SystemSpecific3 - Not used.
2272 ========================================================================
2274 VOID StaQuickResponeForRateUpExec(
2275 IN PVOID SystemSpecific1,
2276 IN PVOID FunctionContext,
2277 IN PVOID SystemSpecific2,
2278 IN PVOID SystemSpecific3)
2280 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2281 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2283 ULONG TxErrorRatio = 0;
2284 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2285 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2287 UCHAR TableSize = 0;
2288 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2289 TX_STA_CNT1_STRUC StaTx1;
2290 TX_STA_CNT0_STRUC TxStaCnt0;
2292 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2293 MAC_TABLE_ENTRY *pEntry;
2296 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2299 // walk through MAC table, see if need to change AP's TX rate toward each entry
2301 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2303 pEntry = &pAd->MacTab.Content[i];
2305 // check if this entry need to switch rate automatically
2306 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2309 if (INFRA_ON(pAd) && (i == 1))
2310 Rssi = RTMPMaxRssi(pAd,
2311 pAd->StaCfg.RssiSample.AvgRssi0,
2312 pAd->StaCfg.RssiSample.AvgRssi1,
2313 pAd->StaCfg.RssiSample.AvgRssi2);
2315 Rssi = RTMPMaxRssi(pAd,
2316 pEntry->RssiSample.AvgRssi0,
2317 pEntry->RssiSample.AvgRssi1,
2318 pEntry->RssiSample.AvgRssi2);
2320 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2322 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2324 // decide the next upgrade rate and downgrade rate, if any
2325 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2327 UpRateIdx = CurrRateIdx + 1;
2328 DownRateIdx = CurrRateIdx -1;
2330 else if (CurrRateIdx == 0)
2332 UpRateIdx = CurrRateIdx + 1;
2333 DownRateIdx = CurrRateIdx;
2335 else if (CurrRateIdx == (TableSize - 1))
2337 UpRateIdx = CurrRateIdx;
2338 DownRateIdx = CurrRateIdx - 1;
2341 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2343 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2345 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2346 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2350 TrainUp = pCurrTxRate->TrainUp;
2351 TrainDown = pCurrTxRate->TrainDown;
2354 if (pAd->MacTab.Size == 1)
2356 // Update statistic counter
2357 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2358 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2360 TxRetransmit = StaTx1.field.TxRetransmit;
2361 TxSuccess = StaTx1.field.TxSuccess;
2362 TxFailCount = TxStaCnt0.field.TxFailCount;
2363 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2365 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2366 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2367 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2368 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2369 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2370 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2373 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2377 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2378 pEntry->OneSecTxRetryOkCount +
2379 pEntry->OneSecTxFailCount;
2382 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2387 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2388 // (criteria copied from RT2500 for Netopia case)
2390 if (TxTotalCnt <= 12)
2392 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2393 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2395 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2397 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2398 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2400 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2402 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2405 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2411 ULONG OneSecTxNoRetryOKRationCount;
2413 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2418 // downgrade TX quality if PER >= Rate-Down threshold
2419 if (TxErrorRatio >= TrainDown)
2421 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2424 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2426 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2428 // perform DRS - consider TxRate Down first, then rate up.
2429 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2431 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2433 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2434 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2439 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2441 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2445 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2447 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2452 // if rate-up happen, clear all bad history of all TX rates
2453 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2455 pAd->DrsCounters.TxRateUpPenalty = 0;
2456 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2457 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2458 bTxRateChanged = TRUE;
2460 // if rate-down happen, only clear DownRate's bad history
2461 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2463 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2465 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2466 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2467 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2468 bTxRateChanged = TRUE;
2472 bTxRateChanged = FALSE;
2475 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2476 if (bTxRateChanged && pNextTxRate)
2478 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2484 ==========================================================================
2486 This routine is executed periodically inside MlmePeriodicExec() after
2487 association with an AP.
2488 It checks if StaCfg.Psm is consistent with user policy (recorded in
2489 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2490 there're some conditions to consider:
2491 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2492 the time when Mibss==TRUE
2493 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2494 if outgoing traffic available in TxRing or MgmtRing.
2496 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2498 IRQL = DISPATCH_LEVEL
2500 ==========================================================================
2502 VOID MlmeCheckPsmChange(
2503 IN PRTMP_ADAPTER pAd,
2509 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2510 // 2. user wants either MAX_PSP or FAST_PSP
2511 // 3. but current psm is not in PWR_SAVE
2512 // 4. CNTL state machine is not doing SCANning
2513 // 5. no TX SUCCESS event for the past 1-sec period
2514 #ifdef NDIS51_MINIPORT
2515 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2516 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2519 PowerMode = pAd->StaCfg.WindowsPowerMode;
2521 if (INFRA_ON(pAd) &&
2522 (PowerMode != Ndis802_11PowerModeCAM) &&
2523 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2524 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2525 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2526 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2527 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2529 // add by johnli, use Rx OK data count per second to calculate throughput
2530 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2531 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2532 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2534 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2536 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2537 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2539 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2541 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2544 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2545 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2546 MlmeSetPsmBit(pAd, PWR_SAVE);
2547 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2549 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2553 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2559 // IRQL = PASSIVE_LEVEL
2560 // IRQL = DISPATCH_LEVEL
2562 IN PRTMP_ADAPTER pAd,
2565 AUTO_RSP_CFG_STRUC csr4;
2567 pAd->StaCfg.Psm = psm;
2568 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2569 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2570 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2573 // IRQL = DISPATCH_LEVEL
2574 VOID MlmeSetTxPreamble(
2575 IN PRTMP_ADAPTER pAd,
2576 IN USHORT TxPreamble)
2578 AUTO_RSP_CFG_STRUC csr4;
2581 // Always use Long preamble before verifiation short preamble functionality works well.
2582 // Todo: remove the following line if short preamble functionality works
2584 //TxPreamble = Rt802_11PreambleLong;
2586 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2587 if (TxPreamble == Rt802_11PreambleLong)
2589 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2590 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2591 csr4.field.AutoResponderPreamble = 0;
2595 // NOTE: 1Mbps should always use long preamble
2596 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2597 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2598 csr4.field.AutoResponderPreamble = 1;
2601 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2605 ==========================================================================
2607 Update basic rate bitmap
2608 ==========================================================================
2611 VOID UpdateBasicRateBitmap(
2612 IN PRTMP_ADAPTER pAdapter)
2615 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2616 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2617 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2618 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2619 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2622 /* if A mode, always use fix BasicRateBitMap */
2623 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2624 if (pAdapter->CommonCfg.Channel > 14)
2625 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2628 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2630 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2634 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2640 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2642 if (bitmap & (1 << i))
2644 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2646 if (sup_p[j] == rate[i])
2651 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2653 if (ext_p[j] == rate[i])
2659 } /* End of UpdateBasicRateBitmap */
2661 // IRQL = PASSIVE_LEVEL
2662 // IRQL = DISPATCH_LEVEL
2663 // bLinkUp is to identify the inital link speed.
2664 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2665 VOID MlmeUpdateTxRates(
2666 IN PRTMP_ADAPTER pAd,
2671 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2672 UCHAR MinSupport = RATE_54;
2673 ULONG BasicRateBitmap = 0;
2674 UCHAR CurrBasicRate = RATE_1;
2675 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2676 PHTTRANSMIT_SETTING pHtPhy = NULL;
2677 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2678 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2679 BOOLEAN *auto_rate_cur_p;
2680 UCHAR HtMcs = MCS_AUTO;
2682 // find max desired rate
2683 UpdateBasicRateBitmap(pAd);
2686 auto_rate_cur_p = NULL;
2687 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2689 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2691 case 2: Rate = RATE_1; num++; break;
2692 case 4: Rate = RATE_2; num++; break;
2693 case 11: Rate = RATE_5_5; num++; break;
2694 case 22: Rate = RATE_11; num++; break;
2695 case 12: Rate = RATE_6; num++; break;
2696 case 18: Rate = RATE_9; num++; break;
2697 case 24: Rate = RATE_12; num++; break;
2698 case 36: Rate = RATE_18; num++; break;
2699 case 48: Rate = RATE_24; num++; break;
2700 case 72: Rate = RATE_36; num++; break;
2701 case 96: Rate = RATE_48; num++; break;
2702 case 108: Rate = RATE_54; num++; break;
2703 //default: Rate = RATE_1; break;
2705 if (MaxDesire < Rate) MaxDesire = Rate;
2708 //===========================================================================
2709 //===========================================================================
2711 pHtPhy = &pAd->StaCfg.HTPhyMode;
2712 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2713 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2715 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2716 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2718 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2719 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2720 (MaxDesire > RATE_11))
2722 MaxDesire = RATE_11;
2726 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2727 pMinHtPhy->word = 0;
2728 pMaxHtPhy->word = 0;
2731 // Auto rate switching is enabled only if more than one DESIRED RATES are
2732 // specified; otherwise disabled
2735 *auto_rate_cur_p = FALSE;
2739 *auto_rate_cur_p = TRUE;
2743 if (HtMcs != MCS_AUTO)
2745 *auto_rate_cur_p = FALSE;
2749 *auto_rate_cur_p = TRUE;
2753 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2755 pSupRate = &pAd->StaActive.SupRate[0];
2756 pExtRate = &pAd->StaActive.ExtRate[0];
2757 SupRateLen = pAd->StaActive.SupRateLen;
2758 ExtRateLen = pAd->StaActive.ExtRateLen;
2762 pSupRate = &pAd->CommonCfg.SupRate[0];
2763 pExtRate = &pAd->CommonCfg.ExtRate[0];
2764 SupRateLen = pAd->CommonCfg.SupRateLen;
2765 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2768 // find max supported rate
2769 for (i=0; i<SupRateLen; i++)
2771 switch (pSupRate[i] & 0x7f)
2773 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2774 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2775 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2776 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2777 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2778 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2779 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2780 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2781 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2782 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2783 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2784 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2785 default: Rate = RATE_1; break;
2787 if (MaxSupport < Rate) MaxSupport = Rate;
2789 if (MinSupport > Rate) MinSupport = Rate;
2792 for (i=0; i<ExtRateLen; i++)
2794 switch (pExtRate[i] & 0x7f)
2796 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2797 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2798 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2799 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2800 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2801 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2802 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2803 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2804 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2805 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2806 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2807 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2808 default: Rate = RATE_1; break;
2810 if (MaxSupport < Rate) MaxSupport = Rate;
2812 if (MinSupport > Rate) MinSupport = Rate;
2815 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2817 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2818 // the DURATION field of outgoing uniicast DATA/MGMT frame
2819 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2821 if (BasicRateBitmap & (0x01 << i))
2822 CurrBasicRate = (UCHAR)i;
2823 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2826 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2827 // max tx rate = min {max desire rate, max supported rate}
2828 if (MaxSupport < MaxDesire)
2829 pAd->CommonCfg.MaxTxRate = MaxSupport;
2831 pAd->CommonCfg.MaxTxRate = MaxDesire;
2833 pAd->CommonCfg.MinTxRate = MinSupport;
2834 if (*auto_rate_cur_p)
2838 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2840 if (bLinkUp == TRUE)
2841 pAd->CommonCfg.TxRate = RATE_24;
2843 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2846 pAd->CommonCfg.TxRate = RATE_11;
2848 pAd->CommonCfg.TxRate = RATE_24;
2850 // should never exceed MaxTxRate (consider 11B-only mode)
2851 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2852 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2854 pAd->CommonCfg.TxRateIndex = 0;
2858 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2859 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2860 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2862 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2863 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2864 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2865 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
2868 if (pAd->CommonCfg.TxRate <= RATE_11)
2870 pMaxHtPhy->field.MODE = MODE_CCK;
2871 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
2872 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
2876 pMaxHtPhy->field.MODE = MODE_OFDM;
2877 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
2878 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
2879 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
2881 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
2884 pHtPhy->word = (pMaxHtPhy->word);
2885 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
2887 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
2888 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
2889 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
2893 switch (pAd->CommonCfg.PhyMode)
2895 case PHY_11BG_MIXED:
2897 case PHY_11BGN_MIXED:
2898 pAd->CommonCfg.MlmeRate = RATE_1;
2899 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2900 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2902 pAd->CommonCfg.RtsRate = RATE_11;
2906 case PHY_11AGN_MIXED:
2907 case PHY_11GN_MIXED:
2909 case PHY_11AN_MIXED:
2911 pAd->CommonCfg.MlmeRate = RATE_6;
2912 pAd->CommonCfg.RtsRate = RATE_6;
2913 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2914 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2916 case PHY_11ABG_MIXED:
2917 case PHY_11ABGN_MIXED:
2918 if (pAd->CommonCfg.Channel <= 14)
2920 pAd->CommonCfg.MlmeRate = RATE_1;
2921 pAd->CommonCfg.RtsRate = RATE_1;
2922 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2923 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2927 pAd->CommonCfg.MlmeRate = RATE_6;
2928 pAd->CommonCfg.RtsRate = RATE_6;
2929 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2930 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2934 pAd->CommonCfg.MlmeRate = RATE_6;
2935 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2936 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2937 pAd->CommonCfg.RtsRate = RATE_1;
2941 // Keep Basic Mlme Rate.
2943 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
2944 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
2945 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
2947 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
2948 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
2951 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
2952 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
2953 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
2954 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
2955 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
2956 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
2957 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 ));
2961 ==========================================================================
2963 This function update HT Rate setting.
2964 Input Wcid value is valid for 2 case :
2965 1. it's used for Station in infra mode that copy AP rate to Mactable.
2966 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
2968 IRQL = DISPATCH_LEVEL
2970 ==========================================================================
2972 VOID MlmeUpdateHtTxRates(
2973 IN PRTMP_ADAPTER pAd,
2976 UCHAR StbcMcs; //j, StbcMcs, bitmask;
2978 RT_HT_CAPABILITY *pRtHtCap = NULL;
2979 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
2982 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
2983 PHTTRANSMIT_SETTING pHtPhy = NULL;
2984 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2985 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2986 BOOLEAN *auto_rate_cur_p;
2988 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
2990 auto_rate_cur_p = NULL;
2993 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
2994 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
2995 pHtPhy = &pAd->StaCfg.HTPhyMode;
2996 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2997 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2999 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3002 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3004 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3007 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3008 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3009 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3010 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3011 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3012 pMaxHtPhy->field.STBC = STBC_USE;
3014 pMaxHtPhy->field.STBC = STBC_NONE;
3018 if (pDesireHtPhy->bHtEnable == FALSE)
3021 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3022 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3023 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3024 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3025 pMaxHtPhy->field.STBC = STBC_USE;
3027 pMaxHtPhy->field.STBC = STBC_NONE;
3030 // Decide MAX ht rate.
3031 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3032 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3034 pMaxHtPhy->field.MODE = MODE_HTMIX;
3036 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3037 pMaxHtPhy->field.BW = BW_40;
3039 pMaxHtPhy->field.BW = BW_20;
3041 if (pMaxHtPhy->field.BW == BW_20)
3042 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3044 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3046 for (i=23; i>=0; i--) // 3*3
3049 bitmask = (1<<(i-(j*8)));
3051 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3053 pMaxHtPhy->field.MCS = i;
3061 // Copy MIN ht rate. rt2860???
3062 pMinHtPhy->field.BW = BW_20;
3063 pMinHtPhy->field.MCS = 0;
3064 pMinHtPhy->field.STBC = 0;
3065 pMinHtPhy->field.ShortGI = 0;
3066 //If STA assigns fixed rate. update to fixed here.
3067 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3069 if (pDesireHtPhy->MCSSet[4] != 0)
3071 pMaxHtPhy->field.MCS = 32;
3072 pMinHtPhy->field.MCS = 32;
3073 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3076 for (i=23; (CHAR)i >= 0; i--) // 3*3
3079 bitmask = (1<<(i-(j*8)));
3080 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3082 pMaxHtPhy->field.MCS = i;
3083 pMinHtPhy->field.MCS = i;
3092 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3093 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3094 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3095 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3096 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3098 // use default now. rt2860
3099 if (pDesireHtPhy->MCSSet[0] != 0xff)
3100 *auto_rate_cur_p = FALSE;
3102 *auto_rate_cur_p = TRUE;
3104 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3105 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3106 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3107 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3110 // IRQL = DISPATCH_LEVEL
3112 IN PRTMP_ADAPTER pAd)
3114 RT28XX_MLME_RADIO_OFF(pAd);
3117 // IRQL = DISPATCH_LEVEL
3119 IN PRTMP_ADAPTER pAd)
3121 RT28XX_MLME_RADIO_ON(pAd);
3124 // ===========================================================================================
3126 // ===========================================================================================
3129 /*! \brief initialize BSS table
3130 * \param p_tab pointer to the table
3135 IRQL = PASSIVE_LEVEL
3136 IRQL = DISPATCH_LEVEL
3145 Tab->BssOverlapNr = 0;
3146 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3148 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3149 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3154 IN PRTMP_ADAPTER pAd,
3159 Tab->numAsOriginator = 0;
3160 Tab->numAsRecipient = 0;
3161 NdisAllocateSpinLock(&pAd->BATabLock);
3162 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3164 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3165 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3167 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3169 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3173 /*! \brief search the BSS table by SSID
3174 * \param p_tab pointer to the bss table
3175 * \param ssid SSID string
3176 * \return index of the table, BSS_NOT_FOUND if not in the table
3179 * \note search by sequential search
3181 IRQL = DISPATCH_LEVEL
3184 ULONG BssTableSearch(
3191 for (i = 0; i < Tab->BssNr; i++)
3194 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3195 // We should distinguish this case.
3197 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3198 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3199 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3204 return (ULONG)BSS_NOT_FOUND;
3207 ULONG BssSsidTableSearch(
3216 for (i = 0; i < Tab->BssNr; i++)
3219 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3220 // We should distinguish this case.
3222 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3223 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3224 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3225 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3230 return (ULONG)BSS_NOT_FOUND;
3233 ULONG BssTableSearchWithSSID(
3242 for (i = 0; i < Tab->BssNr; i++)
3244 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3245 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3246 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3247 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3248 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3249 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3254 return (ULONG)BSS_NOT_FOUND;
3257 // IRQL = DISPATCH_LEVEL
3258 VOID BssTableDeleteEntry(
3259 IN OUT BSS_TABLE *Tab,
3265 for (i = 0; i < Tab->BssNr; i++)
3267 if ((Tab->BssEntry[i].Channel == Channel) &&
3268 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3270 for (j = i; j < Tab->BssNr - 1; j++)
3272 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3274 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3282 ========================================================================
3283 Routine Description:
3284 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3287 // IRQL = DISPATCH_LEVEL
3288 ========================================================================
3290 VOID BATableDeleteORIEntry(
3291 IN OUT PRTMP_ADAPTER pAd,
3292 IN BA_ORI_ENTRY *pBAORIEntry)
3295 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3297 NdisAcquireSpinLock(&pAd->BATabLock);
3298 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3300 pAd->BATable.numAsOriginator -= 1;
3301 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3302 // Erase Bitmap flag.
3304 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3305 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3306 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3307 pBAORIEntry->Token = 1;
3308 // Not clear Sequence here.
3309 NdisReleaseSpinLock(&pAd->BATabLock);
3319 IRQL = DISPATCH_LEVEL
3323 IN PRTMP_ADAPTER pAd,
3324 OUT BSS_ENTRY *pBss,
3329 IN USHORT BeaconPeriod,
3330 IN PCF_PARM pCfParm,
3332 IN USHORT CapabilityInfo,
3334 IN UCHAR SupRateLen,
3336 IN UCHAR ExtRateLen,
3337 IN HT_CAPABILITY_IE *pHtCapability,
3338 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3339 IN UCHAR HtCapabilityLen,
3340 IN UCHAR AddHtInfoLen,
3341 IN UCHAR NewExtChanOffset,
3344 IN LARGE_INTEGER TimeStamp,
3346 IN PEDCA_PARM pEdcaParm,
3347 IN PQOS_CAPABILITY_PARM pQosCapability,
3348 IN PQBSS_LOAD_PARM pQbssLoad,
3349 IN USHORT LengthVIE,
3350 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3352 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3353 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3357 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3358 // Or send beacon /probe response with SSID len matching real SSID length,
3359 // but SSID is all zero. such as "00-00-00-00" with length 4.
3360 // We have to prevent this case overwrite correct table
3361 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3363 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3364 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3365 pBss->SsidLen = SsidLen;
3371 pBss->BssType = BssType;
3372 pBss->BeaconPeriod = BeaconPeriod;
3373 if (BssType == BSS_INFRA)
3375 if (pCfParm->bValid)
3377 pBss->CfpCount = pCfParm->CfpCount;
3378 pBss->CfpPeriod = pCfParm->CfpPeriod;
3379 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3380 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3385 pBss->AtimWin = AtimWin;
3388 pBss->CapabilityInfo = CapabilityInfo;
3389 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3390 // Combine with AuthMode, they will decide the connection methods.
3391 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3392 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3393 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3394 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3396 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3397 pBss->SupRateLen = SupRateLen;
3398 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3399 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3400 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3401 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3402 pBss->NewExtChanOffset = NewExtChanOffset;
3403 pBss->ExtRateLen = ExtRateLen;
3404 pBss->Channel = Channel;
3405 pBss->CentralChannel = Channel;
3407 // Update CkipFlag. if not exists, the value is 0x0
3408 pBss->CkipFlag = CkipFlag;
3410 // New for microsoft Fixed IEs
3411 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3412 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3413 pBss->FixIEs.Capabilities = CapabilityInfo;
3415 // New for microsoft Variable IEs
3418 pBss->VarIELen = LengthVIE;
3419 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3426 pBss->AddHtInfoLen = 0;
3427 pBss->HtCapabilityLen = 0;
3429 if (HtCapabilityLen> 0)
3431 pBss->HtCapabilityLen = HtCapabilityLen;
3432 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3433 if (AddHtInfoLen > 0)
3435 pBss->AddHtInfoLen = AddHtInfoLen;
3436 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3438 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3440 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3442 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3444 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3449 BssCipherParse(pBss);
3453 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3455 pBss->EdcaParm.bValid = FALSE;
3457 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3459 pBss->QosCapability.bValid = FALSE;
3461 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3463 pBss->QbssLoad.bValid = FALSE;
3470 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3471 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3473 pEid = (PEID_STRUCT) pVIE;
3475 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3480 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3482 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3484 pBss->WpaIE.IELen = 0;
3487 pBss->WpaIE.IELen = pEid->Len + 2;
3488 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3492 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3494 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3496 pBss->RsnIE.IELen = 0;
3499 pBss->RsnIE.IELen = pEid->Len + 2;
3500 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3504 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3505 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3511 * \brief insert an entry into the bss table
3512 * \param p_tab The BSS table
3513 * \param Bssid BSSID
3515 * \param ssid_len Length of SSID
3517 * \param beacon_period
3524 * \param channel_idx
3528 * \note If SSID is identical, the old entry will be replaced by the new one
3530 IRQL = DISPATCH_LEVEL
3533 ULONG BssTableSetEntry(
3534 IN PRTMP_ADAPTER pAd,
3540 IN USHORT BeaconPeriod,
3543 IN USHORT CapabilityInfo,
3545 IN UCHAR SupRateLen,
3547 IN UCHAR ExtRateLen,
3548 IN HT_CAPABILITY_IE *pHtCapability,
3549 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3550 IN UCHAR HtCapabilityLen,
3551 IN UCHAR AddHtInfoLen,
3552 IN UCHAR NewExtChanOffset,
3555 IN LARGE_INTEGER TimeStamp,
3557 IN PEDCA_PARM pEdcaParm,
3558 IN PQOS_CAPABILITY_PARM pQosCapability,
3559 IN PQBSS_LOAD_PARM pQbssLoad,
3560 IN USHORT LengthVIE,
3561 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3565 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3566 if (Idx == BSS_NOT_FOUND)
3568 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3571 // It may happen when BSS Table was full.
3572 // The desired AP will not be added into BSS Table
3573 // In this case, if we found the desired AP then overwrite BSS Table.
3575 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3577 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3578 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3580 Idx = Tab->BssOverlapNr;
3581 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3582 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3583 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3584 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3590 return BSS_NOT_FOUND;
3594 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3595 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3596 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3601 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3602 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3603 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3605 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3606 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3607 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3614 // IRQL = DISPATCH_LEVEL
3615 VOID BssTableSsidSort(
3616 IN PRTMP_ADAPTER pAd,
3617 OUT BSS_TABLE *OutTab,
3622 BssTableInit(OutTab);
3624 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3626 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3627 BOOLEAN bIsHiddenApIncluded = FALSE;
3629 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3630 (pAd->MlmeAux.Channel > 14) &&
3631 RadarChannelCheck(pAd, pInBss->Channel))
3635 bIsHiddenApIncluded = TRUE;
3638 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3639 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3641 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3643 // 2.4G/5G N only mode
3644 if ((pInBss->HtCapabilityLen == 0) &&
3645 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3647 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3652 // Check the Authmode first
3653 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3655 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3656 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3660 // Check cipher suite, AP must have more secured cipher than station setting
3661 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3663 // If it's not mixed mode, we should only let BSS pass with the same encryption
3664 if (pInBss->WPA.bMixMode == FALSE)
3665 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3668 // check group cipher
3669 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3672 // check pairwise cipher, skip if none matched
3673 // If profile set to AES, let it pass without question.
3674 // If profile set to TKIP, we must find one mateched
3675 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3676 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3677 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3680 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3682 // If it's not mixed mode, we should only let BSS pass with the same encryption
3683 if (pInBss->WPA2.bMixMode == FALSE)
3684 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3687 // check group cipher
3688 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3691 // check pairwise cipher, skip if none matched
3692 // If profile set to AES, let it pass without question.
3693 // If profile set to TKIP, we must find one mateched
3694 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3695 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3696 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3700 // Bss Type matched, SSID matched.
3701 // We will check wepstatus for qualification Bss
3702 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3704 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3706 // For the SESv2 case, we will not qualify WepStatus.
3712 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3713 // It definitely will fail. So, skip it.
3714 // CCX also require not even try to connect it!!
3718 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3719 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3720 if ((pInBss->CentralChannel != pInBss->Channel) &&
3721 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3723 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3725 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3727 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3731 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3738 // copy matching BSS from InTab to OutTab
3739 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3743 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3745 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3747 // 2.4G/5G N only mode
3748 if ((pInBss->HtCapabilityLen == 0) &&
3749 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3751 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3756 // Check the Authmode first
3757 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3759 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3760 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3764 // Check cipher suite, AP must have more secured cipher than station setting
3765 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3767 // If it's not mixed mode, we should only let BSS pass with the same encryption
3768 if (pInBss->WPA.bMixMode == FALSE)
3769 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3772 // check group cipher
3773 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3776 // check pairwise cipher, skip if none matched
3777 // If profile set to AES, let it pass without question.
3778 // If profile set to TKIP, we must find one mateched
3779 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3780 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3781 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3784 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3786 // If it's not mixed mode, we should only let BSS pass with the same encryption
3787 if (pInBss->WPA2.bMixMode == FALSE)
3788 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3791 // check group cipher
3792 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3795 // check pairwise cipher, skip if none matched
3796 // If profile set to AES, let it pass without question.
3797 // If profile set to TKIP, we must find one mateched
3798 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3799 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3800 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3804 // Bss Type matched, SSID matched.
3805 // We will check wepstatus for qualification Bss
3806 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3809 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3810 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3811 if ((pInBss->CentralChannel != pInBss->Channel) &&
3812 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3814 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3816 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3818 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3822 // copy matching BSS from InTab to OutTab
3823 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3828 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3832 BssTableSortByRssi(OutTab);
3836 // IRQL = DISPATCH_LEVEL
3837 VOID BssTableSortByRssi(
3838 IN OUT BSS_TABLE *OutTab)
3843 for (i = 0; i < OutTab->BssNr - 1; i++)
3845 for (j = i+1; j < OutTab->BssNr; j++)
3847 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
3849 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
3850 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
3851 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
3857 VOID BssCipherParse(
3858 IN OUT PBSS_ENTRY pBss)
3862 PRSN_IE_HEADER_STRUCT pRsnHeader;
3863 PCIPHER_SUITE_STRUCT pCipher;
3864 PAKM_SUITE_STRUCT pAKM;
3867 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
3870 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
3874 pBss->WepStatus = Ndis802_11WEPEnabled;
3878 pBss->WepStatus = Ndis802_11WEPDisabled;
3880 // Set default to disable & open authentication before parsing variable IE
3881 pBss->AuthMode = Ndis802_11AuthModeOpen;
3882 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
3885 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
3886 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
3887 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
3888 pBss->WPA.RsnCapability = 0;
3889 pBss->WPA.bMixMode = FALSE;
3891 // Init WPA2 setting
3892 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
3893 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
3894 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
3895 pBss->WPA2.RsnCapability = 0;
3896 pBss->WPA2.bMixMode = FALSE;
3899 Length = (INT) pBss->VarIELen;
3903 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
3904 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
3905 pEid = (PEID_STRUCT) pTmp;
3909 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
3910 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
3916 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3917 pBss->WepStatus = Ndis802_11Encryption1Enabled;
3918 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3919 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3922 pBss->WepStatus = Ndis802_11Encryption2Enabled;
3923 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3924 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3927 pBss->WepStatus = Ndis802_11Encryption3Enabled;
3928 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3929 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3935 // if Cisco IE_WPA, break
3938 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
3943 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
3945 // if unsupported vendor specific IE
3948 // Skip OUI, version, and multicast suite
3949 // This part should be improved in the future when AP supported multiple cipher suite.
3950 // For now, it's OK since almost all APs have fixed cipher suite supported.
3951 // pTmp = (PUCHAR) pEid->Octet;
3954 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
3962 // Parse group cipher
3966 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3967 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3970 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
3973 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
3978 // number of unicast suite
3981 // skip all unicast cipher suites
3982 //Count = *(PUSHORT) pTmp;
3983 Count = (pTmp[1]<<8) + pTmp[0];
3984 pTmp += sizeof(USHORT);
3986 // Parsing all unicast cipher suite
3991 TmpCipher = Ndis802_11WEPDisabled;
3995 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3996 TmpCipher = Ndis802_11Encryption1Enabled;
3999 TmpCipher = Ndis802_11Encryption2Enabled;
4002 TmpCipher = Ndis802_11Encryption3Enabled;
4007 if (TmpCipher > pBss->WPA.PairCipher)
4009 // Move the lower cipher suite to PairCipherAux
4010 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4011 pBss->WPA.PairCipher = TmpCipher;
4015 pBss->WPA.PairCipherAux = TmpCipher;
4021 // 4. get AKM suite counts
4022 //Count = *(PUSHORT) pTmp;
4023 Count = (pTmp[1]<<8) + pTmp[0];
4024 pTmp += sizeof(USHORT);
4030 // Set AP support WPA mode
4031 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4032 pBss->AuthMode = Ndis802_11AuthModeWPA;
4034 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4037 // Set AP support WPA mode
4038 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4039 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4041 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4048 // Fixed for WPA-None
4049 if (pBss->BssType == BSS_ADHOC)
4051 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4052 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4053 pBss->WepStatus = pBss->WPA.GroupCipher;
4054 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4055 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4058 pBss->WepStatus = pBss->WPA.PairCipher;
4060 // Check the Pair & Group, if different, turn on mixed mode flag
4061 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4062 pBss->WPA.bMixMode = TRUE;
4067 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4069 // 0. Version must be 1
4070 if (le2cpu16(pRsnHeader->Version) != 1)
4072 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4074 // 1. Check group cipher
4075 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4076 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4079 // Parse group cipher
4080 switch (pCipher->Type)
4083 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4084 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4087 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4090 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4095 // set to correct offset for next parsing
4096 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4098 // 2. Get pairwise cipher counts
4099 //Count = *(PUSHORT) pTmp;
4100 Count = (pTmp[1]<<8) + pTmp[0];
4101 pTmp += sizeof(USHORT);
4103 // 3. Get pairwise cipher
4104 // Parsing all unicast cipher suite
4108 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4109 TmpCipher = Ndis802_11WEPDisabled;
4110 switch (pCipher->Type)
4113 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4114 TmpCipher = Ndis802_11Encryption1Enabled;
4117 TmpCipher = Ndis802_11Encryption2Enabled;
4120 TmpCipher = Ndis802_11Encryption3Enabled;
4125 if (TmpCipher > pBss->WPA2.PairCipher)
4127 // Move the lower cipher suite to PairCipherAux
4128 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4129 pBss->WPA2.PairCipher = TmpCipher;
4133 pBss->WPA2.PairCipherAux = TmpCipher;
4135 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4139 // 4. get AKM suite counts
4140 //Count = *(PUSHORT) pTmp;
4141 Count = (pTmp[1]<<8) + pTmp[0];
4142 pTmp += sizeof(USHORT);
4144 // 5. Get AKM ciphers
4145 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4146 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4152 // Set AP support WPA mode
4153 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4154 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4156 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4159 // Set AP support WPA mode
4160 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4161 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4163 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4168 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4170 // Fixed for WPA-None
4171 if (pBss->BssType == BSS_ADHOC)
4173 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4174 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4175 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4176 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4177 pBss->WepStatus = pBss->WPA.GroupCipher;
4178 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4179 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4181 pBss->WepStatus = pBss->WPA2.PairCipher;
4183 // 6. Get RSN capability
4184 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4185 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4186 pTmp += sizeof(USHORT);
4188 // Check the Pair & Group, if different, turn on mixed mode flag
4189 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4190 pBss->WPA2.bMixMode = TRUE;
4196 Length -= (pEid->Len + 2);
4200 // ===========================================================================================
4202 // ===========================================================================================
4204 /*! \brief generates a random mac address value for IBSS BSSID
4205 * \param Addr the bssid location
4210 VOID MacAddrRandomBssid(
4211 IN PRTMP_ADAPTER pAd,
4216 for (i = 0; i < MAC_ADDR_LEN; i++)
4218 pAddr[i] = RandomByte(pAd);
4221 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4224 /*! \brief init the management mac frame header
4225 * \param p_hdr mac header
4226 * \param subtype subtype of the frame
4227 * \param p_ds destination address, don't care if it is a broadcast address
4229 * \pre the station has the following information in the pAd->StaCfg
4233 * \note this function initializes the following field
4235 IRQL = PASSIVE_LEVEL
4236 IRQL = DISPATCH_LEVEL
4239 VOID MgtMacHeaderInit(
4240 IN PRTMP_ADAPTER pAd,
4241 IN OUT PHEADER_802_11 pHdr80211,
4247 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4249 pHdr80211->FC.Type = BTYPE_MGMT;
4250 pHdr80211->FC.SubType = SubType;
4251 pHdr80211->FC.ToDs = ToDs;
4252 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4254 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4256 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4259 // ===========================================================================================
4261 // ===========================================================================================
4263 /*!***************************************************************************
4264 * This routine build an outgoing frame, and fill all information specified
4265 * in argument list to the frame body. The actual frame size is the summation
4268 * Buffer - pointer to a pre-allocated memory segment
4269 * args - a list of <int arg_size, arg> pairs.
4270 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4271 * function will FAIL!!!
4273 * Size of the buffer
4275 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4277 IRQL = PASSIVE_LEVEL
4278 IRQL = DISPATCH_LEVEL
4280 ****************************************************************************/
4281 ULONG MakeOutgoingFrame(
4283 OUT ULONG *FrameLen, ...)
4290 // calculates the total length
4292 va_start(Args, FrameLen);
4295 leng = va_arg(Args, int);
4296 if (leng == END_OF_ARGS)
4300 p = va_arg(Args, PVOID);
4301 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4302 TotLeng = TotLeng + leng;
4305 va_end(Args); /* clean up */
4306 *FrameLen = TotLeng;
4310 // ===========================================================================================
4312 // ===========================================================================================
4314 /*! \brief Initialize The MLME Queue, used by MLME Functions
4315 * \param *Queue The MLME Queue
4316 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4319 * \note Because this is done only once (at the init stage), no need to be locked
4321 IRQL = PASSIVE_LEVEL
4324 NDIS_STATUS MlmeQueueInit(
4325 IN MLME_QUEUE *Queue)
4329 NdisAllocateSpinLock(&Queue->Lock);
4335 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4337 Queue->Entry[i].Occupied = FALSE;
4338 Queue->Entry[i].MsgLen = 0;
4339 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4342 return NDIS_STATUS_SUCCESS;
4345 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4346 * \param *Queue The MLME Queue
4347 * \param Machine The State Machine Id
4348 * \param MsgType The Message Type
4349 * \param MsgLen The Message length
4350 * \param *Msg The message pointer
4351 * \return TRUE if enqueue is successful, FALSE if the queue is full
4354 * \note The message has to be initialized
4356 IRQL = PASSIVE_LEVEL
4357 IRQL = DISPATCH_LEVEL
4360 BOOLEAN MlmeEnqueue(
4361 IN PRTMP_ADAPTER pAd,
4368 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4370 // Do nothing if the driver is starting halt state.
4371 // This might happen when timer already been fired before cancel timer with mlmehalt
4372 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4375 // First check the size, it MUST not exceed the mlme queue size
4376 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4378 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4382 if (MlmeQueueFull(Queue))
4387 NdisAcquireSpinLock(&(Queue->Lock));
4391 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4396 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4397 Queue->Entry[Tail].Occupied = TRUE;
4398 Queue->Entry[Tail].Machine = Machine;
4399 Queue->Entry[Tail].MsgType = MsgType;
4400 Queue->Entry[Tail].MsgLen = MsgLen;
4404 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4407 NdisReleaseSpinLock(&(Queue->Lock));
4411 /*! \brief This function is used when Recv gets a MLME message
4412 * \param *Queue The MLME Queue
4413 * \param TimeStampHigh The upper 32 bit of timestamp
4414 * \param TimeStampLow The lower 32 bit of timestamp
4415 * \param Rssi The receiving RSSI strength
4416 * \param MsgLen The length of the message
4417 * \param *Msg The message pointer
4418 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4422 IRQL = DISPATCH_LEVEL
4425 BOOLEAN MlmeEnqueueForRecv(
4426 IN PRTMP_ADAPTER pAd,
4428 IN ULONG TimeStampHigh,
4429 IN ULONG TimeStampLow,
4438 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4440 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4442 // Do nothing if the driver is starting halt state.
4443 // This might happen when timer already been fired before cancel timer with mlmehalt
4444 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4446 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4450 // First check the size, it MUST not exceed the mlme queue size
4451 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4453 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4457 if (MlmeQueueFull(Queue))
4463 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4465 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4470 // OK, we got all the informations, it is time to put things into queue
4471 NdisAcquireSpinLock(&(Queue->Lock));
4475 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4479 Queue->Entry[Tail].Occupied = TRUE;
4480 Queue->Entry[Tail].Machine = Machine;
4481 Queue->Entry[Tail].MsgType = MsgType;
4482 Queue->Entry[Tail].MsgLen = MsgLen;
4483 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4484 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4485 Queue->Entry[Tail].Rssi0 = Rssi0;
4486 Queue->Entry[Tail].Rssi1 = Rssi1;
4487 Queue->Entry[Tail].Rssi2 = Rssi2;
4488 Queue->Entry[Tail].Signal = Signal;
4489 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4491 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4495 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4498 NdisReleaseSpinLock(&(Queue->Lock));
4500 RT28XX_MLME_HANDLER(pAd);
4506 /*! \brief Dequeue a message from the MLME Queue
4507 * \param *Queue The MLME Queue
4508 * \param *Elem The message dequeued from MLME Queue
4509 * \return TRUE if the Elem contains something, FALSE otherwise
4513 IRQL = DISPATCH_LEVEL
4516 BOOLEAN MlmeDequeue(
4517 IN MLME_QUEUE *Queue,
4518 OUT MLME_QUEUE_ELEM **Elem)
4520 NdisAcquireSpinLock(&(Queue->Lock));
4521 *Elem = &(Queue->Entry[Queue->Head]);
4524 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4528 NdisReleaseSpinLock(&(Queue->Lock));
4532 // IRQL = DISPATCH_LEVEL
4533 VOID MlmeRestartStateMachine(
4534 IN PRTMP_ADAPTER pAd)
4538 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4541 // Cancel all timer events
4542 // Be careful to cancel new added timer
4543 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4544 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4545 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4546 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4547 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4548 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4551 // Change back to original channel in case of doing scan
4552 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4553 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4555 // Resume MSDU which is turned off durning scan
4556 RTMPResumeMsduTransmission(pAd);
4559 // Set all state machines back IDLE
4560 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4561 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4562 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4563 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4564 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4565 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4569 /*! \brief test if the MLME Queue is empty
4570 * \param *Queue The MLME Queue
4571 * \return TRUE if the Queue is empty, FALSE otherwise
4575 IRQL = DISPATCH_LEVEL
4578 BOOLEAN MlmeQueueEmpty(
4579 IN MLME_QUEUE *Queue)
4583 NdisAcquireSpinLock(&(Queue->Lock));
4584 Ans = (Queue->Num == 0);
4585 NdisReleaseSpinLock(&(Queue->Lock));
4590 /*! \brief test if the MLME Queue is full
4591 * \param *Queue The MLME Queue
4592 * \return TRUE if the Queue is empty, FALSE otherwise
4596 IRQL = PASSIVE_LEVEL
4597 IRQL = DISPATCH_LEVEL
4600 BOOLEAN MlmeQueueFull(
4601 IN MLME_QUEUE *Queue)
4605 NdisAcquireSpinLock(&(Queue->Lock));
4606 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4607 NdisReleaseSpinLock(&(Queue->Lock));
4612 /*! \brief The destructor of MLME Queue
4617 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4619 IRQL = PASSIVE_LEVEL
4622 VOID MlmeQueueDestroy(
4623 IN MLME_QUEUE *pQueue)
4625 NdisAcquireSpinLock(&(pQueue->Lock));
4629 NdisReleaseSpinLock(&(pQueue->Lock));
4630 NdisFreeSpinLock(&(pQueue->Lock));
4633 /*! \brief To substitute the message type if the message is coming from external
4634 * \param pFrame The frame received
4635 * \param *Machine The state machine
4636 * \param *MsgType the message type for the state machine
4637 * \return TRUE if the substitution is successful, FALSE otherwise
4641 IRQL = DISPATCH_LEVEL
4644 BOOLEAN MsgTypeSubst(
4645 IN PRTMP_ADAPTER pAd,
4646 IN PFRAME_802_11 pFrame,
4654 // Pointer to start of data frames including SNAP header
4655 pData = (PUCHAR) pFrame + LENGTH_802_11;
4657 // The only data type will pass to this function is EAPOL frame
4658 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4660 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4662 // Cisco Aironet SNAP header
4663 *Machine = AIRONET_STATE_MACHINE;
4664 *MsgType = MT2_AIRONET_MSG;
4668 *Machine = WPA_PSK_STATE_MACHINE;
4669 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4670 return(WpaMsgTypeSubst(EAPType, MsgType));
4674 switch (pFrame->Hdr.FC.SubType)
4676 case SUBTYPE_ASSOC_REQ:
4677 *Machine = ASSOC_STATE_MACHINE;
4678 *MsgType = MT2_PEER_ASSOC_REQ;
4680 case SUBTYPE_ASSOC_RSP:
4681 *Machine = ASSOC_STATE_MACHINE;
4682 *MsgType = MT2_PEER_ASSOC_RSP;
4684 case SUBTYPE_REASSOC_REQ:
4685 *Machine = ASSOC_STATE_MACHINE;
4686 *MsgType = MT2_PEER_REASSOC_REQ;
4688 case SUBTYPE_REASSOC_RSP:
4689 *Machine = ASSOC_STATE_MACHINE;
4690 *MsgType = MT2_PEER_REASSOC_RSP;
4692 case SUBTYPE_PROBE_REQ:
4693 *Machine = SYNC_STATE_MACHINE;
4694 *MsgType = MT2_PEER_PROBE_REQ;
4696 case SUBTYPE_PROBE_RSP:
4697 *Machine = SYNC_STATE_MACHINE;
4698 *MsgType = MT2_PEER_PROBE_RSP;
4700 case SUBTYPE_BEACON:
4701 *Machine = SYNC_STATE_MACHINE;
4702 *MsgType = MT2_PEER_BEACON;
4705 *Machine = SYNC_STATE_MACHINE;
4706 *MsgType = MT2_PEER_ATIM;
4708 case SUBTYPE_DISASSOC:
4709 *Machine = ASSOC_STATE_MACHINE;
4710 *MsgType = MT2_PEER_DISASSOC_REQ;
4713 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4714 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4715 if (Seq == 1 || Seq == 3)
4717 *Machine = AUTH_RSP_STATE_MACHINE;
4718 *MsgType = MT2_PEER_AUTH_ODD;
4720 else if (Seq == 2 || Seq == 4)
4722 *Machine = AUTH_STATE_MACHINE;
4723 *MsgType = MT2_PEER_AUTH_EVEN;
4730 case SUBTYPE_DEAUTH:
4731 *Machine = AUTH_RSP_STATE_MACHINE;
4732 *MsgType = MT2_PEER_DEAUTH;
4734 case SUBTYPE_ACTION:
4735 *Machine = ACTION_STATE_MACHINE;
4736 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4737 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4739 *MsgType = MT2_ACT_INVALID;
4743 *MsgType = (pFrame->Octet[0]&0x7F);
4754 // ===========================================================================================
4756 // ===========================================================================================
4758 /*! \brief Initialize the state machine.
4759 * \param *S pointer to the state machine
4760 * \param Trans State machine transition function
4761 * \param StNr number of states
4762 * \param MsgNr number of messages
4763 * \param DefFunc default function, when there is invalid state/message combination
4764 * \param InitState initial state of the state machine
4765 * \param Base StateMachine base, internal use only
4766 * \pre p_sm should be a legal pointer
4769 IRQL = PASSIVE_LEVEL
4772 VOID StateMachineInit(
4773 IN STATE_MACHINE *S,
4774 IN STATE_MACHINE_FUNC Trans[],
4777 IN STATE_MACHINE_FUNC DefFunc,
4783 // set number of states and messages
4788 S->TransFunc = Trans;
4790 // init all state transition to default function
4791 for (i = 0; i < StNr; i++)
4793 for (j = 0; j < MsgNr; j++)
4795 S->TransFunc[i * MsgNr + j] = DefFunc;
4799 // set the starting state
4800 S->CurrState = InitState;
4803 /*! \brief This function fills in the function pointer into the cell in the state machine
4804 * \param *S pointer to the state machine
4806 * \param Msg incoming message
4807 * \param f the function to be executed when (state, message) combination occurs at the state machine
4808 * \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
4811 IRQL = PASSIVE_LEVEL
4814 VOID StateMachineSetAction(
4815 IN STATE_MACHINE *S,
4818 IN STATE_MACHINE_FUNC Func)
4822 MsgIdx = Msg - S->Base;
4824 if (St < S->NrState && MsgIdx < S->NrMsg)
4826 // boundary checking before setting the action
4827 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
4831 /*! \brief This function does the state transition
4832 * \param *Adapter the NIC adapter pointer
4833 * \param *S the state machine
4834 * \param *Elem the message to be executed
4837 IRQL = DISPATCH_LEVEL
4840 VOID StateMachinePerformAction(
4841 IN PRTMP_ADAPTER pAd,
4842 IN STATE_MACHINE *S,
4843 IN MLME_QUEUE_ELEM *Elem)
4845 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
4849 ==========================================================================
4851 The drop function, when machine executes this, the message is simply
4852 ignored. This function does nothing, the message is freed in
4853 StateMachinePerformAction()
4854 ==========================================================================
4857 IN PRTMP_ADAPTER pAd,
4858 IN MLME_QUEUE_ELEM *Elem)
4862 // ===========================================================================================
4864 // ===========================================================================================
4867 ==========================================================================
4870 IRQL = PASSIVE_LEVEL
4872 ==========================================================================
4875 IN PRTMP_ADAPTER pAd,
4879 pAd->Mlme.ShiftReg = 1;
4881 pAd->Mlme.ShiftReg = Seed;
4885 ==========================================================================
4887 ==========================================================================
4890 IN PRTMP_ADAPTER pAd)
4897 if (pAd->Mlme.ShiftReg == 0)
4898 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
4900 for (i = 0; i < 8; i++)
4902 if (pAd->Mlme.ShiftReg & 0x00000001)
4904 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
4909 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
4912 R = (R << 1) | Result;
4918 VOID AsicUpdateAutoFallBackTable(
4919 IN PRTMP_ADAPTER pAd,
4920 IN PUCHAR pRateTable)
4923 HT_FBK_CFG0_STRUC HtCfg0;
4924 HT_FBK_CFG1_STRUC HtCfg1;
4925 LG_FBK_CFG0_STRUC LgCfg0;
4926 LG_FBK_CFG1_STRUC LgCfg1;
4927 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
4929 // set to initial value
4930 HtCfg0.word = 0x65432100;
4931 HtCfg1.word = 0xedcba988;
4932 LgCfg0.word = 0xedcba988;
4933 LgCfg1.word = 0x00002100;
4935 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
4936 for (i = 1; i < *((PUCHAR) pRateTable); i++)
4938 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
4939 switch (pCurrTxRate->Mode)
4945 switch(pCurrTxRate->CurrMCS)
4948 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4951 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4954 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4957 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4960 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4963 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4966 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4969 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4977 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
4979 switch(pCurrTxRate->CurrMCS)
4982 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
4985 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
4988 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
4991 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
4994 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
4997 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5000 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5003 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5006 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5009 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5012 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5015 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5018 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5021 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5024 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5027 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5030 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5037 pNextTxRate = pCurrTxRate;
5040 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5041 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5042 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5043 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5047 ========================================================================
5049 Routine Description:
5050 Set MAC register value according operation mode.
5051 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5052 If MM or GF mask is not set, those passing argument doesn't not take effect.
5054 Operation mode meaning:
5055 = 0 : Pure HT, no preotection.
5056 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5057 = 0x10: No Transmission in 40M is protected.
5058 = 0x11: Transmission in both 40M and 20M shall be protected
5060 we should choose not to use GF. But still set correct ASIC registers.
5061 ========================================================================
5063 VOID AsicUpdateProtect(
5064 IN PRTMP_ADAPTER pAd,
5065 IN USHORT OperationMode,
5067 IN BOOLEAN bDisableBGProtect,
5068 IN BOOLEAN bNonGFExist)
5070 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5076 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5081 if (pAd->BATable.numAsOriginator)
5084 // enable the RTS/CTS to avoid channel collision
5086 SetMask = ALLN_SETPROTECT;
5090 // Config ASIC RTS threshold register
5091 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5092 MacReg &= 0xFF0000FF;
5094 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5096 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5097 (pAd->CommonCfg.bAggregationCapable == TRUE))
5098 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5100 MacReg |= (0x1000 << 8);
5104 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5107 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5109 // Initial common protection settings
5110 RTMPZeroMemory(Protect, sizeof(Protect));
5113 ProtCfg.field.TxopAllowGF40 = 1;
5114 ProtCfg.field.TxopAllowGF20 = 1;
5115 ProtCfg.field.TxopAllowMM40 = 1;
5116 ProtCfg.field.TxopAllowMM20 = 1;
5117 ProtCfg.field.TxopAllowOfdm = 1;
5118 ProtCfg.field.TxopAllowCck = 1;
5119 ProtCfg.field.RTSThEn = 1;
5120 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5122 // update PHY mode and rate
5123 if (pAd->CommonCfg.Channel > 14)
5124 ProtCfg.field.ProtectRate = 0x4000;
5125 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5127 // Handle legacy(B/G) protection
5128 if (bDisableBGProtect)
5130 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5131 ProtCfg.field.ProtectCtrl = 0;
5132 Protect[0] = ProtCfg.word;
5133 Protect[1] = ProtCfg.word;
5137 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5138 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5139 Protect[0] = ProtCfg.word;
5140 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5141 Protect[1] = ProtCfg.word;
5144 // Decide HT frame protection.
5145 if ((SetMask & ALLN_SETPROTECT) != 0)
5147 switch(OperationMode)
5151 // 1.All STAs in the BSS are 20/40 MHz HT
5152 // 2. in ai 20/40MHz BSS
5153 // 3. all STAs are 20MHz in a 20MHz BSS
5154 // Pure HT. no protection.
5158 // PROT_TXOP(25:20) -- 010111
5159 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5160 // PROT_CTRL(17:16) -- 00 (None)
5161 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5162 Protect[2] = 0x01744004;
5166 // PROT_TXOP(25:20) -- 111111
5167 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5168 // PROT_CTRL(17:16) -- 00 (None)
5169 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5170 Protect[3] = 0x03f44084;
5174 // PROT_TXOP(25:20) -- 010111
5175 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5176 // PROT_CTRL(17:16) -- 00 (None)
5177 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5178 Protect[4] = 0x01744004;
5182 // PROT_TXOP(25:20) -- 111111
5183 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5184 // PROT_CTRL(17:16) -- 00 (None)
5185 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5186 Protect[5] = 0x03f44084;
5190 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5191 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5192 Protect[4] = 0x01754004;
5193 Protect[5] = 0x03f54084;
5195 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5199 // This is "HT non-member protection mode."
5200 // If there may be non-HT STAs my BSS
5201 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5202 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5203 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5205 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5206 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5208 //Assign Protection method for 20&40 MHz packets
5209 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5210 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5211 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5212 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5213 Protect[2] = ProtCfg.word;
5214 Protect[3] = ProtCfg4.word;
5215 Protect[4] = ProtCfg.word;
5216 Protect[5] = ProtCfg4.word;
5217 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5221 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5222 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5223 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5225 //Assign Protection method for 40MHz packets
5226 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5227 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5228 Protect[2] = ProtCfg.word;
5229 Protect[3] = ProtCfg4.word;
5232 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5233 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5235 Protect[4] = ProtCfg.word;
5236 Protect[5] = ProtCfg4.word;
5238 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5242 // HT mixed mode. PROTECT ALL!
5244 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5245 ProtCfg4.word = 0x03f44084;
5246 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5247 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5249 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5250 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5252 //Assign Protection method for 20&40 MHz packets
5253 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5254 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5255 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5256 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5257 Protect[2] = ProtCfg.word;
5258 Protect[3] = ProtCfg4.word;
5259 Protect[4] = ProtCfg.word;
5260 Protect[5] = ProtCfg4.word;
5261 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5265 Protect[2] = 0x01754004;
5266 Protect[3] = 0x03f54084;
5267 Protect[4] = 0x01754004;
5268 Protect[5] = 0x03f54084;
5269 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5274 offset = CCK_PROT_CFG;
5275 for (i = 0;i < 6;i++)
5277 if ((SetMask & (1<< i)))
5279 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5287 ========================================================================
5289 Routine Description: Write RT30xx RF register through MAC
5299 ========================================================================
5301 NTSTATUS RT30xxWriteRFRegister(
5302 IN PRTMP_ADAPTER pAd,
5306 RF_CSR_CFG_STRUC rfcsr;
5311 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5313 if (!rfcsr.field.RF_CSR_KICK)
5317 while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
5319 if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
5321 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
5322 return STATUS_UNSUCCESSFUL;
5325 rfcsr.field.RF_CSR_WR = 1;
5326 rfcsr.field.RF_CSR_KICK = 1;
5327 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5328 rfcsr.field.RF_CSR_DATA = Value;
5330 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5332 return STATUS_SUCCESS;
5337 ========================================================================
5339 Routine Description: Read RT30xx RF register through MAC
5349 ========================================================================
5351 NTSTATUS RT30xxReadRFRegister(
5352 IN PRTMP_ADAPTER pAd,
5356 RF_CSR_CFG_STRUC rfcsr;
5359 for (i=0; i<MAX_BUSY_COUNT; i++)
5361 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5363 if (rfcsr.field.RF_CSR_KICK == BUSY)
5368 rfcsr.field.RF_CSR_WR = 0;
5369 rfcsr.field.RF_CSR_KICK = 1;
5370 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5371 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5372 for (k=0; k<MAX_BUSY_COUNT; k++)
5374 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5376 if (rfcsr.field.RF_CSR_KICK == IDLE)
5379 if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
5380 (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
5382 *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
5386 if (rfcsr.field.RF_CSR_KICK == BUSY)
5388 DBGPRINT_ERR(("RF read R%d=0x%x fail, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
5389 return STATUS_UNSUCCESSFUL;
5392 return STATUS_SUCCESS;
5397 // add by johnli, RF power sequence setup
5399 ==========================================================================
5402 Load RF normal operation-mode setup
5404 ==========================================================================
5406 VOID RT30xxLoadRFNormalModeSetup(
5407 IN PRTMP_ADAPTER pAd)
5411 // 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
5412 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5413 RFValue = (RFValue & (~0x0C)) | 0x31;
5414 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5416 // TX_LO2_en, RF R15 register Bit 3 to 0
5417 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5419 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5421 // TX_LO1_en, RF R17 register Bit 3 to 0
5422 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5424 // to fix rx long range issue
5425 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5429 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5431 // RX_LO1_en, RF R20 register Bit 3 to 0
5432 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5434 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5436 // RX_LO2_en, RF R21 register Bit 3 to 0
5437 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5439 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5441 // LDORF_VC, RF R27 register Bit 2 to 0
5442 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5443 if ((pAd->MACVersion & 0xffff) < 0x0211)
5444 RFValue = (RFValue & (~0x77)) | 0x3;
5446 RFValue = (RFValue & (~0x77));
5447 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5452 ==========================================================================
5455 Load RF sleep-mode setup
5457 ==========================================================================
5459 VOID RT30xxLoadRFSleepModeSetup(
5460 IN PRTMP_ADAPTER pAd)
5465 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5466 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5468 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5470 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5471 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5473 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5475 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5476 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5478 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5480 // RX_CTB_en, RF R21 register Bit 7 to 0
5481 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5483 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5485 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5486 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5488 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5490 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5491 MACValue |= 0x1D000000;
5492 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5496 ==========================================================================
5499 Reverse RF sleep-mode setup
5501 ==========================================================================
5503 VOID RT30xxReverseRFSleepModeSetup(
5504 IN PRTMP_ADAPTER pAd)
5509 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5510 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5512 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5514 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5515 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5517 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5519 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5520 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5522 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5524 // RX_CTB_en, RF R21 register Bit 7 to 1
5525 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5527 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5529 // LDORF_VC, RF R27 register Bit 2 to 0
5530 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5531 if ((pAd->MACVersion & 0xffff) < 0x0211)
5532 RFValue = (RFValue & (~0x77)) | 0x3;
5534 RFValue = (RFValue & (~0x77));
5535 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5537 // RT3071 version E has fixed this issue
5538 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5540 // patch tx EVM issue temporarily
5541 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5542 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5543 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5547 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5548 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5549 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5556 ==========================================================================
5559 IRQL = PASSIVE_LEVEL
5560 IRQL = DISPATCH_LEVEL
5562 ==========================================================================
5564 VOID AsicSwitchChannel(
5565 IN PRTMP_ADAPTER pAd,
5569 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5570 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5572 UINT32 Value = 0; //BbpReg, Value;
5573 RTMP_RF_REGS *RFRegTable;
5575 // Search Tx power value
5577 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5578 // in ChannelList, so use TxPower array instead.
5580 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5582 if (Channel == pAd->TxPower[index].Channel)
5584 TxPwer = pAd->TxPower[index].Power;
5585 TxPwer2 = pAd->TxPower[index].Power2;
5590 for (index = 0; index < pAd->ChannelListNum; index++)
5592 if (Channel == pAd->ChannelList[index].Channel)
5594 TxPwer = pAd->ChannelList[index].Power;
5595 TxPwer2 = pAd->ChannelList[index].Power2;
5601 if (index == MAX_NUM_OF_CHANNELS)
5603 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5607 // The RF programming sequence is difference between 3xxx and 2xxx
5608 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5609 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5611 /* modify by WY for Read RF Reg. error */
5614 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5616 if (Channel == FreqItems3020[index].Channel)
5618 // Programming channel parameters
5619 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5620 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5621 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5622 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5623 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5626 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5627 RFValue = (RFValue & 0xE0) | TxPwer;
5628 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5631 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5632 RFValue = (RFValue & 0xE0) | TxPwer2;
5633 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5635 // Tx/Rx Stream setting
5636 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5637 //if (IS_RT3090(pAd))
5638 // RFValue |= 0x01; // Enable RF block.
5639 RFValue &= 0x03; //clear bit[7~2]
5640 if (pAd->Antenna.field.TxPath == 1)
5642 else if (pAd->Antenna.field.TxPath == 2)
5644 if (pAd->Antenna.field.RxPath == 1)
5646 else if (pAd->Antenna.field.RxPath == 2)
5648 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5651 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5652 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5653 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5656 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5658 RFValue = pAd->Mlme.CaliBW40RfR24;
5659 //DISABLE_11N_CHECK(pAd);
5663 RFValue = pAd->Mlme.CaliBW20RfR24;
5665 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5666 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5669 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5670 RFValue = RFValue | 0x1;
5671 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5673 // latch channel for future usage.
5674 pAd->LatchRfRegs.Channel = Channel;
5676 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5681 pAd->Antenna.field.TxPath,
5682 FreqItems3020[index].N,
5683 FreqItems3020[index].K,
5684 FreqItems3020[index].R));
5694 RFRegTable = RF2850RegTable;
5696 switch (pAd->RfIcType)
5703 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5705 if (Channel == RFRegTable[index].Channel)
5707 R2 = RFRegTable[index].R2;
5708 if (pAd->Antenna.field.TxPath == 1)
5710 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5713 if (pAd->Antenna.field.RxPath == 2)
5715 R2 |= 0x40; // write 1 to off Rxpath.
5717 else if (pAd->Antenna.field.RxPath == 1)
5719 R2 |= 0x20040; // write 1 to off RxPath
5724 // initialize R3, R4
5725 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5726 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5728 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5730 if ((TxPwer >= -7) && (TxPwer < 0))
5732 TxPwer = (7+TxPwer);
5733 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5734 R3 |= (TxPwer << 10);
5735 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5739 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5740 R3 |= (TxPwer << 10) | (1 << 9);
5744 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5746 TxPwer2 = (7+TxPwer2);
5747 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5748 R4 |= (TxPwer2 << 7);
5749 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5753 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5754 R4 |= (TxPwer2 << 7) | (1 << 6);
5759 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5760 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5763 // Based on BBP current mode before changing RF channel.
5764 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5770 pAd->LatchRfRegs.Channel = Channel;
5771 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5772 pAd->LatchRfRegs.R2 = R2;
5773 pAd->LatchRfRegs.R3 = R3;
5774 pAd->LatchRfRegs.R4 = R4;
5776 // Set RF value 1's set R3[bit2] = [0]
5777 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5778 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5779 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5780 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5784 // Set RF value 2's set R3[bit2] = [1]
5785 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5786 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5787 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5788 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5792 // Set RF value 3's set R3[bit2] = [0]
5793 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5794 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5795 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5796 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5808 // Change BBP setting during siwtch from a->g, g->a
5811 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5813 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5814 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5815 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5816 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.
5817 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5819 // Rx High power VGA offset for LNA select
5820 if (pAd->NicConfig2.field.ExternalLNAForG)
5822 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5823 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5827 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5828 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5831 // 5G band selection PIN, bit1 and bit2 are complement
5832 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5835 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5837 // Turn off unused PA or LNA when only 1T or 1R
5838 if (pAd->Antenna.field.TxPath == 1)
5840 TxPinCfg &= 0xFFFFFFF3;
5842 if (pAd->Antenna.field.RxPath == 1)
5844 TxPinCfg &= 0xFFFFF3FF;
5847 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5851 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5853 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5854 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5855 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5856 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.
5857 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5859 // Rx High power VGA offset for LNA select
5860 if (pAd->NicConfig2.field.ExternalLNAForA)
5862 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5866 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5869 // 5G band selection PIN, bit1 and bit2 are complement
5870 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5873 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5875 // Turn off unused PA or LNA when only 1T or 1R
5876 if (pAd->Antenna.field.TxPath == 1)
5878 TxPinCfg &= 0xFFFFFFF3;
5880 if (pAd->Antenna.field.RxPath == 1)
5882 TxPinCfg &= 0xFFFFF3FF;
5885 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5888 // R66 should be set according to Channel and use 20MHz when scanning
5889 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5891 RTMPSetAGCInitValue(pAd, BW_20);
5893 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5896 // On 11A, We should delay and wait RF/BBP to be stable
5897 // and the appropriate time should be 1000 micro seconds
5898 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5900 RTMPusecDelay(1000);
5902 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",
5905 (R3 & 0x00003e00) >> 9,
5906 (R4 & 0x000007c0) >> 6,
5907 pAd->Antenna.field.TxPath,
5908 pAd->LatchRfRegs.R1,
5909 pAd->LatchRfRegs.R2,
5910 pAd->LatchRfRegs.R3,
5911 pAd->LatchRfRegs.R4));
5915 ==========================================================================
5917 This function is required for 2421 only, and should not be used during
5918 site survey. It's only required after NIC decided to stay at a channel
5919 for a longer period.
5920 When this function is called, it's always after AsicSwitchChannel().
5922 IRQL = PASSIVE_LEVEL
5923 IRQL = DISPATCH_LEVEL
5925 ==========================================================================
5927 VOID AsicLockChannel(
5928 IN PRTMP_ADAPTER pAd,
5934 ==========================================================================
5937 IRQL = PASSIVE_LEVEL
5938 IRQL = DISPATCH_LEVEL
5940 ==========================================================================
5942 VOID AsicAntennaSelect(
5943 IN PRTMP_ADAPTER pAd,
5946 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
5948 // patch for AsicSetRxAnt failed
5949 pAd->RxAnt.EvaluatePeriod = 0;
5951 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
5952 // valid indication of the distance between this AP and its clients.
5953 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5957 // if no traffic then reset average rssi to trigger evaluation
5958 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
5960 pAd->RxAnt.Pair1LastAvgRssi = (-99);
5961 pAd->RxAnt.Pair2LastAvgRssi = (-99);
5962 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
5965 pAd->StaCfg.NumOfAvgRssiSample = 0;
5966 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
5968 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
5970 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
5971 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
5973 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
5974 AsicEvaluateRxAnt(pAd);
5979 // if not connected, always switch antenna to try to connect
5982 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
5983 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
5984 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
5986 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
5988 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
5994 ========================================================================
5996 Routine Description:
5997 Antenna miscellaneous setting.
6000 pAd Pointer to our adapter
6001 BandState Indicate current Band State.
6006 IRQL <= DISPATCH_LEVEL
6009 1.) Frame End type control
6010 only valid for G only (RF_2527 & RF_2529)
6011 0: means DPDT, set BBP R4 bit 5 to 1
6012 1: means SPDT, set BBP R4 bit 5 to 0
6015 ========================================================================
6017 VOID AsicAntennaSetting(
6018 IN PRTMP_ADAPTER pAd,
6019 IN ABGBAND_STATE BandState)
6023 VOID AsicRfTuningExec(
6024 IN PVOID SystemSpecific1,
6025 IN PVOID FunctionContext,
6026 IN PVOID SystemSpecific2,
6027 IN PVOID SystemSpecific3)
6032 ==========================================================================
6034 Gives CCK TX rate 2 more dB TX power.
6035 This routine works only in LINK UP in INFRASTRUCTURE mode.
6037 calculate desired Tx power in RF R3.Tx0~5, should consider -
6038 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6039 1. TxPowerPercentage
6040 2. auto calibration based on TSSI feedback
6041 3. extra 2 db for CCK
6042 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6044 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6045 it should be called AFTER MlmeDynamicTxRatSwitching()
6046 ==========================================================================
6048 VOID AsicAdjustTxPower(
6049 IN PRTMP_ADAPTER pAd)
6053 BOOLEAN bAutoTxAgc = FALSE;
6054 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6055 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6056 PCHAR pTxAgcCompensate;
6062 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6064 if (pAd->CommonCfg.CentralChannel > 14)
6066 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6067 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6068 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6069 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6070 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6074 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6075 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6076 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6077 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6078 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6083 if (pAd->CommonCfg.Channel > 14)
6085 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6086 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6087 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6088 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6089 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6093 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6094 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6095 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6096 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6097 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6101 // TX power compensation for temperature variation based on TSSI. try every 4 second
6102 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6104 if (pAd->CommonCfg.Channel <= 14)
6107 bAutoTxAgc = pAd->bAutoTxAgcG;
6108 TssiRef = pAd->TssiRefG;
6109 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6110 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6111 TxAgcStep = pAd->TxAgcStepG;
6112 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6117 bAutoTxAgc = pAd->bAutoTxAgcA;
6118 TssiRef = pAd->TssiRefA;
6119 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6120 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6121 TxAgcStep = pAd->TxAgcStepA;
6122 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6127 /* BbpR1 is unsigned char */
6128 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6130 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6131 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6132 /* step value is defined in pAd->TxAgcStepG for tx power value */
6134 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6135 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6136 above value are examined in mass factory production */
6137 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6139 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6140 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6141 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6143 if (BbpR49 > pTssiMinusBoundary[1])
6145 // Reading is larger than the reference value
6146 // check for how large we need to decrease the Tx power
6147 for (idx = 1; idx < 5; idx++)
6149 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6152 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6153 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6155 DeltaPwr += (*pTxAgcCompensate);
6156 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6157 BbpR49, TssiRef, TxAgcStep, idx-1));
6159 else if (BbpR49 < pTssiPlusBoundary[1])
6161 // Reading is smaller than the reference value
6162 // check for how large we need to increase the Tx power
6163 for (idx = 1; idx < 5; idx++)
6165 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6168 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6169 *pTxAgcCompensate = TxAgcStep * (idx-1);
6170 DeltaPwr += (*pTxAgcCompensate);
6171 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6172 BbpR49, TssiRef, TxAgcStep, idx-1));
6176 *pTxAgcCompensate = 0;
6177 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6178 BbpR49, TssiRef, TxAgcStep, 0));
6184 if (pAd->CommonCfg.Channel <= 14)
6186 bAutoTxAgc = pAd->bAutoTxAgcG;
6187 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6191 bAutoTxAgc = pAd->bAutoTxAgcA;
6192 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6196 DeltaPwr += (*pTxAgcCompensate);
6199 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6202 /* calculate delta power based on the percentage specified from UI */
6203 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6204 // We lower TX power here according to the percentage specified from UI
6205 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6207 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6209 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6213 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6217 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6221 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6226 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6231 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6233 /* reset different new tx power for different TX rate */
6236 if (TxPwr[i] != 0xffffffff)
6240 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6242 if ((Value + DeltaPwr) < 0)
6244 Value = 0; /* min */
6246 else if ((Value + DeltaPwr) > 0xF)
6248 Value = 0xF; /* max */
6252 Value += DeltaPwr; /* temperature compensation */
6255 /* fill new value to CSR offset */
6256 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6259 /* write tx power value to CSR */
6260 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6261 TX power for OFDM 6M/9M
6262 TX power for CCK5.5M/11M
6263 TX power for CCK1M/2M */
6264 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6265 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6273 ==========================================================================
6275 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6276 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6277 the wakeup timer timeout. Driver has to issue a separate command to wake
6280 IRQL = DISPATCH_LEVEL
6282 ==========================================================================
6284 VOID AsicSleepThenAutoWakeup(
6285 IN PRTMP_ADAPTER pAd,
6286 IN USHORT TbttNumToNextWakeUp)
6288 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6292 ==========================================================================
6294 AsicForceWakeup() is used whenever manual wakeup is required
6295 AsicForceSleep() should only be used when not in INFRA BSS. When
6296 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6297 ==========================================================================
6299 VOID AsicForceSleep(
6300 IN PRTMP_ADAPTER pAd)
6306 ==========================================================================
6308 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6311 IRQL = PASSIVE_LEVEL
6312 IRQL = DISPATCH_LEVEL
6313 ==========================================================================
6315 VOID AsicForceWakeup(
6316 IN PRTMP_ADAPTER pAd,
6319 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6320 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6324 ==========================================================================
6328 IRQL = DISPATCH_LEVEL
6330 ==========================================================================
6333 IN PRTMP_ADAPTER pAd,
6337 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6338 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6340 Addr4 = (ULONG)(pBssid[0]) |
6341 (ULONG)(pBssid[1] << 8) |
6342 (ULONG)(pBssid[2] << 16) |
6343 (ULONG)(pBssid[3] << 24);
6344 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6347 // always one BSSID in STA mode
6348 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6350 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6353 VOID AsicSetMcastWC(
6354 IN PRTMP_ADAPTER pAd)
6356 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6359 pEntry->Sst = SST_ASSOC;
6360 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6361 pEntry->PsMode = PWR_ACTIVE;
6362 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6363 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6367 ==========================================================================
6370 IRQL = DISPATCH_LEVEL
6372 ==========================================================================
6374 VOID AsicDelWcidTab(
6375 IN PRTMP_ADAPTER pAd,
6378 ULONG Addr0 = 0x0, Addr1 = 0x0;
6381 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6382 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6383 RTMP_IO_WRITE32(pAd, offset, Addr0);
6385 RTMP_IO_WRITE32(pAd, offset, Addr1);
6389 ==========================================================================
6392 IRQL = DISPATCH_LEVEL
6394 ==========================================================================
6397 IN PRTMP_ADAPTER pAd)
6399 TX_LINK_CFG_STRUC TxLinkCfg;
6402 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6403 TxLinkCfg.field.TxRDGEn = 1;
6404 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6406 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6409 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6411 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6415 ==========================================================================
6418 IRQL = DISPATCH_LEVEL
6420 ==========================================================================
6422 VOID AsicDisableRDG(
6423 IN PRTMP_ADAPTER pAd)
6425 TX_LINK_CFG_STRUC TxLinkCfg;
6429 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6430 TxLinkCfg.field.TxRDGEn = 0;
6431 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6433 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6436 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6437 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6440 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6441 if (pAd->CommonCfg.bEnableTxBurst)
6444 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6448 ==========================================================================
6451 IRQL = PASSIVE_LEVEL
6452 IRQL = DISPATCH_LEVEL
6454 ==========================================================================
6456 VOID AsicDisableSync(
6457 IN PRTMP_ADAPTER pAd)
6459 BCN_TIME_CFG_STRUC csr;
6461 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6463 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6464 // that NIC will never wakes up because TSF stops and no more
6466 pAd->TbttTickCount = 0;
6467 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6468 csr.field.bBeaconGen = 0;
6469 csr.field.bTBTTEnable = 0;
6470 csr.field.TsfSyncMode = 0;
6471 csr.field.bTsfTicking = 0;
6472 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6477 ==========================================================================
6480 IRQL = DISPATCH_LEVEL
6482 ==========================================================================
6484 VOID AsicEnableBssSync(
6485 IN PRTMP_ADAPTER pAd)
6487 BCN_TIME_CFG_STRUC csr;
6489 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6491 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6494 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6495 csr.field.bTsfTicking = 1;
6496 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6497 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6498 csr.field.bTBTTEnable = 1;
6501 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6505 ==========================================================================
6508 BEACON frame in shared memory should be built ok before this routine
6509 can be called. Otherwise, a garbage frame maybe transmitted out every
6512 IRQL = DISPATCH_LEVEL
6514 ==========================================================================
6516 VOID AsicEnableIbssSync(
6517 IN PRTMP_ADAPTER pAd)
6519 BCN_TIME_CFG_STRUC csr9;
6523 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6525 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6526 csr9.field.bBeaconGen = 0;
6527 csr9.field.bTBTTEnable = 0;
6528 csr9.field.bTsfTicking = 0;
6529 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6533 // move BEACON TXD and frame content to on-chip memory
6534 ptr = (PUCHAR)&pAd->BeaconTxWI;
6535 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6537 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6541 // start right after the 16-byte TXWI field
6542 ptr = pAd->BeaconBuf;
6543 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6545 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6550 // start sending BEACON
6551 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6552 csr9.field.bTsfTicking = 1;
6553 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6554 csr9.field.bTBTTEnable = 1;
6555 csr9.field.bBeaconGen = 1;
6556 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6560 ==========================================================================
6563 IRQL = PASSIVE_LEVEL
6564 IRQL = DISPATCH_LEVEL
6566 ==========================================================================
6568 VOID AsicSetEdcaParm(
6569 IN PRTMP_ADAPTER pAd,
6570 IN PEDCA_PARM pEdcaParm)
6572 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6573 AC_TXOP_CSR0_STRUC csr0;
6574 AC_TXOP_CSR1_STRUC csr1;
6575 AIFSN_CSR_STRUC AifsnCsr;
6576 CWMIN_CSR_STRUC CwminCsr;
6577 CWMAX_CSR_STRUC CwmaxCsr;
6584 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6586 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6587 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6588 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6590 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6591 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6594 //========================================================
6595 // MAC Register has a copy .
6596 //========================================================
6597 if( pAd->CommonCfg.bEnableTxBurst )
6599 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6600 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6603 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6604 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6605 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6606 Ac0Cfg.field.Aifsn = 2;
6607 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6609 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6610 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6611 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6612 Ac1Cfg.field.Aifsn = 2;
6613 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6615 if (pAd->CommonCfg.PhyMode == PHY_11B)
6617 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6618 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6622 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6623 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6625 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6626 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6627 Ac2Cfg.field.Aifsn = 2;
6628 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6629 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6630 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6631 Ac3Cfg.field.Aifsn = 2;
6632 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6634 //========================================================
6635 // DMA Register has a copy too.
6636 //========================================================
6637 csr0.field.Ac0Txop = 0; // QID_AC_BE
6638 csr0.field.Ac1Txop = 0; // QID_AC_BK
6639 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6640 if (pAd->CommonCfg.PhyMode == PHY_11B)
6642 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6643 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6647 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6648 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6650 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6653 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6654 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6655 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6656 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6657 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6660 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6661 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6662 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6663 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6664 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6666 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6668 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6672 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6673 //========================================================
6674 // MAC Register has a copy.
6675 //========================================================
6677 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6678 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6680 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6682 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6683 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6684 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6685 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6687 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6688 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6689 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6690 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6692 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6693 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6694 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6695 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6698 // Tuning for Wi-Fi WMM S06
6699 if (pAd->CommonCfg.bWiFiTest &&
6700 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6701 Ac2Cfg.field.Aifsn -= 1;
6703 // Tuning for TGn Wi-Fi 5.2.32
6704 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6705 if (STA_TGN_WIFI_ON(pAd) &&
6706 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6708 Ac0Cfg.field.Aifsn = 3;
6709 Ac2Cfg.field.AcTxop = 5;
6713 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6715 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6716 Ac2Cfg.field.Aifsn = 5;
6721 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6722 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6723 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6724 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6727 if (pAd->CommonCfg.bWiFiTest)
6729 if (Ac3Cfg.field.AcTxop == 102)
6731 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6732 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6733 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6734 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6735 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6738 //#endif // WIFI_TEST //
6740 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6741 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6742 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6743 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6746 //========================================================
6747 // DMA Register has a copy too.
6748 //========================================================
6749 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6750 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6751 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6753 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6754 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6755 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6758 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6759 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6760 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6762 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6764 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6767 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6768 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6769 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6770 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6771 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6774 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6775 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6776 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6779 // Tuning for Wi-Fi WMM S06
6780 if (pAd->CommonCfg.bWiFiTest &&
6781 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6782 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6784 // Tuning for TGn Wi-Fi 5.2.32
6785 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6786 if (STA_TGN_WIFI_ON(pAd) &&
6787 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6789 AifsnCsr.field.Aifsn0 = 3;
6790 AifsnCsr.field.Aifsn2 = 7;
6794 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6797 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6799 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6800 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
6803 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6805 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6808 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6809 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6810 pEdcaParm->Aifsn[0],
6811 pEdcaParm->Cwmin[0],
6812 pEdcaParm->Cwmax[0],
6813 pEdcaParm->Txop[0]<<5,
6814 pEdcaParm->bACM[0]));
6815 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6816 pEdcaParm->Aifsn[1],
6817 pEdcaParm->Cwmin[1],
6818 pEdcaParm->Cwmax[1],
6819 pEdcaParm->Txop[1]<<5,
6820 pEdcaParm->bACM[1]));
6821 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6822 pEdcaParm->Aifsn[2],
6823 pEdcaParm->Cwmin[2],
6824 pEdcaParm->Cwmax[2],
6825 pEdcaParm->Txop[2]<<5,
6826 pEdcaParm->bACM[2]));
6827 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6828 pEdcaParm->Aifsn[3],
6829 pEdcaParm->Cwmin[3],
6830 pEdcaParm->Cwmax[3],
6831 pEdcaParm->Txop[3]<<5,
6832 pEdcaParm->bACM[3]));
6838 ==========================================================================
6841 IRQL = PASSIVE_LEVEL
6842 IRQL = DISPATCH_LEVEL
6844 ==========================================================================
6846 VOID AsicSetSlotTime(
6847 IN PRTMP_ADAPTER pAd,
6848 IN BOOLEAN bUseShortSlotTime)
6851 UINT32 RegValue = 0;
6853 if (pAd->CommonCfg.Channel > 14)
6854 bUseShortSlotTime = TRUE;
6856 if (bUseShortSlotTime)
6857 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6859 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6861 SlotTime = (bUseShortSlotTime)? 9 : 20;
6864 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6865 if (pAd->CommonCfg.bEnableTxBurst)
6870 // For some reasons, always set it to short slot time.
6872 // ToDo: Should consider capability with 11B
6874 if (pAd->StaCfg.BssType == BSS_ADHOC)
6877 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6878 RegValue = RegValue & 0xFFFFFF00;
6880 RegValue |= SlotTime;
6882 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6886 ========================================================================
6888 Add Shared key information into ASIC.
6889 Update shared key, TxMic and RxMic to Asic Shared key table
6890 Update its cipherAlg to Asic Shared key Mode.
6893 ========================================================================
6895 VOID AsicAddSharedKeyEntry(
6896 IN PRTMP_ADAPTER pAd,
6904 ULONG offset; //, csr0;
6905 SHAREDKEY_MODE_STRUC csr1;
6907 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6908 //============================================================================================
6910 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6911 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6912 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]));
6915 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6916 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6920 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6921 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6923 //============================================================================================
6925 // fill key material - key + TX MIC + RX MIC
6930 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6931 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
6933 offset += MAX_LEN_OF_SHARE_KEY;
6936 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
6942 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
6948 // Update cipher algorithm. WSTA always use BSS0
6950 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6951 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6952 if ((BssIndex%2) == 0)
6955 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6956 else if (KeyIdx == 1)
6957 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6958 else if (KeyIdx == 2)
6959 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6961 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6966 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6967 else if (KeyIdx == 1)
6968 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6969 else if (KeyIdx == 2)
6970 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6972 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6974 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6975 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6979 // IRQL = DISPATCH_LEVEL
6980 VOID AsicRemoveSharedKeyEntry(
6981 IN PRTMP_ADAPTER pAd,
6986 SHAREDKEY_MODE_STRUC csr1;
6988 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6990 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6991 if ((BssIndex%2) == 0)
6994 csr1.field.Bss0Key0CipherAlg = 0;
6995 else if (KeyIdx == 1)
6996 csr1.field.Bss0Key1CipherAlg = 0;
6997 else if (KeyIdx == 2)
6998 csr1.field.Bss0Key2CipherAlg = 0;
7000 csr1.field.Bss0Key3CipherAlg = 0;
7005 csr1.field.Bss1Key0CipherAlg = 0;
7006 else if (KeyIdx == 1)
7007 csr1.field.Bss1Key1CipherAlg = 0;
7008 else if (KeyIdx == 2)
7009 csr1.field.Bss1Key2CipherAlg = 0;
7011 csr1.field.Bss1Key3CipherAlg = 0;
7013 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7014 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7015 ASSERT(BssIndex < 4);
7021 VOID AsicUpdateWCIDAttribute(
7022 IN PRTMP_ADAPTER pAd,
7026 IN BOOLEAN bUsePairewiseKeyTable)
7028 ULONG WCIDAttri = 0, offset;
7031 // Update WCID attribute.
7032 // Only TxKey could update WCID attribute.
7034 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7035 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7036 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7039 VOID AsicUpdateWCIDIVEIV(
7040 IN PRTMP_ADAPTER pAd,
7047 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7049 RTMP_IO_WRITE32(pAd, offset, uIV);
7050 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7053 VOID AsicUpdateRxWCIDTable(
7054 IN PRTMP_ADAPTER pAd,
7061 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7062 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7063 RTMP_IO_WRITE32(pAd, offset, Addr);
7064 Addr = pAddr[4] + (pAddr[5] << 8);
7065 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7070 ========================================================================
7072 Routine Description:
7073 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7076 pAd Pointer to our adapter
7077 WCID WCID Entry number.
7078 BssIndex BSSID index, station or none multiple BSSID support
7079 this value should be 0.
7080 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7081 pCipherKey Pointer to Cipher Key.
7082 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7083 otherwise PairewiseKey table
7084 bTxKey This is the transmit key if enabled.
7090 This routine will set the relative key stuff to Asic including WCID attribute,
7091 Cipher Key, Cipher algorithm and IV/EIV.
7093 IV/EIV will be update if this CipherKey is the transmission key because
7094 ASIC will base on IV's KeyID value to select Cipher Key.
7096 If bTxKey sets to FALSE, this is not the TX key, but it could be
7099 For AP mode bTxKey must be always set to TRUE.
7100 ========================================================================
7102 VOID AsicAddKeyEntry(
7103 IN PRTMP_ADAPTER pAd,
7107 IN PCIPHER_KEY pCipherKey,
7108 IN BOOLEAN bUsePairewiseKeyTable,
7113 PUCHAR pKey = pCipherKey->Key;
7114 PUCHAR pTxMic = pCipherKey->TxMic;
7115 PUCHAR pRxMic = pCipherKey->RxMic;
7116 PUCHAR pTxtsc = pCipherKey->TxTsc;
7117 UCHAR CipherAlg = pCipherKey->CipherAlg;
7118 SHAREDKEY_MODE_STRUC csr1;
7120 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7122 // 1.) decide key table offset
7124 if (bUsePairewiseKeyTable)
7125 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7127 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7130 // 2.) Set Key to Asic
7132 //for (i = 0; i < KeyLen; i++)
7135 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7136 offset += MAX_LEN_OF_PEER_KEY;
7139 // 3.) Set MIC key if available
7143 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7145 offset += LEN_TKIP_TXMICK;
7149 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7154 // 4.) Modify IV/EIV if needs
7155 // This will force Asic to use this key ID by setting IV.
7166 IV4 = (KeyIdx << 6);
7167 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7168 IV4 |= 0x20; // turn on extension bit means EIV existence
7170 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7171 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7177 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7179 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7182 if (!bUsePairewiseKeyTable)
7185 // Only update the shared key security mode
7187 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7188 if ((BssIndex % 2) == 0)
7191 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7192 else if (KeyIdx == 1)
7193 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7194 else if (KeyIdx == 2)
7195 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7197 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7202 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7203 else if (KeyIdx == 1)
7204 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7205 else if (KeyIdx == 2)
7206 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7208 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7210 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7213 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7218 ========================================================================
7220 Add Pair-wise key material into ASIC.
7221 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7224 ========================================================================
7226 VOID AsicAddPairwiseKeyEntry(
7227 IN PRTMP_ADAPTER pAd,
7230 IN CIPHER_KEY *pCipherKey)
7234 PUCHAR pKey = pCipherKey->Key;
7235 PUCHAR pTxMic = pCipherKey->TxMic;
7236 PUCHAR pRxMic = pCipherKey->RxMic;
7238 UCHAR CipherAlg = pCipherKey->CipherAlg;
7242 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7244 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7246 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7249 RTMP_IO_READ32(pAd, offset + i, &Value);
7252 offset += MAX_LEN_OF_PEER_KEY;
7258 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7265 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7269 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7270 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7271 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]));
7274 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7275 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7279 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7280 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7284 ========================================================================
7286 Remove Pair-wise key material from ASIC.
7289 ========================================================================
7291 VOID AsicRemovePairwiseKeyEntry(
7292 IN PRTMP_ADAPTER pAd,
7299 // re-set the entry's WCID attribute as OPEN-NONE.
7300 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7301 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7302 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7305 BOOLEAN AsicSendCommandToMcu(
7306 IN PRTMP_ADAPTER pAd,
7312 HOST_CMD_CSR_STRUC H2MCmd;
7313 H2M_MAILBOX_STRUC H2MMailbox;
7317 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7318 if (H2MMailbox.field.Owner == 0)
7327 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7333 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7334 H2MMailbox.field.CmdToken = Token;
7335 H2MMailbox.field.HighByte = Arg1;
7336 H2MMailbox.field.LowByte = Arg0;
7337 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7340 H2MCmd.field.HostCommand = Command;
7341 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7343 if (Command != 0x80)
7352 ========================================================================
7354 Routine Description:
7355 Verify the support rate for different PHY type
7358 pAd Pointer to our adapter
7363 IRQL = PASSIVE_LEVEL
7365 ========================================================================
7367 VOID RTMPCheckRates(
7368 IN PRTMP_ADAPTER pAd,
7369 IN OUT UCHAR SupRate[],
7370 IN OUT UCHAR *SupRateLen)
7372 UCHAR RateIdx, i, j;
7373 UCHAR NewRate[12], NewRateLen;
7377 if (pAd->CommonCfg.PhyMode == PHY_11B)
7382 // Check for support rates exclude basic rate bit
7383 for (i = 0; i < *SupRateLen; i++)
7384 for (j = 0; j < RateIdx; j++)
7385 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7386 NewRate[NewRateLen++] = SupRate[i];
7388 *SupRateLen = NewRateLen;
7389 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7392 BOOLEAN RTMPCheckChannel(
7393 IN PRTMP_ADAPTER pAd,
7394 IN UCHAR CentralChannel,
7398 UCHAR UpperChannel = 0, LowerChannel = 0;
7399 UCHAR NoEffectChannelinList = 0;
7401 // Find upper and lower channel according to 40MHz current operation.
7402 if (CentralChannel < Channel)
7404 UpperChannel = Channel;
7405 if (CentralChannel > 2)
7406 LowerChannel = CentralChannel - 2;
7410 else if (CentralChannel > Channel)
7412 UpperChannel = CentralChannel + 2;
7413 LowerChannel = Channel;
7416 for (k = 0;k < pAd->ChannelListNum;k++)
7418 if (pAd->ChannelList[k].Channel == UpperChannel)
7420 NoEffectChannelinList ++;
7422 if (pAd->ChannelList[k].Channel == LowerChannel)
7424 NoEffectChannelinList ++;
7428 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7429 if (NoEffectChannelinList == 2)
7436 ========================================================================
7438 Routine Description:
7439 Verify the support rate for HT phy type
7442 pAd Pointer to our adapter
7445 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7447 IRQL = PASSIVE_LEVEL
7449 ========================================================================
7451 BOOLEAN RTMPCheckHt(
7452 IN PRTMP_ADAPTER pAd,
7454 IN HT_CAPABILITY_IE *pHtCapability,
7455 IN ADD_HT_INFO_IE *pAddHtInfo)
7457 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7460 // If use AMSDU, set flag.
7461 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7462 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7463 // Save Peer Capability
7464 if (pHtCapability->HtCapInfo.ShortGIfor20)
7465 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7466 if (pHtCapability->HtCapInfo.ShortGIfor40)
7467 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7468 if (pHtCapability->HtCapInfo.TxSTBC)
7469 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7470 if (pHtCapability->HtCapInfo.RxSTBC)
7471 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7472 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7474 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7477 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7479 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7482 // Will check ChannelWidth for MCSSet[4] below
7483 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7484 switch (pAd->CommonCfg.RxStream)
7487 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7488 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7489 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7490 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7493 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7494 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7495 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7496 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7499 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7500 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7501 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7502 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7506 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7508 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7509 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7510 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7512 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7514 // Send Assoc Req with my HT capability.
7515 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7516 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7517 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7518 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7519 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7520 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7521 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7522 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7523 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7524 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7525 if (pAd->CommonCfg.bRdg)
7527 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7528 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7531 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7532 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7534 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7539 ========================================================================
7541 Routine Description:
7542 Verify the support rate for different PHY type
7545 pAd Pointer to our adapter
7550 IRQL = PASSIVE_LEVEL
7552 ========================================================================
7554 VOID RTMPUpdateMlmeRate(
7555 IN PRTMP_ADAPTER pAd)
7558 UCHAR ProperMlmeRate; //= RATE_54;
7559 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7560 BOOLEAN bMatch = FALSE;
7562 switch (pAd->CommonCfg.PhyMode)
7565 ProperMlmeRate = RATE_11;
7566 MinimumRate = RATE_1;
7568 case PHY_11BG_MIXED:
7569 case PHY_11ABGN_MIXED:
7570 case PHY_11BGN_MIXED:
7571 if ((pAd->MlmeAux.SupRateLen == 4) &&
7572 (pAd->MlmeAux.ExtRateLen == 0))
7574 ProperMlmeRate = RATE_11;
7576 ProperMlmeRate = RATE_24;
7578 if (pAd->MlmeAux.Channel <= 14)
7579 MinimumRate = RATE_1;
7581 MinimumRate = RATE_6;
7584 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7585 case PHY_11GN_MIXED:
7586 case PHY_11AGN_MIXED:
7587 case PHY_11AN_MIXED:
7589 ProperMlmeRate = RATE_24;
7590 MinimumRate = RATE_6;
7592 case PHY_11ABG_MIXED:
7593 ProperMlmeRate = RATE_24;
7594 if (pAd->MlmeAux.Channel <= 14)
7595 MinimumRate = RATE_1;
7597 MinimumRate = RATE_6;
7600 ProperMlmeRate = RATE_1;
7601 MinimumRate = RATE_1;
7605 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7607 for (j = 0; j < RateIdx; j++)
7609 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7611 if (j == ProperMlmeRate)
7623 if (bMatch == FALSE)
7625 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7627 for (j = 0; j < RateIdx; j++)
7629 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7631 if (j == ProperMlmeRate)
7644 if (bMatch == FALSE)
7646 ProperMlmeRate = MinimumRate;
7649 pAd->CommonCfg.MlmeRate = MinimumRate;
7650 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7651 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7653 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7654 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7655 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7656 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7660 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7661 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7662 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7663 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7666 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7670 IN PRTMP_ADAPTER pAd,
7677 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7682 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7684 larger = max(Rssi0, Rssi1);
7687 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7689 larger = max(larger, Rssi2);
7699 // Antenna divesity use GPIO3 and EESK pin for control
7700 // Antenna and EEPROM access are both using EESK pin,
7701 // Therefor we should avoid accessing EESK at the same time
7702 // Then restore antenna after EEPROM access
7704 IN PRTMP_ADAPTER pAd,
7711 if ((pAd->EepromAccess) ||
7712 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
7713 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
7714 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
7715 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
7720 // the antenna selection is through firmware and MAC register(GPIO3)
7724 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
7726 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
7728 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
7730 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
7731 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
7736 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
7738 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
7740 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
7743 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
7744 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
7751 ========================================================================
7752 Routine Description:
7753 Periodic evaluate antenna link status
7756 pAd - Adapter pointer
7761 ========================================================================
7763 VOID AsicEvaluateRxAnt(
7764 IN PRTMP_ADAPTER pAd)
7768 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7769 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7770 fRTMP_ADAPTER_RADIO_OFF |
7771 fRTMP_ADAPTER_NIC_NOT_EXIST |
7772 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
7773 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
7775 || (pAd->EepromAccess)
7782 //if (pAd->StaCfg.Psm == PWR_SAVE)
7786 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
7787 // one is antenna diversity:there is only one antenna can rx and tx
7788 // the other is failed antenna remove:two physical antenna can rx and tx
7789 if (pAd->NicConfig2.field.AntDiversity)
7791 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
7792 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
7794 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
7796 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
7797 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
7798 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
7800 // a one-shot timer to end the evalution
7801 // dynamic adjust antenna evaluation period according to the traffic
7802 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7803 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
7805 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7809 if (pAd->StaCfg.Psm == PWR_SAVE)
7812 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7814 if(pAd->Antenna.field.RxPath == 3)
7818 else if(pAd->Antenna.field.RxPath == 2)
7822 else if(pAd->Antenna.field.RxPath == 1)
7826 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7828 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7831 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7832 pAd->RalinkCounters.OneSecTxRetryOkCount +
7833 pAd->RalinkCounters.OneSecTxFailCount;
7835 // dynamic adjust antenna evaluation period according to the traffic
7836 if (TxTotalCnt > 50)
7838 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7839 pAd->Mlme.bLowThroughput = FALSE;
7843 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7844 pAd->Mlme.bLowThroughput = TRUE;
7851 ========================================================================
7852 Routine Description:
7853 After evaluation, check antenna link status
7856 pAd - Adapter pointer
7861 ========================================================================
7863 VOID AsicRxAntEvalTimeout(
7864 IN PVOID SystemSpecific1,
7865 IN PVOID FunctionContext,
7866 IN PVOID SystemSpecific2,
7867 IN PVOID SystemSpecific3)
7869 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7871 CHAR larger = -127, rssi0, rssi1, rssi2;
7873 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7874 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7875 fRTMP_ADAPTER_RADIO_OFF |
7876 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
7877 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
7879 || (pAd->EepromAccess)
7885 //if (pAd->StaCfg.Psm == PWR_SAVE)
7888 if (pAd->NicConfig2.field.AntDiversity)
7890 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
7895 // select PrimaryRxAntPair
7896 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
7897 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
7899 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
7900 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
7901 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
7903 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
7904 pAd->RxAnt.EvaluateStableCnt = 0;
7908 // if the evaluated antenna is not better than original, switch back to original antenna
7909 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
7910 pAd->RxAnt.EvaluateStableCnt ++;
7913 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
7915 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
7916 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
7920 if (pAd->StaCfg.Psm == PWR_SAVE)
7923 // if the traffic is low, use average rssi as the criteria
7924 if (pAd->Mlme.bLowThroughput == TRUE)
7926 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7927 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7928 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7932 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7933 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7934 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7937 if(pAd->Antenna.field.RxPath == 3)
7939 larger = max(rssi0, rssi1);
7941 if (larger > (rssi2 + 20))
7942 pAd->Mlme.RealRxPath = 2;
7944 pAd->Mlme.RealRxPath = 3;
7946 else if(pAd->Antenna.field.RxPath == 2)
7948 if (rssi0 > (rssi1 + 20))
7949 pAd->Mlme.RealRxPath = 1;
7951 pAd->Mlme.RealRxPath = 2;
7954 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7956 if(pAd->Mlme.RealRxPath == 3)
7960 else if(pAd->Mlme.RealRxPath == 2)
7964 else if(pAd->Mlme.RealRxPath == 1)
7968 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7975 VOID APSDPeriodicExec(
7976 IN PVOID SystemSpecific1,
7977 IN PVOID FunctionContext,
7978 IN PVOID SystemSpecific2,
7979 IN PVOID SystemSpecific3)
7981 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7983 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7986 pAd->CommonCfg.TriggerTimerCount++;
7990 ========================================================================
7991 Routine Description:
7992 Set/reset MAC registers according to bPiggyBack parameter
7995 pAd - Adapter pointer
7996 bPiggyBack - Enable / Disable Piggy-Back
8001 ========================================================================
8003 VOID RTMPSetPiggyBack(
8004 IN PRTMP_ADAPTER pAd,
8005 IN BOOLEAN bPiggyBack)
8007 TX_LINK_CFG_STRUC TxLinkCfg;
8009 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8011 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8012 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8016 ========================================================================
8017 Routine Description:
8018 check if this entry need to switch rate automatically
8028 ========================================================================
8030 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8031 IN PRTMP_ADAPTER pAd,
8032 IN PMAC_TABLE_ENTRY pEntry)
8034 BOOLEAN result = TRUE;
8037 // only associated STA counts
8038 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8040 result = pAd->StaCfg.bAutoTxRateSwitch;
8050 BOOLEAN RTMPAutoRateSwitchCheck(
8051 IN PRTMP_ADAPTER pAd)
8053 if (pAd->StaCfg.bAutoTxRateSwitch)
8061 ========================================================================
8062 Routine Description:
8063 check if this entry need to fix tx legacy rate
8073 ========================================================================
8075 UCHAR RTMPStaFixedTxMode(
8076 IN PRTMP_ADAPTER pAd,
8077 IN PMAC_TABLE_ENTRY pEntry)
8079 UCHAR tx_mode = FIXED_TXMODE_HT;
8082 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8089 ========================================================================
8090 Routine Description:
8091 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8101 ========================================================================
8103 VOID RTMPUpdateLegacyTxSetting(
8104 UCHAR fixed_tx_mode,
8105 PMAC_TABLE_ENTRY pEntry)
8107 HTTRANSMIT_SETTING TransmitSetting;
8109 if (fixed_tx_mode == FIXED_TXMODE_HT)
8112 TransmitSetting.word = 0;
8114 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8115 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8117 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8119 TransmitSetting.field.MODE = MODE_CCK;
8120 // CCK mode allow MCS 0~3
8121 if (TransmitSetting.field.MCS > MCS_3)
8122 TransmitSetting.field.MCS = MCS_3;
8126 TransmitSetting.field.MODE = MODE_OFDM;
8127 // OFDM mode allow MCS 0~7
8128 if (TransmitSetting.field.MCS > MCS_7)
8129 TransmitSetting.field.MCS = MCS_7;
8132 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8134 pEntry->HTPhyMode.word = TransmitSetting.word;
8135 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8136 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8141 ==========================================================================
8143 dynamic tune BBP R66 to find a balance between sensibility and
8146 IRQL = DISPATCH_LEVEL
8148 ==========================================================================
8150 VOID AsicStaBbpTuning(
8151 IN PRTMP_ADAPTER pAd)
8153 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8156 // 2860C did not support Fase CCA, therefore can't tune
8157 if (pAd->MACVersion == 0x28600100)
8163 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8166 if ((pAd->OpMode == OPMODE_STA)
8167 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8169 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8172 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8175 if (pAd->Antenna.field.RxPath > 1)
8176 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8178 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8180 if (pAd->LatchRfRegs.Channel <= 14)
8183 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8184 // Otherwise, it will have some throughput side effect when low RSSI
8187 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8189 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8190 if (OrigR66Value != R66)
8192 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8197 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8198 if (OrigR66Value != R66)
8200 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8207 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8209 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8210 if (OrigR66Value != R66)
8212 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8217 R66 = 0x2E + GET_LNA_GAIN(pAd);
8218 if (OrigR66Value != R66)
8220 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8228 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8230 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8232 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8233 if (OrigR66Value != R66)
8235 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8240 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8241 if (OrigR66Value != R66)
8243 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8249 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8251 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8252 if (OrigR66Value != R66)
8254 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8259 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8260 if (OrigR66Value != R66)
8262 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8272 VOID RTMPSetAGCInitValue(
8273 IN PRTMP_ADAPTER pAd,
8278 if (pAd->LatchRfRegs.Channel <= 14)
8280 R66 = 0x2E + GET_LNA_GAIN(pAd);
8281 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8285 if (BandWidth == BW_20)
8287 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8288 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8292 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8293 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8299 VOID AsicTurnOffRFClk(
8300 IN PRTMP_ADAPTER pAd,
8304 UINT32 R1 = 0, R2 = 0, R3 = 0;
8306 RTMP_RF_REGS *RFRegTable;
8309 // The RF programming sequence is difference between 3xxx and 2xxx
8312 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8317 RFRegTable = RF2850RegTable;
8319 switch (pAd->RfIcType)
8326 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8328 if (Channel == RFRegTable[index].Channel)
8330 R1 = RFRegTable[index].R1 & 0xffffdfff;
8331 R2 = RFRegTable[index].R2 & 0xfffbffff;
8332 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8334 RTMP_RF_IO_WRITE32(pAd, R1);
8335 RTMP_RF_IO_WRITE32(pAd, R2);
8337 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8338 // Set RF R2 bit18=0, R3 bit[18:19]=0
8339 //if (pAd->StaCfg.bRadio == FALSE)
8342 RTMP_RF_IO_WRITE32(pAd, R3);
8344 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8345 Channel, pAd->RfIcType, R2, R3));
8348 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8349 Channel, pAd->RfIcType, R2));
8365 VOID AsicTurnOnRFClk(
8366 IN PRTMP_ADAPTER pAd,
8370 UINT32 R1 = 0, R2 = 0, R3 = 0;
8372 RTMP_RF_REGS *RFRegTable;
8375 // The RF programming sequence is difference between 3xxx and 2xxx
8382 RFRegTable = RF2850RegTable;
8384 switch (pAd->RfIcType)
8391 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8393 if (Channel == RFRegTable[index].Channel)
8395 R3 = pAd->LatchRfRegs.R3;
8398 RTMP_RF_IO_WRITE32(pAd, R3);
8400 R1 = RFRegTable[index].R1;
8401 RTMP_RF_IO_WRITE32(pAd, R1);
8403 R2 = RFRegTable[index].R2;
8404 if (pAd->Antenna.field.TxPath == 1)
8406 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8409 if (pAd->Antenna.field.RxPath == 2)
8411 R2 |= 0x40; // write 1 to off Rxpath.
8413 else if (pAd->Antenna.field.RxPath == 1)
8415 R2 |= 0x20040; // write 1 to off RxPath
8417 RTMP_RF_IO_WRITE32(pAd, R2);