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 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
453 ==========================================================================
455 initialize the MLME task and its data structure (queue, spinlock,
456 timer, state machines).
461 always return NDIS_STATUS_SUCCESS
463 ==========================================================================
465 NDIS_STATUS MlmeInit(
466 IN PRTMP_ADAPTER pAd)
468 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
470 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
474 Status = MlmeQueueInit(&pAd->Mlme.Queue);
475 if(Status != NDIS_STATUS_SUCCESS)
478 pAd->Mlme.bRunning = FALSE;
479 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
482 BssTableInit(&pAd->ScanTab);
484 // init STA state machines
485 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
486 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
487 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
488 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
489 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
490 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
492 // Since we are using switch/case to implement it, the init is different from the above
493 // state machine init
494 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
497 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
499 // Init mlme periodic timer
500 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
502 // Set mlme periodic timer
503 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
505 // software-based RX Antenna diversity
506 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 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
645 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
647 // disable BEACON generation and other BEACON related hardware timers
648 AsicDisableSync(pAd);
652 // Cancel pending timers
653 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
654 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
655 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
656 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
657 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
658 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
661 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
662 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
666 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
669 RTMPSetLED(pAd, LED_HALT);
670 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
673 LED_CFG_STRUC LedCfg;
674 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
675 LedCfg.field.LedPolar = 0;
676 LedCfg.field.RLedMode = 0;
677 LedCfg.field.GLedMode = 0;
678 LedCfg.field.YLedMode = 0;
679 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
684 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
686 MlmeQueueDestroy(&pAd->Mlme.Queue);
687 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
689 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
692 VOID MlmeResetRalinkCounters(
693 IN PRTMP_ADAPTER pAd)
695 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
696 // clear all OneSecxxx counters.
697 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
698 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
699 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
700 pAd->RalinkCounters.OneSecRxOkCnt = 0;
701 pAd->RalinkCounters.OneSecTxFailCount = 0;
702 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
703 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
704 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
706 // TODO: for debug only. to be removed
707 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
708 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
709 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
710 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
711 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
712 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
713 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
714 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
715 pAd->RalinkCounters.OneSecTxDoneCount = 0;
716 pAd->RalinkCounters.OneSecRxCount = 0;
717 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
718 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
723 unsigned long rx_AMSDU;
724 unsigned long rx_Total;
727 ==========================================================================
729 This routine is executed periodically to -
730 1. Decide if it's a right time to turn on PwrMgmt bit of all
732 2. Calculate ChannelQuality based on statistics of the last
733 period, so that TX rate won't toggling very frequently between a
734 successful TX and a failed TX.
735 3. If the calculated ChannelQuality indicated current connection not
736 healthy, then a ROAMing attempt is tried here.
738 IRQL = DISPATCH_LEVEL
740 ==========================================================================
742 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
743 VOID MlmePeriodicExec(
744 IN PVOID SystemSpecific1,
745 IN PVOID FunctionContext,
746 IN PVOID SystemSpecific2,
747 IN PVOID SystemSpecific3)
750 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
752 // Do nothing if the driver is starting halt state.
753 // This might happen when timer already been fired before cancel timer with mlmehalt
754 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
755 fRTMP_ADAPTER_RADIO_OFF |
756 fRTMP_ADAPTER_RADIO_MEASUREMENT |
757 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
760 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
763 // Do nothing if monitor mode is on
767 if (pAd->Mlme.PeriodicRound & 0x1)
769 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
770 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
771 (STA_TGN_WIFI_ON(pAd)) &&
772 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
775 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
776 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
778 else if ((STA_TGN_WIFI_ON(pAd)) &&
779 ((pAd->MACVersion & 0xffff) == 0x0101))
781 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
782 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
787 pAd->bUpdateBcnCntDone = FALSE;
789 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
790 pAd->Mlme.PeriodicRound ++;
792 // execute every 500ms
793 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
795 // perform dynamic tx rate switching based on past TX history
797 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
799 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
800 MlmeDynamicTxRateSwitching(pAd);
804 // Normal 1 second Mlme PeriodicExec.
805 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
807 pAd->Mlme.OneSecPeriodicRound ++;
817 // Media status changed, report to NDIS
818 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
820 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
821 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
823 pAd->IndicateMediaState = NdisMediaStateConnected;
824 RTMP_IndicateMediaState(pAd);
829 pAd->IndicateMediaState = NdisMediaStateDisconnected;
830 RTMP_IndicateMediaState(pAd);
834 NdisGetSystemUpTime(&pAd->Mlme.Now32);
836 // add the most up-to-date h/w raw counters into software variable, so that
837 // the dynamic tuning mechanism below are based on most up-to-date information
838 NICUpdateRawCounters(pAd);
841 RT2870_WatchDog(pAd);
844 // Need statistics after read counter. So put after NICUpdateRawCounters
845 ORIBATimerTimeout(pAd);
848 // The time period for checking antenna is according to traffic
849 if (pAd->Mlme.bEnableAutoAntennaCheck)
851 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
852 pAd->RalinkCounters.OneSecTxRetryOkCount +
853 pAd->RalinkCounters.OneSecTxFailCount;
857 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
859 AsicEvaluateRxAnt(pAd);
864 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
866 AsicEvaluateRxAnt(pAd);
871 STAMlmePeriodicExec(pAd);
873 MlmeResetRalinkCounters(pAd);
877 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
878 // and sending CTS-to-self over and over.
879 // Software Patch Solution:
880 // 1. Polling debug state register 0x10F4 every one second.
881 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
882 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
886 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
887 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
889 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
891 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
893 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
898 RT28XX_MLME_HANDLER(pAd);
902 pAd->bUpdateBcnCntDone = FALSE;
905 VOID STAMlmePeriodicExec(
911 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
913 // WPA MIC error should block association attempt for 60 seconds
914 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
915 pAd->StaCfg.bBlockAssoc = FALSE;
918 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
920 if (pAd->IndicateMediaState == NdisMediaStateConnected)
922 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
924 pAd->PreMediaState = pAd->IndicateMediaState;
930 AsicStaBbpTuning(pAd);
932 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
933 pAd->RalinkCounters.OneSecTxRetryOkCount +
934 pAd->RalinkCounters.OneSecTxFailCount;
936 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
938 // update channel quality for Roaming and UI LinkQuality display
939 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
942 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
943 // Radio is currently in noisy environment
944 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
945 AsicAdjustTxPower(pAd);
949 // Is PSM bit consistent with user power management policy?
950 // This is the only place that will set PSM bit ON.
951 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
952 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
954 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
956 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
957 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
958 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
960 RTMPSetAGCInitValue(pAd, BW_20);
961 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
965 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
967 // When APSD is enabled, the period changes as 20 sec
968 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
969 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
973 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
974 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
976 if (pAd->CommonCfg.bWmmCapable)
977 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
979 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
984 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
986 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
987 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
988 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
990 // Lost AP, send disconnect & link down event
991 LinkDown(pAd, FALSE);
994 union iwreq_data wrqu;
995 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
996 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
999 MlmeAutoReconnectLastSSID(pAd);
1001 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1003 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1004 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1005 MlmeAutoReconnectLastSSID(pAd);
1008 // Add auto seamless roaming
1009 if (pAd->StaCfg.bFastRoaming)
1011 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1013 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));
1015 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1017 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1021 else if (ADHOC_ON(pAd))
1024 if ((pAd->CommonCfg.Channel > 14)
1025 && (pAd->CommonCfg.bIEEE80211H == 1)
1026 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1028 RadarDetectPeriodic(pAd);
1031 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1032 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1034 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1035 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1037 MLME_START_REQ_STRUCT StartReq;
1039 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1040 LinkDown(pAd, FALSE);
1042 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1043 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1044 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1047 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1049 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1051 if (pEntry->ValidAsCLI == FALSE)
1054 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1055 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1058 else // no INFRA nor ADHOC connection
1061 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1062 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1063 goto SKIP_AUTO_SCAN_CONN;
1065 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1067 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1068 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1069 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1071 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1073 MLME_SCAN_REQ_STRUCT ScanReq;
1075 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1077 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1078 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1079 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1080 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1081 // Reset Missed scan number
1082 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1084 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1085 MlmeAutoReconnectLastSSID(pAd);
1087 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1089 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1092 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1096 MlmeAutoReconnectLastSSID(pAd);
1102 SKIP_AUTO_SCAN_CONN:
1104 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1106 pAd->MacTab.fAnyBASession = TRUE;
1107 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1109 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1111 pAd->MacTab.fAnyBASession = FALSE;
1112 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1120 IN PVOID SystemSpecific1,
1121 IN PVOID FunctionContext,
1122 IN PVOID SystemSpecific2,
1123 IN PVOID SystemSpecific3)
1126 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1128 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1129 RTMP_IndicateMediaState(pAd);
1130 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1133 // IRQL = DISPATCH_LEVEL
1135 IN PRTMP_ADAPTER pAd)
1137 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1138 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1140 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1142 MLME_CNTL_STATE_MACHINE,
1143 OID_802_11_BSSID_LIST_SCAN,
1146 RT28XX_MLME_HANDLER(pAd);
1150 // IRQL = DISPATCH_LEVEL
1151 VOID MlmeAutoReconnectLastSSID(
1152 IN PRTMP_ADAPTER pAd)
1156 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1157 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1158 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1160 NDIS_802_11_SSID OidSsid;
1161 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1162 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1164 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1166 MLME_CNTL_STATE_MACHINE,
1168 sizeof(NDIS_802_11_SSID),
1170 RT28XX_MLME_HANDLER(pAd);
1175 ==========================================================================
1176 Validate SSID for connection try and rescan purpose
1177 Valid SSID will have visible chars only.
1178 The valid length is from 0 to 32.
1179 IRQL = DISPATCH_LEVEL
1180 ==========================================================================
1182 BOOLEAN MlmeValidateSSID(
1188 if (SsidLen > MAX_LEN_OF_SSID)
1191 // Check each character value
1192 for (index = 0; index < SsidLen; index++)
1194 if (pSsid[index] < 0x20)
1202 VOID MlmeSelectTxRateTable(
1203 IN PRTMP_ADAPTER pAd,
1204 IN PMAC_TABLE_ENTRY pEntry,
1206 IN PUCHAR pTableSize,
1207 IN PUCHAR pInitTxRateIdx)
1211 // decide the rate table for tuning
1212 if (pAd->CommonCfg.TxRateTableSize > 0)
1214 *ppTable = RateSwitchTable;
1215 *pTableSize = RateSwitchTable[0];
1216 *pInitTxRateIdx = RateSwitchTable[1];
1221 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1223 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1224 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1225 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1227 *ppTable = RateSwitchTable11N1S;
1228 *pTableSize = RateSwitchTable11N1S[0];
1229 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1232 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1233 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1234 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1235 (pAd->Antenna.field.TxPath == 2))
1237 if (pAd->LatchRfRegs.Channel <= 14)
1239 *ppTable = RateSwitchTable11N2S;
1240 *pTableSize = RateSwitchTable11N2S[0];
1241 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1245 *ppTable = RateSwitchTable11N2SForABand;
1246 *pTableSize = RateSwitchTable11N2SForABand[0];
1247 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1252 if ((pEntry->RateLen == 4)
1253 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1256 *ppTable = RateSwitchTable11B;
1257 *pTableSize = RateSwitchTable11B[0];
1258 *pInitTxRateIdx = RateSwitchTable11B[1];
1261 else if (pAd->LatchRfRegs.Channel <= 14)
1263 *ppTable = RateSwitchTable11BG;
1264 *pTableSize = RateSwitchTable11BG[0];
1265 *pInitTxRateIdx = RateSwitchTable11BG[1];
1270 *ppTable = RateSwitchTable11G;
1271 *pTableSize = RateSwitchTable11G[0];
1272 *pInitTxRateIdx = RateSwitchTable11G[1];
1278 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1279 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1281 *ppTable = RateSwitchTable11BGN1S;
1282 *pTableSize = RateSwitchTable11BGN1S[0];
1283 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1288 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1289 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1291 if (pAd->LatchRfRegs.Channel <= 14)
1293 *ppTable = RateSwitchTable11BGN2S;
1294 *pTableSize = RateSwitchTable11BGN2S[0];
1295 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1300 *ppTable = RateSwitchTable11BGN2SForABand;
1301 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1302 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1308 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1310 *ppTable = RateSwitchTable11N1S;
1311 *pTableSize = RateSwitchTable11N1S[0];
1312 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1317 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1319 if (pAd->LatchRfRegs.Channel <= 14)
1321 *ppTable = RateSwitchTable11N2S;
1322 *pTableSize = RateSwitchTable11N2S[0];
1323 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1327 *ppTable = RateSwitchTable11N2SForABand;
1328 *pTableSize = RateSwitchTable11N2SForABand[0];
1329 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1335 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1336 if ((pEntry->RateLen == 4)
1337 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1340 *ppTable = RateSwitchTable11B;
1341 *pTableSize = RateSwitchTable11B[0];
1342 *pInitTxRateIdx = RateSwitchTable11B[1];
1347 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1348 if ((pEntry->RateLen > 8)
1349 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1352 *ppTable = RateSwitchTable11BG;
1353 *pTableSize = RateSwitchTable11BG[0];
1354 *pInitTxRateIdx = RateSwitchTable11BG[1];
1359 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1360 if ((pEntry->RateLen == 8)
1361 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1364 *ppTable = RateSwitchTable11G;
1365 *pTableSize = RateSwitchTable11G[0];
1366 *pInitTxRateIdx = RateSwitchTable11G[1];
1372 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1373 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1375 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1377 *ppTable = RateSwitchTable11B;
1378 *pTableSize = RateSwitchTable11B[0];
1379 *pInitTxRateIdx = RateSwitchTable11B[1];
1381 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1383 *ppTable = RateSwitchTable11G;
1384 *pTableSize = RateSwitchTable11G[0];
1385 *pInitTxRateIdx = RateSwitchTable11G[1];
1390 *ppTable = RateSwitchTable11BG;
1391 *pTableSize = RateSwitchTable11BG[0];
1392 *pInitTxRateIdx = RateSwitchTable11BG[1];
1397 if (pAd->LatchRfRegs.Channel <= 14)
1399 if (pAd->CommonCfg.TxStream == 1)
1401 *ppTable = RateSwitchTable11N1S;
1402 *pTableSize = RateSwitchTable11N1S[0];
1403 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1404 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1408 *ppTable = RateSwitchTable11N2S;
1409 *pTableSize = RateSwitchTable11N2S[0];
1410 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1411 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1416 if (pAd->CommonCfg.TxStream == 1)
1418 *ppTable = RateSwitchTable11N1S;
1419 *pTableSize = RateSwitchTable11N1S[0];
1420 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1421 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1425 *ppTable = RateSwitchTable11N2SForABand;
1426 *pTableSize = RateSwitchTable11N2SForABand[0];
1427 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1428 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1432 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1433 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1439 ==========================================================================
1441 This routine checks if there're other APs out there capable for
1442 roaming. Caller should call this routine only when Link up in INFRA mode
1443 and channel quality is below CQI_GOOD_THRESHOLD.
1445 IRQL = DISPATCH_LEVEL
1448 ==========================================================================
1450 VOID MlmeCheckForRoaming(
1451 IN PRTMP_ADAPTER pAd,
1455 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1458 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1459 // put all roaming candidates into RoamTab, and sort in RSSI order
1460 BssTableInit(pRoamTab);
1461 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1463 pBss = &pAd->ScanTab.BssEntry[i];
1465 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1466 continue; // AP disappear
1467 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1468 continue; // RSSI too weak. forget it.
1469 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1470 continue; // skip current AP
1471 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1472 continue; // only AP with stronger RSSI is eligible for roaming
1474 // AP passing all above rules is put into roaming candidate table
1475 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1476 pRoamTab->BssNr += 1;
1479 if (pRoamTab->BssNr > 0)
1481 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1482 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1484 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1485 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1486 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1487 RT28XX_MLME_HANDLER(pAd);
1490 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1494 ==========================================================================
1496 This routine checks if there're other APs out there capable for
1497 roaming. Caller should call this routine only when link up in INFRA mode
1498 and channel quality is below CQI_GOOD_THRESHOLD.
1500 IRQL = DISPATCH_LEVEL
1503 ==========================================================================
1505 VOID MlmeCheckForFastRoaming(
1506 IN PRTMP_ADAPTER pAd,
1510 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1513 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1514 // put all roaming candidates into RoamTab, and sort in RSSI order
1515 BssTableInit(pRoamTab);
1516 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1518 pBss = &pAd->ScanTab.BssEntry[i];
1520 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1521 continue; // RSSI too weak. forget it.
1522 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1523 continue; // skip current AP
1524 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1525 continue; // skip different SSID
1526 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1527 continue; // skip AP without better RSSI
1529 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));
1530 // AP passing all above rules is put into roaming candidate table
1531 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1532 pRoamTab->BssNr += 1;
1535 if (pRoamTab->BssNr > 0)
1537 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1538 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1540 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1541 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1542 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1543 RT28XX_MLME_HANDLER(pAd);
1546 // Maybe site survey required
1549 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1551 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1552 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1553 pAd->StaCfg.ScanCnt = 2;
1554 pAd->StaCfg.LastScanTime = Now;
1559 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1563 ==========================================================================
1565 This routine calculates TxPER, RxPER of the past N-sec period. And
1566 according to the calculation result, ChannelQuality is calculated here
1567 to decide if current AP is still doing the job.
1569 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1571 StaCfg.ChannelQuality - 0..100
1573 IRQL = DISPATCH_LEVEL
1575 NOTE: This routine decide channle quality based on RX CRC error ratio.
1576 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1577 is performed right before this routine, so that this routine can decide
1578 channel quality based on the most up-to-date information
1579 ==========================================================================
1581 VOID MlmeCalculateChannelQuality(
1582 IN PRTMP_ADAPTER pAd,
1585 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1589 ULONG BeaconLostTime = BEACON_LOST_TIME;
1591 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1594 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1596 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1597 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1605 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1606 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1610 // calculate RX PER - don't take RxPER into consideration if too few sample
1612 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1616 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1619 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1621 if (INFRA_ON(pAd) &&
1622 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1623 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1625 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1626 pAd->Mlme.ChannelQuality = 0;
1633 else if (MaxRssi < -90)
1636 NorRssi = (MaxRssi + 90) * 2;
1638 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1639 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1640 TX_WEIGHTING * (100 - TxPRR) +
1641 RX_WEIGHTING* (100 - RxPER)) / 100;
1642 if (pAd->Mlme.ChannelQuality >= 100)
1643 pAd->Mlme.ChannelQuality = 100;
1649 IN PRTMP_ADAPTER pAd,
1650 IN PMAC_TABLE_ENTRY pEntry,
1651 IN PRTMP_TX_RATE_SWITCH pTxRate)
1653 UCHAR MaxMode = MODE_OFDM;
1655 MaxMode = MODE_HTGREENFIELD;
1657 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1658 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1660 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1662 if (pTxRate->CurrMCS < MCS_AUTO)
1663 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1665 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1666 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1670 // If peer adhoc is b-only mode, we can't send 11g rate.
1671 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1672 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1675 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1677 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1678 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1679 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1681 // Patch speed error in status page
1682 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1686 if (pTxRate->Mode <= MaxMode)
1687 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1689 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1690 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1692 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1694 // Reexam each bandwidth's SGI support.
1695 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1697 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1698 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1699 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1700 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1703 // Turn RTS/CTS rate to 6Mbps.
1704 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1706 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1707 if (pAd->MacTab.fAnyBASession)
1709 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1713 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1716 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1718 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1719 if (pAd->MacTab.fAnyBASession)
1721 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1725 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1728 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1730 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1733 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1735 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1738 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1739 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1740 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1741 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1743 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1744 pAd->WIFItestbed.bGreenField)
1745 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1748 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1752 ==========================================================================
1754 This routine calculates the acumulated TxPER of eaxh TxRate. And
1755 according to the calculation result, change CommonCfg.TxRate which
1756 is the stable TX Rate we expect the Radio situation could sustained.
1758 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1762 IRQL = DISPATCH_LEVEL
1765 call this routine every second
1766 ==========================================================================
1768 VOID MlmeDynamicTxRateSwitching(
1769 IN PRTMP_ADAPTER pAd)
1771 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1772 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1773 ULONG TxErrorRatio = 0;
1774 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1775 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1777 UCHAR TableSize = 0;
1778 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1779 CHAR Rssi, RssiOffset = 0;
1780 TX_STA_CNT1_STRUC StaTx1;
1781 TX_STA_CNT0_STRUC TxStaCnt0;
1782 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1783 MAC_TABLE_ENTRY *pEntry;
1786 // walk through MAC table, see if need to change AP's TX rate toward each entry
1788 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1790 pEntry = &pAd->MacTab.Content[i];
1792 // check if this entry need to switch rate automatically
1793 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1796 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1798 Rssi = RTMPMaxRssi(pAd,
1799 pAd->StaCfg.RssiSample.AvgRssi0,
1800 pAd->StaCfg.RssiSample.AvgRssi1,
1801 pAd->StaCfg.RssiSample.AvgRssi2);
1803 // Update statistic counter
1804 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1805 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1806 pAd->bUpdateBcnCntDone = TRUE;
1807 TxRetransmit = StaTx1.field.TxRetransmit;
1808 TxSuccess = StaTx1.field.TxSuccess;
1809 TxFailCount = TxStaCnt0.field.TxFailCount;
1810 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1812 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1813 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1814 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1815 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1816 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1817 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1819 // if no traffic in the past 1-sec period, don't change TX rate,
1820 // but clear all bad history. because the bad history may affect the next
1821 // Chariot throughput test
1822 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1823 pAd->RalinkCounters.OneSecTxRetryOkCount +
1824 pAd->RalinkCounters.OneSecTxFailCount;
1827 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1831 if (INFRA_ON(pAd) && (i == 1))
1832 Rssi = RTMPMaxRssi(pAd,
1833 pAd->StaCfg.RssiSample.AvgRssi0,
1834 pAd->StaCfg.RssiSample.AvgRssi1,
1835 pAd->StaCfg.RssiSample.AvgRssi2);
1837 Rssi = RTMPMaxRssi(pAd,
1838 pEntry->RssiSample.AvgRssi0,
1839 pEntry->RssiSample.AvgRssi1,
1840 pEntry->RssiSample.AvgRssi2);
1842 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1843 pEntry->OneSecTxRetryOkCount +
1844 pEntry->OneSecTxFailCount;
1847 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1850 CurrRateIdx = pEntry->CurrTxRateIndex;
1852 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1854 if (CurrRateIdx >= TableSize)
1856 CurrRateIdx = TableSize - 1;
1859 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1860 // So need to sync here.
1861 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1862 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1863 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1867 // Need to sync Real Tx rate and our record.
1868 // Then return for next DRS.
1869 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1870 pEntry->CurrTxRateIndex = InitTxRateIdx;
1871 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1873 // reset all OneSecTx counters
1874 RESET_ONE_SEC_TX_CNT(pEntry);
1878 // decide the next upgrade rate and downgrade rate, if any
1879 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
1881 UpRateIdx = CurrRateIdx + 1;
1882 DownRateIdx = CurrRateIdx -1;
1884 else if (CurrRateIdx == 0)
1886 UpRateIdx = CurrRateIdx + 1;
1887 DownRateIdx = CurrRateIdx;
1889 else if (CurrRateIdx == (TableSize - 1))
1891 UpRateIdx = CurrRateIdx;
1892 DownRateIdx = CurrRateIdx - 1;
1895 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1897 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
1899 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
1900 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
1904 TrainUp = pCurrTxRate->TrainUp;
1905 TrainDown = pCurrTxRate->TrainDown;
1908 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
1911 // Keep the last time TxRateChangeAction status.
1913 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
1918 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
1919 // (criteria copied from RT2500 for Netopia case)
1921 if (TxTotalCnt <= 15)
1925 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1926 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
1927 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
1928 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
1930 // check the existence and index of each needed MCS
1931 while (idx < pTable[0])
1933 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
1935 if (pCurrTxRate->CurrMCS == MCS_0)
1939 else if (pCurrTxRate->CurrMCS == MCS_1)
1943 else if (pCurrTxRate->CurrMCS == MCS_2)
1947 else if (pCurrTxRate->CurrMCS == MCS_3)
1951 else if (pCurrTxRate->CurrMCS == MCS_4)
1955 else if (pCurrTxRate->CurrMCS == MCS_5)
1959 else if (pCurrTxRate->CurrMCS == MCS_6)
1963 //else if (pCurrTxRate->CurrMCS == MCS_7)
1964 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
1968 else if (pCurrTxRate->CurrMCS == MCS_12)
1972 else if (pCurrTxRate->CurrMCS == MCS_13)
1976 else if (pCurrTxRate->CurrMCS == MCS_14)
1980 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
1984 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
1988 else if (pCurrTxRate->CurrMCS == MCS_21)
1992 else if (pCurrTxRate->CurrMCS == MCS_22)
1996 else if (pCurrTxRate->CurrMCS == MCS_23)
2003 if (pAd->LatchRfRegs.Channel <= 14)
2005 if (pAd->NicConfig2.field.ExternalLNAForG)
2016 if (pAd->NicConfig2.field.ExternalLNAForA)
2027 if ((pTable == RateSwitchTable11BGN3S) ||
2028 (pTable == RateSwitchTable11N3S) ||
2029 (pTable == RateSwitchTable))
2030 {// N mode with 3 stream // 3*3
2031 if (MCS23 && (Rssi >= -70))
2033 else if (MCS22 && (Rssi >= -72))
2035 else if (MCS21 && (Rssi >= -76))
2037 else if (MCS20 && (Rssi >= -78))
2039 else if (MCS4 && (Rssi >= -82))
2041 else if (MCS3 && (Rssi >= -84))
2043 else if (MCS2 && (Rssi >= -86))
2045 else if (MCS1 && (Rssi >= -88))
2050 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2051 {// N mode with 2 stream
2052 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2054 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2056 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2058 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2060 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2062 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2064 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2066 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2071 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2072 {// N mode with 1 stream
2073 if (MCS7 && (Rssi > (-72+RssiOffset)))
2075 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2077 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2079 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2081 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2083 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2085 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2092 if (MCS7 && (Rssi > -70))
2094 else if (MCS6 && (Rssi > -74))
2096 else if (MCS5 && (Rssi > -78))
2098 else if (MCS4 && (Rssi > -82))
2100 else if (MCS4 == 0) // for B-only mode
2102 else if (MCS3 && (Rssi > -85))
2104 else if (MCS2 && (Rssi > -87))
2106 else if (MCS1 && (Rssi > -90))
2113 pEntry->CurrTxRateIndex = TxRateIdx;
2114 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2115 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2118 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2119 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2120 pEntry->fLastSecAccordingRSSI = TRUE;
2121 // reset all OneSecTx counters
2122 RESET_ONE_SEC_TX_CNT(pEntry);
2127 if (pEntry->fLastSecAccordingRSSI == TRUE)
2129 pEntry->fLastSecAccordingRSSI = FALSE;
2130 pEntry->LastSecTxRateChangeAction = 0;
2131 // reset all OneSecTx counters
2132 RESET_ONE_SEC_TX_CNT(pEntry);
2139 BOOLEAN bTrainUpDown = FALSE;
2141 pEntry->CurrTxRateStableTime ++;
2143 // downgrade TX quality if PER >= Rate-Down threshold
2144 if (TxErrorRatio >= TrainDown)
2146 bTrainUpDown = TRUE;
2147 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2149 // upgrade TX quality if PER <= Rate-Up threshold
2150 else if (TxErrorRatio <= TrainUp)
2152 bTrainUpDown = TRUE;
2153 bUpgradeQuality = TRUE;
2154 if (pEntry->TxQuality[CurrRateIdx])
2155 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2157 if (pEntry->TxRateUpPenalty)
2158 pEntry->TxRateUpPenalty --;
2159 else if (pEntry->TxQuality[UpRateIdx])
2160 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2163 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2167 // perform DRS - consider TxRate Down first, then rate up.
2168 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2170 pEntry->CurrTxRateIndex = DownRateIdx;
2172 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2174 pEntry->CurrTxRateIndex = UpRateIdx;
2179 // if rate-up happen, clear all bad history of all TX rates
2180 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2182 pEntry->CurrTxRateStableTime = 0;
2183 pEntry->TxRateUpPenalty = 0;
2184 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2185 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2186 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2189 // For TxRate fast train up
2191 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2193 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2195 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2197 bTxRateChanged = TRUE;
2199 // if rate-down happen, only clear DownRate's bad history
2200 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2202 pEntry->CurrTxRateStableTime = 0;
2203 pEntry->TxRateUpPenalty = 0; // no penalty
2204 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2205 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2206 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2209 // For TxRate fast train down
2211 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2213 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2215 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2217 bTxRateChanged = TRUE;
2221 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2222 bTxRateChanged = FALSE;
2225 pEntry->LastTxOkCount = TxSuccess;
2227 // reset all OneSecTx counters
2228 RESET_ONE_SEC_TX_CNT(pEntry);
2230 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2231 if (bTxRateChanged && pNextTxRate)
2233 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2239 ========================================================================
2240 Routine Description:
2241 Station side, Auto TxRate faster train up timer call back function.
2244 SystemSpecific1 - Not used.
2245 FunctionContext - Pointer to our Adapter context.
2246 SystemSpecific2 - Not used.
2247 SystemSpecific3 - Not used.
2252 ========================================================================
2254 VOID StaQuickResponeForRateUpExec(
2255 IN PVOID SystemSpecific1,
2256 IN PVOID FunctionContext,
2257 IN PVOID SystemSpecific2,
2258 IN PVOID SystemSpecific3)
2260 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2261 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2263 ULONG TxErrorRatio = 0;
2264 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2265 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2267 UCHAR TableSize = 0;
2268 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2269 TX_STA_CNT1_STRUC StaTx1;
2270 TX_STA_CNT0_STRUC TxStaCnt0;
2272 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2273 MAC_TABLE_ENTRY *pEntry;
2276 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2279 // walk through MAC table, see if need to change AP's TX rate toward each entry
2281 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2283 pEntry = &pAd->MacTab.Content[i];
2285 // check if this entry need to switch rate automatically
2286 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2289 if (INFRA_ON(pAd) && (i == 1))
2290 Rssi = RTMPMaxRssi(pAd,
2291 pAd->StaCfg.RssiSample.AvgRssi0,
2292 pAd->StaCfg.RssiSample.AvgRssi1,
2293 pAd->StaCfg.RssiSample.AvgRssi2);
2295 Rssi = RTMPMaxRssi(pAd,
2296 pEntry->RssiSample.AvgRssi0,
2297 pEntry->RssiSample.AvgRssi1,
2298 pEntry->RssiSample.AvgRssi2);
2300 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2302 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2304 // decide the next upgrade rate and downgrade rate, if any
2305 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2307 UpRateIdx = CurrRateIdx + 1;
2308 DownRateIdx = CurrRateIdx -1;
2310 else if (CurrRateIdx == 0)
2312 UpRateIdx = CurrRateIdx + 1;
2313 DownRateIdx = CurrRateIdx;
2315 else if (CurrRateIdx == (TableSize - 1))
2317 UpRateIdx = CurrRateIdx;
2318 DownRateIdx = CurrRateIdx - 1;
2321 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2323 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2325 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2326 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2330 TrainUp = pCurrTxRate->TrainUp;
2331 TrainDown = pCurrTxRate->TrainDown;
2334 if (pAd->MacTab.Size == 1)
2336 // Update statistic counter
2337 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2338 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2340 TxRetransmit = StaTx1.field.TxRetransmit;
2341 TxSuccess = StaTx1.field.TxSuccess;
2342 TxFailCount = TxStaCnt0.field.TxFailCount;
2343 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2345 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2346 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2347 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2348 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2349 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2350 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2353 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2357 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2358 pEntry->OneSecTxRetryOkCount +
2359 pEntry->OneSecTxFailCount;
2362 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2367 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2368 // (criteria copied from RT2500 for Netopia case)
2370 if (TxTotalCnt <= 12)
2372 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2373 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2375 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2377 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2378 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2380 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2382 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2385 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2391 ULONG OneSecTxNoRetryOKRationCount;
2393 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2398 // downgrade TX quality if PER >= Rate-Down threshold
2399 if (TxErrorRatio >= TrainDown)
2401 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2404 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2406 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2408 // perform DRS - consider TxRate Down first, then rate up.
2409 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2411 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2413 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2414 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2419 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2421 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2425 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2427 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2432 // if rate-up happen, clear all bad history of all TX rates
2433 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2435 pAd->DrsCounters.TxRateUpPenalty = 0;
2436 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2437 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2438 bTxRateChanged = TRUE;
2440 // if rate-down happen, only clear DownRate's bad history
2441 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2443 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2445 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2446 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2447 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2448 bTxRateChanged = TRUE;
2452 bTxRateChanged = FALSE;
2455 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2456 if (bTxRateChanged && pNextTxRate)
2458 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2464 ==========================================================================
2466 This routine is executed periodically inside MlmePeriodicExec() after
2467 association with an AP.
2468 It checks if StaCfg.Psm is consistent with user policy (recorded in
2469 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2470 there're some conditions to consider:
2471 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2472 the time when Mibss==TRUE
2473 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2474 if outgoing traffic available in TxRing or MgmtRing.
2476 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2478 IRQL = DISPATCH_LEVEL
2480 ==========================================================================
2482 VOID MlmeCheckPsmChange(
2483 IN PRTMP_ADAPTER pAd,
2489 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2490 // 2. user wants either MAX_PSP or FAST_PSP
2491 // 3. but current psm is not in PWR_SAVE
2492 // 4. CNTL state machine is not doing SCANning
2493 // 5. no TX SUCCESS event for the past 1-sec period
2494 #ifdef NDIS51_MINIPORT
2495 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2496 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2499 PowerMode = pAd->StaCfg.WindowsPowerMode;
2501 if (INFRA_ON(pAd) &&
2502 (PowerMode != Ndis802_11PowerModeCAM) &&
2503 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2504 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2506 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2507 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2508 MlmeSetPsmBit(pAd, PWR_SAVE);
2509 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2511 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2515 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2520 // IRQL = PASSIVE_LEVEL
2521 // IRQL = DISPATCH_LEVEL
2523 IN PRTMP_ADAPTER pAd,
2526 AUTO_RSP_CFG_STRUC csr4;
2528 pAd->StaCfg.Psm = psm;
2529 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2530 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2531 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2532 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2535 // IRQL = DISPATCH_LEVEL
2536 VOID MlmeSetTxPreamble(
2537 IN PRTMP_ADAPTER pAd,
2538 IN USHORT TxPreamble)
2540 AUTO_RSP_CFG_STRUC csr4;
2543 // Always use Long preamble before verifiation short preamble functionality works well.
2544 // Todo: remove the following line if short preamble functionality works
2546 //TxPreamble = Rt802_11PreambleLong;
2548 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2549 if (TxPreamble == Rt802_11PreambleLong)
2551 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2552 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2553 csr4.field.AutoResponderPreamble = 0;
2557 // NOTE: 1Mbps should always use long preamble
2558 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2559 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2560 csr4.field.AutoResponderPreamble = 1;
2563 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2567 ==========================================================================
2569 Update basic rate bitmap
2570 ==========================================================================
2573 VOID UpdateBasicRateBitmap(
2574 IN PRTMP_ADAPTER pAdapter)
2577 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2578 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2579 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2580 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2581 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2584 /* if A mode, always use fix BasicRateBitMap */
2585 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2586 if (pAdapter->CommonCfg.Channel > 14)
2587 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2590 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2592 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2596 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2602 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2604 if (bitmap & (1 << i))
2606 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2608 if (sup_p[j] == rate[i])
2613 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2615 if (ext_p[j] == rate[i])
2621 } /* End of UpdateBasicRateBitmap */
2623 // IRQL = PASSIVE_LEVEL
2624 // IRQL = DISPATCH_LEVEL
2625 // bLinkUp is to identify the inital link speed.
2626 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2627 VOID MlmeUpdateTxRates(
2628 IN PRTMP_ADAPTER pAd,
2633 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2634 UCHAR MinSupport = RATE_54;
2635 ULONG BasicRateBitmap = 0;
2636 UCHAR CurrBasicRate = RATE_1;
2637 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2638 PHTTRANSMIT_SETTING pHtPhy = NULL;
2639 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2640 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2641 BOOLEAN *auto_rate_cur_p;
2642 UCHAR HtMcs = MCS_AUTO;
2644 // find max desired rate
2645 UpdateBasicRateBitmap(pAd);
2648 auto_rate_cur_p = NULL;
2649 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2651 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2653 case 2: Rate = RATE_1; num++; break;
2654 case 4: Rate = RATE_2; num++; break;
2655 case 11: Rate = RATE_5_5; num++; break;
2656 case 22: Rate = RATE_11; num++; break;
2657 case 12: Rate = RATE_6; num++; break;
2658 case 18: Rate = RATE_9; num++; break;
2659 case 24: Rate = RATE_12; num++; break;
2660 case 36: Rate = RATE_18; num++; break;
2661 case 48: Rate = RATE_24; num++; break;
2662 case 72: Rate = RATE_36; num++; break;
2663 case 96: Rate = RATE_48; num++; break;
2664 case 108: Rate = RATE_54; num++; break;
2665 //default: Rate = RATE_1; break;
2667 if (MaxDesire < Rate) MaxDesire = Rate;
2670 //===========================================================================
2671 //===========================================================================
2673 pHtPhy = &pAd->StaCfg.HTPhyMode;
2674 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2675 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2677 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2678 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2680 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2681 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2682 (MaxDesire > RATE_11))
2684 MaxDesire = RATE_11;
2688 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2689 pMinHtPhy->word = 0;
2690 pMaxHtPhy->word = 0;
2693 // Auto rate switching is enabled only if more than one DESIRED RATES are
2694 // specified; otherwise disabled
2697 *auto_rate_cur_p = FALSE;
2701 *auto_rate_cur_p = TRUE;
2705 if (HtMcs != MCS_AUTO)
2707 *auto_rate_cur_p = FALSE;
2711 *auto_rate_cur_p = TRUE;
2715 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2717 pSupRate = &pAd->StaActive.SupRate[0];
2718 pExtRate = &pAd->StaActive.ExtRate[0];
2719 SupRateLen = pAd->StaActive.SupRateLen;
2720 ExtRateLen = pAd->StaActive.ExtRateLen;
2724 pSupRate = &pAd->CommonCfg.SupRate[0];
2725 pExtRate = &pAd->CommonCfg.ExtRate[0];
2726 SupRateLen = pAd->CommonCfg.SupRateLen;
2727 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2730 // find max supported rate
2731 for (i=0; i<SupRateLen; i++)
2733 switch (pSupRate[i] & 0x7f)
2735 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2736 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2737 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2738 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2739 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2740 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2741 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2742 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2743 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2744 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2745 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2746 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2747 default: Rate = RATE_1; break;
2749 if (MaxSupport < Rate) MaxSupport = Rate;
2751 if (MinSupport > Rate) MinSupport = Rate;
2754 for (i=0; i<ExtRateLen; i++)
2756 switch (pExtRate[i] & 0x7f)
2758 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2759 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2760 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2761 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2762 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2763 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2764 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2765 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2766 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2767 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2768 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2769 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2770 default: Rate = RATE_1; break;
2772 if (MaxSupport < Rate) MaxSupport = Rate;
2774 if (MinSupport > Rate) MinSupport = Rate;
2777 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2779 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2780 // the DURATION field of outgoing uniicast DATA/MGMT frame
2781 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2783 if (BasicRateBitmap & (0x01 << i))
2784 CurrBasicRate = (UCHAR)i;
2785 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2788 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2789 // max tx rate = min {max desire rate, max supported rate}
2790 if (MaxSupport < MaxDesire)
2791 pAd->CommonCfg.MaxTxRate = MaxSupport;
2793 pAd->CommonCfg.MaxTxRate = MaxDesire;
2795 pAd->CommonCfg.MinTxRate = MinSupport;
2796 if (*auto_rate_cur_p)
2800 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2802 if (bLinkUp == TRUE)
2803 pAd->CommonCfg.TxRate = RATE_24;
2805 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2808 pAd->CommonCfg.TxRate = RATE_11;
2810 pAd->CommonCfg.TxRate = RATE_24;
2812 // should never exceed MaxTxRate (consider 11B-only mode)
2813 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2814 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2816 pAd->CommonCfg.TxRateIndex = 0;
2820 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2821 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2822 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2824 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2825 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2826 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2827 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
2830 if (pAd->CommonCfg.TxRate <= RATE_11)
2832 pMaxHtPhy->field.MODE = MODE_CCK;
2833 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
2834 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
2838 pMaxHtPhy->field.MODE = MODE_OFDM;
2839 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
2840 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
2841 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
2843 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
2846 pHtPhy->word = (pMaxHtPhy->word);
2847 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
2849 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
2850 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
2851 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
2855 switch (pAd->CommonCfg.PhyMode)
2857 case PHY_11BG_MIXED:
2859 case PHY_11BGN_MIXED:
2860 pAd->CommonCfg.MlmeRate = RATE_1;
2861 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2862 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2864 pAd->CommonCfg.RtsRate = RATE_11;
2868 case PHY_11AGN_MIXED:
2869 case PHY_11GN_MIXED:
2871 case PHY_11AN_MIXED:
2873 pAd->CommonCfg.MlmeRate = RATE_6;
2874 pAd->CommonCfg.RtsRate = RATE_6;
2875 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2876 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2878 case PHY_11ABG_MIXED:
2879 case PHY_11ABGN_MIXED:
2880 if (pAd->CommonCfg.Channel <= 14)
2882 pAd->CommonCfg.MlmeRate = RATE_1;
2883 pAd->CommonCfg.RtsRate = RATE_1;
2884 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2885 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2889 pAd->CommonCfg.MlmeRate = RATE_6;
2890 pAd->CommonCfg.RtsRate = RATE_6;
2891 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2892 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2896 pAd->CommonCfg.MlmeRate = RATE_6;
2897 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2898 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2899 pAd->CommonCfg.RtsRate = RATE_1;
2903 // Keep Basic Mlme Rate.
2905 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
2906 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
2907 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
2909 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
2910 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
2913 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
2914 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
2915 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
2916 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
2917 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
2918 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
2919 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 ));
2923 ==========================================================================
2925 This function update HT Rate setting.
2926 Input Wcid value is valid for 2 case :
2927 1. it's used for Station in infra mode that copy AP rate to Mactable.
2928 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
2930 IRQL = DISPATCH_LEVEL
2932 ==========================================================================
2934 VOID MlmeUpdateHtTxRates(
2935 IN PRTMP_ADAPTER pAd,
2938 UCHAR StbcMcs; //j, StbcMcs, bitmask;
2940 RT_HT_CAPABILITY *pRtHtCap = NULL;
2941 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
2944 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
2945 PHTTRANSMIT_SETTING pHtPhy = NULL;
2946 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2947 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2948 BOOLEAN *auto_rate_cur_p;
2950 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
2952 auto_rate_cur_p = NULL;
2955 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
2956 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
2957 pHtPhy = &pAd->StaCfg.HTPhyMode;
2958 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2959 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2961 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2964 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2966 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
2969 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
2970 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
2971 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
2972 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
2973 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
2974 pMaxHtPhy->field.STBC = STBC_USE;
2976 pMaxHtPhy->field.STBC = STBC_NONE;
2980 if (pDesireHtPhy->bHtEnable == FALSE)
2983 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
2984 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
2985 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
2986 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
2987 pMaxHtPhy->field.STBC = STBC_USE;
2989 pMaxHtPhy->field.STBC = STBC_NONE;
2992 // Decide MAX ht rate.
2993 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
2994 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
2996 pMaxHtPhy->field.MODE = MODE_HTMIX;
2998 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
2999 pMaxHtPhy->field.BW = BW_40;
3001 pMaxHtPhy->field.BW = BW_20;
3003 if (pMaxHtPhy->field.BW == BW_20)
3004 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3006 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3008 for (i=23; i>=0; i--) // 3*3
3011 bitmask = (1<<(i-(j*8)));
3013 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3015 pMaxHtPhy->field.MCS = i;
3023 // Copy MIN ht rate. rt2860???
3024 pMinHtPhy->field.BW = BW_20;
3025 pMinHtPhy->field.MCS = 0;
3026 pMinHtPhy->field.STBC = 0;
3027 pMinHtPhy->field.ShortGI = 0;
3028 //If STA assigns fixed rate. update to fixed here.
3029 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3031 if (pDesireHtPhy->MCSSet[4] != 0)
3033 pMaxHtPhy->field.MCS = 32;
3034 pMinHtPhy->field.MCS = 32;
3035 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3038 for (i=23; (CHAR)i >= 0; i--) // 3*3
3041 bitmask = (1<<(i-(j*8)));
3042 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3044 pMaxHtPhy->field.MCS = i;
3045 pMinHtPhy->field.MCS = i;
3054 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3055 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3056 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3057 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3058 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3060 // use default now. rt2860
3061 if (pDesireHtPhy->MCSSet[0] != 0xff)
3062 *auto_rate_cur_p = FALSE;
3064 *auto_rate_cur_p = TRUE;
3066 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3067 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3068 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3069 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3072 // IRQL = DISPATCH_LEVEL
3074 IN PRTMP_ADAPTER pAd)
3076 RT28XX_MLME_RADIO_OFF(pAd);
3079 // IRQL = DISPATCH_LEVEL
3081 IN PRTMP_ADAPTER pAd)
3083 RT28XX_MLME_RADIO_ON(pAd);
3086 // ===========================================================================================
3088 // ===========================================================================================
3091 /*! \brief initialize BSS table
3092 * \param p_tab pointer to the table
3097 IRQL = PASSIVE_LEVEL
3098 IRQL = DISPATCH_LEVEL
3107 Tab->BssOverlapNr = 0;
3108 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3110 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3111 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3116 IN PRTMP_ADAPTER pAd,
3121 Tab->numAsOriginator = 0;
3122 Tab->numAsRecipient = 0;
3123 NdisAllocateSpinLock(&pAd->BATabLock);
3124 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3126 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3127 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3129 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3131 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3135 /*! \brief search the BSS table by SSID
3136 * \param p_tab pointer to the bss table
3137 * \param ssid SSID string
3138 * \return index of the table, BSS_NOT_FOUND if not in the table
3141 * \note search by sequential search
3143 IRQL = DISPATCH_LEVEL
3146 ULONG BssTableSearch(
3153 for (i = 0; i < Tab->BssNr; i++)
3156 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3157 // We should distinguish this case.
3159 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3160 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3161 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3166 return (ULONG)BSS_NOT_FOUND;
3169 ULONG BssSsidTableSearch(
3178 for (i = 0; i < Tab->BssNr; i++)
3181 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3182 // We should distinguish this case.
3184 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3185 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3186 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3187 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3192 return (ULONG)BSS_NOT_FOUND;
3195 ULONG BssTableSearchWithSSID(
3204 for (i = 0; i < Tab->BssNr; i++)
3206 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3207 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3208 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3209 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3210 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3211 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3216 return (ULONG)BSS_NOT_FOUND;
3219 // IRQL = DISPATCH_LEVEL
3220 VOID BssTableDeleteEntry(
3221 IN OUT BSS_TABLE *Tab,
3227 for (i = 0; i < Tab->BssNr; i++)
3229 if ((Tab->BssEntry[i].Channel == Channel) &&
3230 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3232 for (j = i; j < Tab->BssNr - 1; j++)
3234 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3236 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3244 ========================================================================
3245 Routine Description:
3246 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3249 // IRQL = DISPATCH_LEVEL
3250 ========================================================================
3252 VOID BATableDeleteORIEntry(
3253 IN OUT PRTMP_ADAPTER pAd,
3254 IN BA_ORI_ENTRY *pBAORIEntry)
3257 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3259 NdisAcquireSpinLock(&pAd->BATabLock);
3260 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3262 pAd->BATable.numAsOriginator -= 1;
3263 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3264 // Erase Bitmap flag.
3266 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3267 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3268 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3269 pBAORIEntry->Token = 1;
3270 // Not clear Sequence here.
3271 NdisReleaseSpinLock(&pAd->BATabLock);
3281 IRQL = DISPATCH_LEVEL
3285 IN PRTMP_ADAPTER pAd,
3286 OUT BSS_ENTRY *pBss,
3291 IN USHORT BeaconPeriod,
3292 IN PCF_PARM pCfParm,
3294 IN USHORT CapabilityInfo,
3296 IN UCHAR SupRateLen,
3298 IN UCHAR ExtRateLen,
3299 IN HT_CAPABILITY_IE *pHtCapability,
3300 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3301 IN UCHAR HtCapabilityLen,
3302 IN UCHAR AddHtInfoLen,
3303 IN UCHAR NewExtChanOffset,
3306 IN LARGE_INTEGER TimeStamp,
3308 IN PEDCA_PARM pEdcaParm,
3309 IN PQOS_CAPABILITY_PARM pQosCapability,
3310 IN PQBSS_LOAD_PARM pQbssLoad,
3311 IN USHORT LengthVIE,
3312 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3314 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3315 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3319 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3320 // Or send beacon /probe response with SSID len matching real SSID length,
3321 // but SSID is all zero. such as "00-00-00-00" with length 4.
3322 // We have to prevent this case overwrite correct table
3323 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3325 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3326 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3327 pBss->SsidLen = SsidLen;
3333 pBss->BssType = BssType;
3334 pBss->BeaconPeriod = BeaconPeriod;
3335 if (BssType == BSS_INFRA)
3337 if (pCfParm->bValid)
3339 pBss->CfpCount = pCfParm->CfpCount;
3340 pBss->CfpPeriod = pCfParm->CfpPeriod;
3341 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3342 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3347 pBss->AtimWin = AtimWin;
3350 pBss->CapabilityInfo = CapabilityInfo;
3351 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3352 // Combine with AuthMode, they will decide the connection methods.
3353 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3354 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3355 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3356 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3358 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3359 pBss->SupRateLen = SupRateLen;
3360 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3361 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3362 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3363 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3364 pBss->NewExtChanOffset = NewExtChanOffset;
3365 pBss->ExtRateLen = ExtRateLen;
3366 pBss->Channel = Channel;
3367 pBss->CentralChannel = Channel;
3369 // Update CkipFlag. if not exists, the value is 0x0
3370 pBss->CkipFlag = CkipFlag;
3372 // New for microsoft Fixed IEs
3373 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3374 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3375 pBss->FixIEs.Capabilities = CapabilityInfo;
3377 // New for microsoft Variable IEs
3380 pBss->VarIELen = LengthVIE;
3381 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3388 pBss->AddHtInfoLen = 0;
3389 pBss->HtCapabilityLen = 0;
3391 if (HtCapabilityLen> 0)
3393 pBss->HtCapabilityLen = HtCapabilityLen;
3394 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3395 if (AddHtInfoLen > 0)
3397 pBss->AddHtInfoLen = AddHtInfoLen;
3398 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3400 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3402 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3404 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3406 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3411 BssCipherParse(pBss);
3415 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3417 pBss->EdcaParm.bValid = FALSE;
3419 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3421 pBss->QosCapability.bValid = FALSE;
3423 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3425 pBss->QbssLoad.bValid = FALSE;
3432 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3433 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3435 pEid = (PEID_STRUCT) pVIE;
3437 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3442 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3444 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3446 pBss->WpaIE.IELen = 0;
3449 pBss->WpaIE.IELen = pEid->Len + 2;
3450 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3454 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3456 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3458 pBss->RsnIE.IELen = 0;
3461 pBss->RsnIE.IELen = pEid->Len + 2;
3462 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3466 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3467 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3473 * \brief insert an entry into the bss table
3474 * \param p_tab The BSS table
3475 * \param Bssid BSSID
3477 * \param ssid_len Length of SSID
3479 * \param beacon_period
3486 * \param channel_idx
3490 * \note If SSID is identical, the old entry will be replaced by the new one
3492 IRQL = DISPATCH_LEVEL
3495 ULONG BssTableSetEntry(
3496 IN PRTMP_ADAPTER pAd,
3502 IN USHORT BeaconPeriod,
3505 IN USHORT CapabilityInfo,
3507 IN UCHAR SupRateLen,
3509 IN UCHAR ExtRateLen,
3510 IN HT_CAPABILITY_IE *pHtCapability,
3511 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3512 IN UCHAR HtCapabilityLen,
3513 IN UCHAR AddHtInfoLen,
3514 IN UCHAR NewExtChanOffset,
3517 IN LARGE_INTEGER TimeStamp,
3519 IN PEDCA_PARM pEdcaParm,
3520 IN PQOS_CAPABILITY_PARM pQosCapability,
3521 IN PQBSS_LOAD_PARM pQbssLoad,
3522 IN USHORT LengthVIE,
3523 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3527 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3528 if (Idx == BSS_NOT_FOUND)
3530 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3533 // It may happen when BSS Table was full.
3534 // The desired AP will not be added into BSS Table
3535 // In this case, if we found the desired AP then overwrite BSS Table.
3537 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3539 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3540 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3542 Idx = Tab->BssOverlapNr;
3543 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3544 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3545 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3546 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3552 return BSS_NOT_FOUND;
3556 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3557 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3558 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3563 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3564 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3565 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3571 // IRQL = DISPATCH_LEVEL
3572 VOID BssTableSsidSort(
3573 IN PRTMP_ADAPTER pAd,
3574 OUT BSS_TABLE *OutTab,
3579 BssTableInit(OutTab);
3581 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3583 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3584 BOOLEAN bIsHiddenApIncluded = FALSE;
3586 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3587 (pAd->MlmeAux.Channel > 14) &&
3588 RadarChannelCheck(pAd, pInBss->Channel))
3592 bIsHiddenApIncluded = TRUE;
3595 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3596 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3598 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3600 // 2.4G/5G N only mode
3601 if ((pInBss->HtCapabilityLen == 0) &&
3602 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3604 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3609 // Check the Authmode first
3610 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3612 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3613 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3617 // Check cipher suite, AP must have more secured cipher than station setting
3618 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3620 // If it's not mixed mode, we should only let BSS pass with the same encryption
3621 if (pInBss->WPA.bMixMode == FALSE)
3622 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3625 // check group cipher
3626 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3627 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3628 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3631 // check pairwise cipher, skip if none matched
3632 // If profile set to AES, let it pass without question.
3633 // If profile set to TKIP, we must find one mateched
3634 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3635 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3636 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3639 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3641 // If it's not mixed mode, we should only let BSS pass with the same encryption
3642 if (pInBss->WPA2.bMixMode == FALSE)
3643 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3646 // check group cipher
3647 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3648 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3649 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3652 // check pairwise cipher, skip if none matched
3653 // If profile set to AES, let it pass without question.
3654 // If profile set to TKIP, we must find one mateched
3655 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3656 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3657 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3661 // Bss Type matched, SSID matched.
3662 // We will check wepstatus for qualification Bss
3663 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3665 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3667 // For the SESv2 case, we will not qualify WepStatus.
3673 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3674 // It definitely will fail. So, skip it.
3675 // CCX also require not even try to connect it!!
3679 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3680 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3681 if ((pInBss->CentralChannel != pInBss->Channel) &&
3682 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3684 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3686 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3688 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3692 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3699 // copy matching BSS from InTab to OutTab
3700 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3704 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3706 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3708 // 2.4G/5G N only mode
3709 if ((pInBss->HtCapabilityLen == 0) &&
3710 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3712 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3717 // Check the Authmode first
3718 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3720 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3721 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3725 // Check cipher suite, AP must have more secured cipher than station setting
3726 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3728 // If it's not mixed mode, we should only let BSS pass with the same encryption
3729 if (pInBss->WPA.bMixMode == FALSE)
3730 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3733 // check group cipher
3734 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3737 // check pairwise cipher, skip if none matched
3738 // If profile set to AES, let it pass without question.
3739 // If profile set to TKIP, we must find one mateched
3740 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3741 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3742 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3745 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3747 // If it's not mixed mode, we should only let BSS pass with the same encryption
3748 if (pInBss->WPA2.bMixMode == FALSE)
3749 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3752 // check group cipher
3753 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3756 // check pairwise cipher, skip if none matched
3757 // If profile set to AES, let it pass without question.
3758 // If profile set to TKIP, we must find one mateched
3759 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3760 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3761 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3765 // Bss Type matched, SSID matched.
3766 // We will check wepstatus for qualification Bss
3767 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3770 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3771 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3772 if ((pInBss->CentralChannel != pInBss->Channel) &&
3773 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3775 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3777 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3779 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3783 // copy matching BSS from InTab to OutTab
3784 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3789 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3793 BssTableSortByRssi(OutTab);
3797 // IRQL = DISPATCH_LEVEL
3798 VOID BssTableSortByRssi(
3799 IN OUT BSS_TABLE *OutTab)
3804 for (i = 0; i < OutTab->BssNr - 1; i++)
3806 for (j = i+1; j < OutTab->BssNr; j++)
3808 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
3810 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
3811 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
3812 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
3818 VOID BssCipherParse(
3819 IN OUT PBSS_ENTRY pBss)
3823 PRSN_IE_HEADER_STRUCT pRsnHeader;
3824 PCIPHER_SUITE_STRUCT pCipher;
3825 PAKM_SUITE_STRUCT pAKM;
3828 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
3831 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
3835 pBss->WepStatus = Ndis802_11WEPEnabled;
3839 pBss->WepStatus = Ndis802_11WEPDisabled;
3841 // Set default to disable & open authentication before parsing variable IE
3842 pBss->AuthMode = Ndis802_11AuthModeOpen;
3843 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
3846 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
3847 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
3848 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
3849 pBss->WPA.RsnCapability = 0;
3850 pBss->WPA.bMixMode = FALSE;
3852 // Init WPA2 setting
3853 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
3854 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
3855 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
3856 pBss->WPA2.RsnCapability = 0;
3857 pBss->WPA2.bMixMode = FALSE;
3860 Length = (INT) pBss->VarIELen;
3864 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
3865 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
3866 pEid = (PEID_STRUCT) pTmp;
3870 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
3871 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
3877 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3878 pBss->WepStatus = Ndis802_11Encryption1Enabled;
3879 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3880 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3883 pBss->WepStatus = Ndis802_11Encryption2Enabled;
3884 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3885 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3888 pBss->WepStatus = Ndis802_11Encryption3Enabled;
3889 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3890 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
3896 // if Cisco IE_WPA, break
3899 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
3904 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
3906 // if unsupported vendor specific IE
3909 // Skip OUI, version, and multicast suite
3910 // This part should be improved in the future when AP supported multiple cipher suite.
3911 // For now, it's OK since almost all APs have fixed cipher suite supported.
3912 // pTmp = (PUCHAR) pEid->Octet;
3915 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
3923 // Parse group cipher
3927 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
3930 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
3933 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
3936 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
3941 // number of unicast suite
3944 // skip all unicast cipher suites
3945 //Count = *(PUSHORT) pTmp;
3946 Count = (pTmp[1]<<8) + pTmp[0];
3947 pTmp += sizeof(USHORT);
3949 // Parsing all unicast cipher suite
3954 TmpCipher = Ndis802_11WEPDisabled;
3958 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3959 TmpCipher = Ndis802_11Encryption1Enabled;
3962 TmpCipher = Ndis802_11Encryption2Enabled;
3965 TmpCipher = Ndis802_11Encryption3Enabled;
3970 if (TmpCipher > pBss->WPA.PairCipher)
3972 // Move the lower cipher suite to PairCipherAux
3973 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
3974 pBss->WPA.PairCipher = TmpCipher;
3978 pBss->WPA.PairCipherAux = TmpCipher;
3984 // 4. get AKM suite counts
3985 //Count = *(PUSHORT) pTmp;
3986 Count = (pTmp[1]<<8) + pTmp[0];
3987 pTmp += sizeof(USHORT);
3993 // Set AP support WPA mode
3994 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
3995 pBss->AuthMode = Ndis802_11AuthModeWPA;
3997 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4000 // Set AP support WPA mode
4001 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4002 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4004 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4011 // Fixed for WPA-None
4012 if (pBss->BssType == BSS_ADHOC)
4014 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4015 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4016 pBss->WepStatus = pBss->WPA.GroupCipher;
4017 // Patched bugs for old driver
4018 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4019 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4022 pBss->WepStatus = pBss->WPA.PairCipher;
4024 // Check the Pair & Group, if different, turn on mixed mode flag
4025 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4026 pBss->WPA.bMixMode = TRUE;
4031 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4033 // 0. Version must be 1
4034 if (le2cpu16(pRsnHeader->Version) != 1)
4036 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4038 // 1. Check group cipher
4039 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4040 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4043 // Parse group cipher
4044 switch (pCipher->Type)
4047 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4050 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4053 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4056 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4061 // set to correct offset for next parsing
4062 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4064 // 2. Get pairwise cipher counts
4065 //Count = *(PUSHORT) pTmp;
4066 Count = (pTmp[1]<<8) + pTmp[0];
4067 pTmp += sizeof(USHORT);
4069 // 3. Get pairwise cipher
4070 // Parsing all unicast cipher suite
4074 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4075 TmpCipher = Ndis802_11WEPDisabled;
4076 switch (pCipher->Type)
4079 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4080 TmpCipher = Ndis802_11Encryption1Enabled;
4083 TmpCipher = Ndis802_11Encryption2Enabled;
4086 TmpCipher = Ndis802_11Encryption3Enabled;
4091 if (TmpCipher > pBss->WPA2.PairCipher)
4093 // Move the lower cipher suite to PairCipherAux
4094 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4095 pBss->WPA2.PairCipher = TmpCipher;
4099 pBss->WPA2.PairCipherAux = TmpCipher;
4101 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4105 // 4. get AKM suite counts
4106 //Count = *(PUSHORT) pTmp;
4107 Count = (pTmp[1]<<8) + pTmp[0];
4108 pTmp += sizeof(USHORT);
4110 // 5. Get AKM ciphers
4111 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4112 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4118 // Set AP support WPA mode
4119 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4120 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4122 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4125 // Set AP support WPA mode
4126 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4127 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4129 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4134 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4136 // Fixed for WPA-None
4137 if (pBss->BssType == BSS_ADHOC)
4139 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4140 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4141 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4142 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4143 pBss->WepStatus = pBss->WPA.GroupCipher;
4144 // Patched bugs for old driver
4145 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4146 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4148 pBss->WepStatus = pBss->WPA2.PairCipher;
4150 // 6. Get RSN capability
4151 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4152 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4153 pTmp += sizeof(USHORT);
4155 // Check the Pair & Group, if different, turn on mixed mode flag
4156 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4157 pBss->WPA2.bMixMode = TRUE;
4163 Length -= (pEid->Len + 2);
4167 // ===========================================================================================
4169 // ===========================================================================================
4171 /*! \brief generates a random mac address value for IBSS BSSID
4172 * \param Addr the bssid location
4177 VOID MacAddrRandomBssid(
4178 IN PRTMP_ADAPTER pAd,
4183 for (i = 0; i < MAC_ADDR_LEN; i++)
4185 pAddr[i] = RandomByte(pAd);
4188 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4191 /*! \brief init the management mac frame header
4192 * \param p_hdr mac header
4193 * \param subtype subtype of the frame
4194 * \param p_ds destination address, don't care if it is a broadcast address
4196 * \pre the station has the following information in the pAd->StaCfg
4200 * \note this function initializes the following field
4202 IRQL = PASSIVE_LEVEL
4203 IRQL = DISPATCH_LEVEL
4206 VOID MgtMacHeaderInit(
4207 IN PRTMP_ADAPTER pAd,
4208 IN OUT PHEADER_802_11 pHdr80211,
4214 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4216 pHdr80211->FC.Type = BTYPE_MGMT;
4217 pHdr80211->FC.SubType = SubType;
4218 pHdr80211->FC.ToDs = ToDs;
4219 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4221 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4223 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4226 // ===========================================================================================
4228 // ===========================================================================================
4230 /*!***************************************************************************
4231 * This routine build an outgoing frame, and fill all information specified
4232 * in argument list to the frame body. The actual frame size is the summation
4235 * Buffer - pointer to a pre-allocated memory segment
4236 * args - a list of <int arg_size, arg> pairs.
4237 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4238 * function will FAIL!!!
4240 * Size of the buffer
4242 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4244 IRQL = PASSIVE_LEVEL
4245 IRQL = DISPATCH_LEVEL
4247 ****************************************************************************/
4248 ULONG MakeOutgoingFrame(
4250 OUT ULONG *FrameLen, ...)
4257 // calculates the total length
4259 va_start(Args, FrameLen);
4262 leng = va_arg(Args, int);
4263 if (leng == END_OF_ARGS)
4267 p = va_arg(Args, PVOID);
4268 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4269 TotLeng = TotLeng + leng;
4272 va_end(Args); /* clean up */
4273 *FrameLen = TotLeng;
4277 // ===========================================================================================
4279 // ===========================================================================================
4281 /*! \brief Initialize The MLME Queue, used by MLME Functions
4282 * \param *Queue The MLME Queue
4283 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4286 * \note Because this is done only once (at the init stage), no need to be locked
4288 IRQL = PASSIVE_LEVEL
4291 NDIS_STATUS MlmeQueueInit(
4292 IN MLME_QUEUE *Queue)
4296 NdisAllocateSpinLock(&Queue->Lock);
4302 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4304 Queue->Entry[i].Occupied = FALSE;
4305 Queue->Entry[i].MsgLen = 0;
4306 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4309 return NDIS_STATUS_SUCCESS;
4312 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4313 * \param *Queue The MLME Queue
4314 * \param Machine The State Machine Id
4315 * \param MsgType The Message Type
4316 * \param MsgLen The Message length
4317 * \param *Msg The message pointer
4318 * \return TRUE if enqueue is successful, FALSE if the queue is full
4321 * \note The message has to be initialized
4323 IRQL = PASSIVE_LEVEL
4324 IRQL = DISPATCH_LEVEL
4327 BOOLEAN MlmeEnqueue(
4328 IN PRTMP_ADAPTER pAd,
4335 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4337 // Do nothing if the driver is starting halt state.
4338 // This might happen when timer already been fired before cancel timer with mlmehalt
4339 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4342 // First check the size, it MUST not exceed the mlme queue size
4343 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4345 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4349 if (MlmeQueueFull(Queue))
4354 NdisAcquireSpinLock(&(Queue->Lock));
4358 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4363 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4364 Queue->Entry[Tail].Occupied = TRUE;
4365 Queue->Entry[Tail].Machine = Machine;
4366 Queue->Entry[Tail].MsgType = MsgType;
4367 Queue->Entry[Tail].MsgLen = MsgLen;
4371 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4374 NdisReleaseSpinLock(&(Queue->Lock));
4378 /*! \brief This function is used when Recv gets a MLME message
4379 * \param *Queue The MLME Queue
4380 * \param TimeStampHigh The upper 32 bit of timestamp
4381 * \param TimeStampLow The lower 32 bit of timestamp
4382 * \param Rssi The receiving RSSI strength
4383 * \param MsgLen The length of the message
4384 * \param *Msg The message pointer
4385 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4389 IRQL = DISPATCH_LEVEL
4392 BOOLEAN MlmeEnqueueForRecv(
4393 IN PRTMP_ADAPTER pAd,
4395 IN ULONG TimeStampHigh,
4396 IN ULONG TimeStampLow,
4405 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4407 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4409 // Do nothing if the driver is starting halt state.
4410 // This might happen when timer already been fired before cancel timer with mlmehalt
4411 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4413 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4417 // First check the size, it MUST not exceed the mlme queue size
4418 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4420 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4424 if (MlmeQueueFull(Queue))
4430 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4432 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4437 // OK, we got all the informations, it is time to put things into queue
4438 NdisAcquireSpinLock(&(Queue->Lock));
4442 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4446 Queue->Entry[Tail].Occupied = TRUE;
4447 Queue->Entry[Tail].Machine = Machine;
4448 Queue->Entry[Tail].MsgType = MsgType;
4449 Queue->Entry[Tail].MsgLen = MsgLen;
4450 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4451 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4452 Queue->Entry[Tail].Rssi0 = Rssi0;
4453 Queue->Entry[Tail].Rssi1 = Rssi1;
4454 Queue->Entry[Tail].Rssi2 = Rssi2;
4455 Queue->Entry[Tail].Signal = Signal;
4456 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4458 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4462 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4465 NdisReleaseSpinLock(&(Queue->Lock));
4467 RT28XX_MLME_HANDLER(pAd);
4473 /*! \brief Dequeue a message from the MLME Queue
4474 * \param *Queue The MLME Queue
4475 * \param *Elem The message dequeued from MLME Queue
4476 * \return TRUE if the Elem contains something, FALSE otherwise
4480 IRQL = DISPATCH_LEVEL
4483 BOOLEAN MlmeDequeue(
4484 IN MLME_QUEUE *Queue,
4485 OUT MLME_QUEUE_ELEM **Elem)
4487 NdisAcquireSpinLock(&(Queue->Lock));
4488 *Elem = &(Queue->Entry[Queue->Head]);
4491 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4495 NdisReleaseSpinLock(&(Queue->Lock));
4499 // IRQL = DISPATCH_LEVEL
4500 VOID MlmeRestartStateMachine(
4501 IN PRTMP_ADAPTER pAd)
4505 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4508 // Cancel all timer events
4509 // Be careful to cancel new added timer
4510 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4511 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4512 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4513 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4514 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4515 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4518 // Change back to original channel in case of doing scan
4519 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4520 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4522 // Resume MSDU which is turned off durning scan
4523 RTMPResumeMsduTransmission(pAd);
4526 // Set all state machines back IDLE
4527 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4528 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4529 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4530 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4531 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4532 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4536 /*! \brief test if the MLME Queue is empty
4537 * \param *Queue The MLME Queue
4538 * \return TRUE if the Queue is empty, FALSE otherwise
4542 IRQL = DISPATCH_LEVEL
4545 BOOLEAN MlmeQueueEmpty(
4546 IN MLME_QUEUE *Queue)
4550 NdisAcquireSpinLock(&(Queue->Lock));
4551 Ans = (Queue->Num == 0);
4552 NdisReleaseSpinLock(&(Queue->Lock));
4557 /*! \brief test if the MLME Queue is full
4558 * \param *Queue The MLME Queue
4559 * \return TRUE if the Queue is empty, FALSE otherwise
4563 IRQL = PASSIVE_LEVEL
4564 IRQL = DISPATCH_LEVEL
4567 BOOLEAN MlmeQueueFull(
4568 IN MLME_QUEUE *Queue)
4572 NdisAcquireSpinLock(&(Queue->Lock));
4573 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4574 NdisReleaseSpinLock(&(Queue->Lock));
4579 /*! \brief The destructor of MLME Queue
4584 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4586 IRQL = PASSIVE_LEVEL
4589 VOID MlmeQueueDestroy(
4590 IN MLME_QUEUE *pQueue)
4592 NdisAcquireSpinLock(&(pQueue->Lock));
4596 NdisReleaseSpinLock(&(pQueue->Lock));
4597 NdisFreeSpinLock(&(pQueue->Lock));
4600 /*! \brief To substitute the message type if the message is coming from external
4601 * \param pFrame The frame received
4602 * \param *Machine The state machine
4603 * \param *MsgType the message type for the state machine
4604 * \return TRUE if the substitution is successful, FALSE otherwise
4608 IRQL = DISPATCH_LEVEL
4611 BOOLEAN MsgTypeSubst(
4612 IN PRTMP_ADAPTER pAd,
4613 IN PFRAME_802_11 pFrame,
4621 // Pointer to start of data frames including SNAP header
4622 pData = (PUCHAR) pFrame + LENGTH_802_11;
4624 // The only data type will pass to this function is EAPOL frame
4625 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4627 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4629 // Cisco Aironet SNAP header
4630 *Machine = AIRONET_STATE_MACHINE;
4631 *MsgType = MT2_AIRONET_MSG;
4635 *Machine = WPA_PSK_STATE_MACHINE;
4636 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4637 return(WpaMsgTypeSubst(EAPType, MsgType));
4641 switch (pFrame->Hdr.FC.SubType)
4643 case SUBTYPE_ASSOC_REQ:
4644 *Machine = ASSOC_STATE_MACHINE;
4645 *MsgType = MT2_PEER_ASSOC_REQ;
4647 case SUBTYPE_ASSOC_RSP:
4648 *Machine = ASSOC_STATE_MACHINE;
4649 *MsgType = MT2_PEER_ASSOC_RSP;
4651 case SUBTYPE_REASSOC_REQ:
4652 *Machine = ASSOC_STATE_MACHINE;
4653 *MsgType = MT2_PEER_REASSOC_REQ;
4655 case SUBTYPE_REASSOC_RSP:
4656 *Machine = ASSOC_STATE_MACHINE;
4657 *MsgType = MT2_PEER_REASSOC_RSP;
4659 case SUBTYPE_PROBE_REQ:
4660 *Machine = SYNC_STATE_MACHINE;
4661 *MsgType = MT2_PEER_PROBE_REQ;
4663 case SUBTYPE_PROBE_RSP:
4664 *Machine = SYNC_STATE_MACHINE;
4665 *MsgType = MT2_PEER_PROBE_RSP;
4667 case SUBTYPE_BEACON:
4668 *Machine = SYNC_STATE_MACHINE;
4669 *MsgType = MT2_PEER_BEACON;
4672 *Machine = SYNC_STATE_MACHINE;
4673 *MsgType = MT2_PEER_ATIM;
4675 case SUBTYPE_DISASSOC:
4676 *Machine = ASSOC_STATE_MACHINE;
4677 *MsgType = MT2_PEER_DISASSOC_REQ;
4680 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4681 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4682 if (Seq == 1 || Seq == 3)
4684 *Machine = AUTH_RSP_STATE_MACHINE;
4685 *MsgType = MT2_PEER_AUTH_ODD;
4687 else if (Seq == 2 || Seq == 4)
4689 *Machine = AUTH_STATE_MACHINE;
4690 *MsgType = MT2_PEER_AUTH_EVEN;
4697 case SUBTYPE_DEAUTH:
4698 *Machine = AUTH_RSP_STATE_MACHINE;
4699 *MsgType = MT2_PEER_DEAUTH;
4701 case SUBTYPE_ACTION:
4702 *Machine = ACTION_STATE_MACHINE;
4703 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4704 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4706 *MsgType = MT2_ACT_INVALID;
4710 *MsgType = (pFrame->Octet[0]&0x7F);
4721 // ===========================================================================================
4723 // ===========================================================================================
4725 /*! \brief Initialize the state machine.
4726 * \param *S pointer to the state machine
4727 * \param Trans State machine transition function
4728 * \param StNr number of states
4729 * \param MsgNr number of messages
4730 * \param DefFunc default function, when there is invalid state/message combination
4731 * \param InitState initial state of the state machine
4732 * \param Base StateMachine base, internal use only
4733 * \pre p_sm should be a legal pointer
4736 IRQL = PASSIVE_LEVEL
4739 VOID StateMachineInit(
4740 IN STATE_MACHINE *S,
4741 IN STATE_MACHINE_FUNC Trans[],
4744 IN STATE_MACHINE_FUNC DefFunc,
4750 // set number of states and messages
4755 S->TransFunc = Trans;
4757 // init all state transition to default function
4758 for (i = 0; i < StNr; i++)
4760 for (j = 0; j < MsgNr; j++)
4762 S->TransFunc[i * MsgNr + j] = DefFunc;
4766 // set the starting state
4767 S->CurrState = InitState;
4770 /*! \brief This function fills in the function pointer into the cell in the state machine
4771 * \param *S pointer to the state machine
4773 * \param Msg incoming message
4774 * \param f the function to be executed when (state, message) combination occurs at the state machine
4775 * \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
4778 IRQL = PASSIVE_LEVEL
4781 VOID StateMachineSetAction(
4782 IN STATE_MACHINE *S,
4785 IN STATE_MACHINE_FUNC Func)
4789 MsgIdx = Msg - S->Base;
4791 if (St < S->NrState && MsgIdx < S->NrMsg)
4793 // boundary checking before setting the action
4794 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
4798 /*! \brief This function does the state transition
4799 * \param *Adapter the NIC adapter pointer
4800 * \param *S the state machine
4801 * \param *Elem the message to be executed
4804 IRQL = DISPATCH_LEVEL
4807 VOID StateMachinePerformAction(
4808 IN PRTMP_ADAPTER pAd,
4809 IN STATE_MACHINE *S,
4810 IN MLME_QUEUE_ELEM *Elem)
4812 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
4816 ==========================================================================
4818 The drop function, when machine executes this, the message is simply
4819 ignored. This function does nothing, the message is freed in
4820 StateMachinePerformAction()
4821 ==========================================================================
4824 IN PRTMP_ADAPTER pAd,
4825 IN MLME_QUEUE_ELEM *Elem)
4829 // ===========================================================================================
4831 // ===========================================================================================
4834 ==========================================================================
4837 IRQL = PASSIVE_LEVEL
4839 ==========================================================================
4842 IN PRTMP_ADAPTER pAd,
4846 pAd->Mlme.ShiftReg = 1;
4848 pAd->Mlme.ShiftReg = Seed;
4852 ==========================================================================
4854 ==========================================================================
4857 IN PRTMP_ADAPTER pAd)
4864 if (pAd->Mlme.ShiftReg == 0)
4865 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
4867 for (i = 0; i < 8; i++)
4869 if (pAd->Mlme.ShiftReg & 0x00000001)
4871 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
4876 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
4879 R = (R << 1) | Result;
4885 VOID AsicUpdateAutoFallBackTable(
4886 IN PRTMP_ADAPTER pAd,
4887 IN PUCHAR pRateTable)
4890 HT_FBK_CFG0_STRUC HtCfg0;
4891 HT_FBK_CFG1_STRUC HtCfg1;
4892 LG_FBK_CFG0_STRUC LgCfg0;
4893 LG_FBK_CFG1_STRUC LgCfg1;
4894 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
4896 // set to initial value
4897 HtCfg0.word = 0x65432100;
4898 HtCfg1.word = 0xedcba988;
4899 LgCfg0.word = 0xedcba988;
4900 LgCfg1.word = 0x00002100;
4902 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
4903 for (i = 1; i < *((PUCHAR) pRateTable); i++)
4905 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
4906 switch (pCurrTxRate->Mode)
4912 switch(pCurrTxRate->CurrMCS)
4915 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4918 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4921 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4924 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4927 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4930 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4933 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4936 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
4944 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
4946 switch(pCurrTxRate->CurrMCS)
4949 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
4952 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
4955 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
4958 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
4961 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
4964 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
4967 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
4970 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
4973 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
4976 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
4979 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
4982 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
4985 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
4988 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
4991 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
4994 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
4997 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5004 pNextTxRate = pCurrTxRate;
5007 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5008 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5009 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5010 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5014 ========================================================================
5016 Routine Description:
5017 Set MAC register value according operation mode.
5018 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5019 If MM or GF mask is not set, those passing argument doesn't not take effect.
5021 Operation mode meaning:
5022 = 0 : Pure HT, no preotection.
5023 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5024 = 0x10: No Transmission in 40M is protected.
5025 = 0x11: Transmission in both 40M and 20M shall be protected
5027 we should choose not to use GF. But still set correct ASIC registers.
5028 ========================================================================
5030 VOID AsicUpdateProtect(
5031 IN PRTMP_ADAPTER pAd,
5032 IN USHORT OperationMode,
5034 IN BOOLEAN bDisableBGProtect,
5035 IN BOOLEAN bNonGFExist)
5037 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5043 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5048 if (pAd->BATable.numAsOriginator)
5051 // enable the RTS/CTS to avoid channel collision
5053 SetMask = ALLN_SETPROTECT;
5057 // Config ASIC RTS threshold register
5058 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5059 MacReg &= 0xFF0000FF;
5061 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5063 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5064 (pAd->CommonCfg.bAggregationCapable == TRUE))
5065 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5067 MacReg |= (0x1000 << 8);
5071 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5074 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5076 // Initial common protection settings
5077 RTMPZeroMemory(Protect, sizeof(Protect));
5080 ProtCfg.field.TxopAllowGF40 = 1;
5081 ProtCfg.field.TxopAllowGF20 = 1;
5082 ProtCfg.field.TxopAllowMM40 = 1;
5083 ProtCfg.field.TxopAllowMM20 = 1;
5084 ProtCfg.field.TxopAllowOfdm = 1;
5085 ProtCfg.field.TxopAllowCck = 1;
5086 ProtCfg.field.RTSThEn = 1;
5087 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5089 // update PHY mode and rate
5090 if (pAd->CommonCfg.Channel > 14)
5091 ProtCfg.field.ProtectRate = 0x4000;
5092 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5094 // Handle legacy(B/G) protection
5095 if (bDisableBGProtect)
5097 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5098 ProtCfg.field.ProtectCtrl = 0;
5099 Protect[0] = ProtCfg.word;
5100 Protect[1] = ProtCfg.word;
5104 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5105 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5106 Protect[0] = ProtCfg.word;
5107 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5108 Protect[1] = ProtCfg.word;
5111 // Decide HT frame protection.
5112 if ((SetMask & ALLN_SETPROTECT) != 0)
5114 switch(OperationMode)
5118 // 1.All STAs in the BSS are 20/40 MHz HT
5119 // 2. in ai 20/40MHz BSS
5120 // 3. all STAs are 20MHz in a 20MHz BSS
5121 // Pure HT. no protection.
5125 // PROT_TXOP(25:20) -- 010111
5126 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5127 // PROT_CTRL(17:16) -- 00 (None)
5128 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5129 Protect[2] = 0x01744004;
5133 // PROT_TXOP(25:20) -- 111111
5134 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5135 // PROT_CTRL(17:16) -- 00 (None)
5136 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5137 Protect[3] = 0x03f44084;
5141 // PROT_TXOP(25:20) -- 010111
5142 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5143 // PROT_CTRL(17:16) -- 00 (None)
5144 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5145 Protect[4] = 0x01744004;
5149 // PROT_TXOP(25:20) -- 111111
5150 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5151 // PROT_CTRL(17:16) -- 00 (None)
5152 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5153 Protect[5] = 0x03f44084;
5157 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5158 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5159 Protect[4] = 0x01754004;
5160 Protect[5] = 0x03f54084;
5162 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5166 // This is "HT non-member protection mode."
5167 // If there may be non-HT STAs my BSS
5168 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5169 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5170 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5172 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5173 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5175 //Assign Protection method for 20&40 MHz packets
5176 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5177 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5178 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5179 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5180 Protect[2] = ProtCfg.word;
5181 Protect[3] = ProtCfg4.word;
5182 Protect[4] = ProtCfg.word;
5183 Protect[5] = ProtCfg4.word;
5184 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5188 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5189 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5190 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5192 //Assign Protection method for 40MHz packets
5193 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5194 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5195 Protect[2] = ProtCfg.word;
5196 Protect[3] = ProtCfg4.word;
5199 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5200 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5202 Protect[4] = ProtCfg.word;
5203 Protect[5] = ProtCfg4.word;
5205 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5209 // HT mixed mode. PROTECT ALL!
5211 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5212 ProtCfg4.word = 0x03f44084;
5213 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5214 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5216 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5217 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5219 //Assign Protection method for 20&40 MHz packets
5220 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5221 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5222 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5223 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5224 Protect[2] = ProtCfg.word;
5225 Protect[3] = ProtCfg4.word;
5226 Protect[4] = ProtCfg.word;
5227 Protect[5] = ProtCfg4.word;
5228 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5232 // Special on for Atheros problem n chip.
5233 Protect[2] = 0x01754004;
5234 Protect[3] = 0x03f54084;
5235 Protect[4] = 0x01754004;
5236 Protect[5] = 0x03f54084;
5237 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5242 offset = CCK_PROT_CFG;
5243 for (i = 0;i < 6;i++)
5245 if ((SetMask & (1<< i)))
5247 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5253 ==========================================================================
5256 IRQL = PASSIVE_LEVEL
5257 IRQL = DISPATCH_LEVEL
5259 ==========================================================================
5261 VOID AsicSwitchChannel(
5262 IN PRTMP_ADAPTER pAd,
5266 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5267 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5269 UINT32 Value = 0; //BbpReg, Value;
5270 RTMP_RF_REGS *RFRegTable;
5272 // Search Tx power value
5273 for (index = 0; index < pAd->ChannelListNum; index++)
5275 if (Channel == pAd->ChannelList[index].Channel)
5277 TxPwer = pAd->ChannelList[index].Power;
5278 TxPwer2 = pAd->ChannelList[index].Power2;
5283 if (index == MAX_NUM_OF_CHANNELS)
5285 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5289 // The RF programming sequence is difference between 3xxx and 2xxx
5290 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5292 /* modify by WY for Read RF Reg. error */
5295 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5297 if (Channel == FreqItems3020[index].Channel)
5299 // Programming channel parameters
5300 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5301 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5303 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5304 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5305 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5308 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5309 RFValue = (RFValue & 0xE0) | TxPwer;
5310 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5313 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5314 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5315 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5318 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5320 RFValue = pAd->Mlme.CaliBW40RfR24;
5321 //DISABLE_11N_CHECK(pAd);
5325 RFValue = pAd->Mlme.CaliBW20RfR24;
5327 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5330 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5331 RFValue = RFValue | 0x1;
5332 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5334 // latch channel for future usage.
5335 pAd->LatchRfRegs.Channel = Channel;
5341 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5346 pAd->Antenna.field.TxPath,
5347 FreqItems3020[index].N,
5348 FreqItems3020[index].K,
5349 FreqItems3020[index].R));
5354 RFRegTable = RF2850RegTable;
5356 switch (pAd->RfIcType)
5363 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5365 if (Channel == RFRegTable[index].Channel)
5367 R2 = RFRegTable[index].R2;
5368 if (pAd->Antenna.field.TxPath == 1)
5370 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5373 if (pAd->Antenna.field.RxPath == 2)
5375 R2 |= 0x40; // write 1 to off Rxpath.
5377 else if (pAd->Antenna.field.RxPath == 1)
5379 R2 |= 0x20040; // write 1 to off RxPath
5384 // initialize R3, R4
5385 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5386 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5388 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5390 if ((TxPwer >= -7) && (TxPwer < 0))
5392 TxPwer = (7+TxPwer);
5393 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5394 R3 |= (TxPwer << 10);
5395 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5399 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5400 R3 |= (TxPwer << 10) | (1 << 9);
5404 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5406 TxPwer2 = (7+TxPwer2);
5407 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5408 R4 |= (TxPwer2 << 7);
5409 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5413 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5414 R4 |= (TxPwer2 << 7) | (1 << 6);
5419 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5420 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5423 // Based on BBP current mode before changing RF channel.
5424 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5430 pAd->LatchRfRegs.Channel = Channel;
5431 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5432 pAd->LatchRfRegs.R2 = R2;
5433 pAd->LatchRfRegs.R3 = R3;
5434 pAd->LatchRfRegs.R4 = R4;
5436 // Set RF value 1's set R3[bit2] = [0]
5437 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5438 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5439 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5440 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5444 // Set RF value 2's set R3[bit2] = [1]
5445 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5446 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5447 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5448 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5452 // Set RF value 3's set R3[bit2] = [0]
5453 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5454 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5455 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5456 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5468 // Change BBP setting during siwtch from a->g, g->a
5471 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5473 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5474 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5475 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5476 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.
5477 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5479 // Rx High power VGA offset for LNA select
5480 if (pAd->NicConfig2.field.ExternalLNAForG)
5482 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5483 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5487 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5488 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5491 // 5G band selection PIN, bit1 and bit2 are complement
5492 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5495 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5497 // Turn off unused PA or LNA when only 1T or 1R
5498 if (pAd->Antenna.field.TxPath == 1)
5500 TxPinCfg &= 0xFFFFFFF3;
5502 if (pAd->Antenna.field.RxPath == 1)
5504 TxPinCfg &= 0xFFFFF3FF;
5507 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5511 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5513 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5514 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5515 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5516 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.
5517 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5519 // Rx High power VGA offset for LNA select
5520 if (pAd->NicConfig2.field.ExternalLNAForA)
5522 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5526 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5529 // 5G band selection PIN, bit1 and bit2 are complement
5530 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5533 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5535 // Turn off unused PA or LNA when only 1T or 1R
5536 if (pAd->Antenna.field.TxPath == 1)
5538 TxPinCfg &= 0xFFFFFFF3;
5540 if (pAd->Antenna.field.RxPath == 1)
5542 TxPinCfg &= 0xFFFFF3FF;
5545 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5548 // R66 should be set according to Channel and use 20MHz when scanning
5549 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5551 RTMPSetAGCInitValue(pAd, BW_20);
5553 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5556 // On 11A, We should delay and wait RF/BBP to be stable
5557 // and the appropriate time should be 1000 micro seconds
5558 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5560 RTMPusecDelay(1000);
5562 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",
5565 (R3 & 0x00003e00) >> 9,
5566 (R4 & 0x000007c0) >> 6,
5567 pAd->Antenna.field.TxPath,
5568 pAd->LatchRfRegs.R1,
5569 pAd->LatchRfRegs.R2,
5570 pAd->LatchRfRegs.R3,
5571 pAd->LatchRfRegs.R4));
5575 ==========================================================================
5577 This function is required for 2421 only, and should not be used during
5578 site survey. It's only required after NIC decided to stay at a channel
5579 for a longer period.
5580 When this function is called, it's always after AsicSwitchChannel().
5582 IRQL = PASSIVE_LEVEL
5583 IRQL = DISPATCH_LEVEL
5585 ==========================================================================
5587 VOID AsicLockChannel(
5588 IN PRTMP_ADAPTER pAd,
5594 ==========================================================================
5597 IRQL = PASSIVE_LEVEL
5598 IRQL = DISPATCH_LEVEL
5600 ==========================================================================
5602 VOID AsicAntennaSelect(
5603 IN PRTMP_ADAPTER pAd,
5609 ========================================================================
5611 Routine Description:
5612 Antenna miscellaneous setting.
5615 pAd Pointer to our adapter
5616 BandState Indicate current Band State.
5621 IRQL <= DISPATCH_LEVEL
5624 1.) Frame End type control
5625 only valid for G only (RF_2527 & RF_2529)
5626 0: means DPDT, set BBP R4 bit 5 to 1
5627 1: means SPDT, set BBP R4 bit 5 to 0
5630 ========================================================================
5632 VOID AsicAntennaSetting(
5633 IN PRTMP_ADAPTER pAd,
5634 IN ABGBAND_STATE BandState)
5638 VOID AsicRfTuningExec(
5639 IN PVOID SystemSpecific1,
5640 IN PVOID FunctionContext,
5641 IN PVOID SystemSpecific2,
5642 IN PVOID SystemSpecific3)
5647 ==========================================================================
5649 Gives CCK TX rate 2 more dB TX power.
5650 This routine works only in LINK UP in INFRASTRUCTURE mode.
5652 calculate desired Tx power in RF R3.Tx0~5, should consider -
5653 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5654 1. TxPowerPercentage
5655 2. auto calibration based on TSSI feedback
5656 3. extra 2 db for CCK
5657 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5659 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5660 it should be called AFTER MlmeDynamicTxRatSwitching()
5661 ==========================================================================
5663 VOID AsicAdjustTxPower(
5664 IN PRTMP_ADAPTER pAd)
5668 BOOLEAN bAutoTxAgc = FALSE;
5669 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5670 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5671 PCHAR pTxAgcCompensate;
5675 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5677 if (pAd->CommonCfg.CentralChannel > 14)
5679 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5680 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5681 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5682 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5683 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5687 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5688 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5689 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5690 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5691 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5696 if (pAd->CommonCfg.Channel > 14)
5698 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5699 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5700 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5701 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5702 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5706 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5707 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5708 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5709 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5710 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5714 // TX power compensation for temperature variation based on TSSI. try every 4 second
5715 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5717 if (pAd->CommonCfg.Channel <= 14)
5720 bAutoTxAgc = pAd->bAutoTxAgcG;
5721 TssiRef = pAd->TssiRefG;
5722 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5723 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5724 TxAgcStep = pAd->TxAgcStepG;
5725 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5730 bAutoTxAgc = pAd->bAutoTxAgcA;
5731 TssiRef = pAd->TssiRefA;
5732 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
5733 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
5734 TxAgcStep = pAd->TxAgcStepA;
5735 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5740 /* BbpR1 is unsigned char */
5741 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
5743 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
5744 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
5745 /* step value is defined in pAd->TxAgcStepG for tx power value */
5747 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
5748 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
5749 above value are examined in mass factory production */
5750 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
5752 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
5753 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
5754 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
5756 if (BbpR49 > pTssiMinusBoundary[1])
5758 // Reading is larger than the reference value
5759 // check for how large we need to decrease the Tx power
5760 for (idx = 1; idx < 5; idx++)
5762 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
5765 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
5766 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
5768 DeltaPwr += (*pTxAgcCompensate);
5769 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
5770 BbpR49, TssiRef, TxAgcStep, idx-1));
5772 else if (BbpR49 < pTssiPlusBoundary[1])
5774 // Reading is smaller than the reference value
5775 // check for how large we need to increase the Tx power
5776 for (idx = 1; idx < 5; idx++)
5778 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
5781 // The index is the step we should increase, idx = 0 means there is nothing to compensate
5782 *pTxAgcCompensate = TxAgcStep * (idx-1);
5783 DeltaPwr += (*pTxAgcCompensate);
5784 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5785 BbpR49, TssiRef, TxAgcStep, idx-1));
5789 *pTxAgcCompensate = 0;
5790 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5791 BbpR49, TssiRef, TxAgcStep, 0));
5797 if (pAd->CommonCfg.Channel <= 14)
5799 bAutoTxAgc = pAd->bAutoTxAgcG;
5800 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5804 bAutoTxAgc = pAd->bAutoTxAgcA;
5805 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5809 DeltaPwr += (*pTxAgcCompensate);
5812 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
5815 /* calculate delta power based on the percentage specified from UI */
5816 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
5817 // We lower TX power here according to the percentage specified from UI
5818 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
5820 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
5822 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
5826 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
5830 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
5834 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
5839 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
5844 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
5846 /* reset different new tx power for different TX rate */
5849 if (TxPwr[i] != 0xffffffff)
5853 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
5855 if ((Value + DeltaPwr) < 0)
5857 Value = 0; /* min */
5859 else if ((Value + DeltaPwr) > 0xF)
5861 Value = 0xF; /* max */
5865 Value += DeltaPwr; /* temperature compensation */
5868 /* fill new value to CSR offset */
5869 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
5872 /* write tx power value to CSR */
5873 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
5874 TX power for OFDM 6M/9M
5875 TX power for CCK5.5M/11M
5876 TX power for CCK1M/2M */
5877 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
5878 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
5885 ==========================================================================
5887 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
5888 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
5889 the wakeup timer timeout. Driver has to issue a separate command to wake
5892 IRQL = DISPATCH_LEVEL
5894 ==========================================================================
5896 VOID AsicSleepThenAutoWakeup(
5897 IN PRTMP_ADAPTER pAd,
5898 IN USHORT TbttNumToNextWakeUp)
5900 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
5904 ==========================================================================
5906 AsicForceWakeup() is used whenever manual wakeup is required
5907 AsicForceSleep() should only be used when not in INFRA BSS. When
5908 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
5909 ==========================================================================
5911 VOID AsicForceSleep(
5912 IN PRTMP_ADAPTER pAd)
5918 ==========================================================================
5920 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
5923 IRQL = PASSIVE_LEVEL
5924 IRQL = DISPATCH_LEVEL
5925 ==========================================================================
5927 VOID AsicForceWakeup(
5928 IN PRTMP_ADAPTER pAd,
5931 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
5932 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
5936 ==========================================================================
5940 IRQL = DISPATCH_LEVEL
5942 ==========================================================================
5945 IN PRTMP_ADAPTER pAd,
5949 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
5950 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
5952 Addr4 = (ULONG)(pBssid[0]) |
5953 (ULONG)(pBssid[1] << 8) |
5954 (ULONG)(pBssid[2] << 16) |
5955 (ULONG)(pBssid[3] << 24);
5956 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
5959 // always one BSSID in STA mode
5960 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
5962 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
5965 VOID AsicSetMcastWC(
5966 IN PRTMP_ADAPTER pAd)
5968 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
5971 pEntry->Sst = SST_ASSOC;
5972 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
5973 pEntry->PsMode = PWR_ACTIVE;
5974 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
5975 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
5979 ==========================================================================
5982 IRQL = DISPATCH_LEVEL
5984 ==========================================================================
5986 VOID AsicDelWcidTab(
5987 IN PRTMP_ADAPTER pAd,
5990 ULONG Addr0 = 0x0, Addr1 = 0x0;
5993 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
5994 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
5995 RTMP_IO_WRITE32(pAd, offset, Addr0);
5997 RTMP_IO_WRITE32(pAd, offset, Addr1);
6001 ==========================================================================
6004 IRQL = DISPATCH_LEVEL
6006 ==========================================================================
6009 IN PRTMP_ADAPTER pAd)
6011 TX_LINK_CFG_STRUC TxLinkCfg;
6014 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6015 TxLinkCfg.field.TxRDGEn = 1;
6016 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6018 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6021 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6023 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6027 ==========================================================================
6030 IRQL = DISPATCH_LEVEL
6032 ==========================================================================
6034 VOID AsicDisableRDG(
6035 IN PRTMP_ADAPTER pAd)
6037 TX_LINK_CFG_STRUC TxLinkCfg;
6041 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6042 TxLinkCfg.field.TxRDGEn = 0;
6043 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6045 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6048 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6049 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6052 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6053 if (pAd->CommonCfg.bEnableTxBurst)
6056 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6060 ==========================================================================
6063 IRQL = PASSIVE_LEVEL
6064 IRQL = DISPATCH_LEVEL
6066 ==========================================================================
6068 VOID AsicDisableSync(
6069 IN PRTMP_ADAPTER pAd)
6071 BCN_TIME_CFG_STRUC csr;
6073 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6075 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6076 // that NIC will never wakes up because TSF stops and no more
6078 pAd->TbttTickCount = 0;
6079 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6080 csr.field.bBeaconGen = 0;
6081 csr.field.bTBTTEnable = 0;
6082 csr.field.TsfSyncMode = 0;
6083 csr.field.bTsfTicking = 0;
6084 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6089 ==========================================================================
6092 IRQL = DISPATCH_LEVEL
6094 ==========================================================================
6096 VOID AsicEnableBssSync(
6097 IN PRTMP_ADAPTER pAd)
6099 BCN_TIME_CFG_STRUC csr;
6101 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6103 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6106 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6107 csr.field.bTsfTicking = 1;
6108 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6109 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6110 csr.field.bTBTTEnable = 1;
6113 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6117 ==========================================================================
6120 BEACON frame in shared memory should be built ok before this routine
6121 can be called. Otherwise, a garbage frame maybe transmitted out every
6124 IRQL = DISPATCH_LEVEL
6126 ==========================================================================
6128 VOID AsicEnableIbssSync(
6129 IN PRTMP_ADAPTER pAd)
6131 BCN_TIME_CFG_STRUC csr9;
6135 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6137 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6138 csr9.field.bBeaconGen = 0;
6139 csr9.field.bTBTTEnable = 0;
6140 csr9.field.bTsfTicking = 0;
6141 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6145 // move BEACON TXD and frame content to on-chip memory
6146 ptr = (PUCHAR)&pAd->BeaconTxWI;
6147 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6149 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6153 // start right after the 16-byte TXWI field
6154 ptr = pAd->BeaconBuf;
6155 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6157 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6162 // start sending BEACON
6163 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6164 csr9.field.bTsfTicking = 1;
6165 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6166 csr9.field.bTBTTEnable = 1;
6167 csr9.field.bBeaconGen = 1;
6168 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6172 ==========================================================================
6175 IRQL = PASSIVE_LEVEL
6176 IRQL = DISPATCH_LEVEL
6178 ==========================================================================
6180 VOID AsicSetEdcaParm(
6181 IN PRTMP_ADAPTER pAd,
6182 IN PEDCA_PARM pEdcaParm)
6184 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6185 AC_TXOP_CSR0_STRUC csr0;
6186 AC_TXOP_CSR1_STRUC csr1;
6187 AIFSN_CSR_STRUC AifsnCsr;
6188 CWMIN_CSR_STRUC CwminCsr;
6189 CWMAX_CSR_STRUC CwmaxCsr;
6196 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6198 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6199 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6200 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6202 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6203 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6206 //========================================================
6207 // MAC Register has a copy .
6208 //========================================================
6209 if( pAd->CommonCfg.bEnableTxBurst )
6211 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6212 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6215 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6216 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6217 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6218 Ac0Cfg.field.Aifsn = 2;
6219 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6221 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6222 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6223 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6224 Ac1Cfg.field.Aifsn = 2;
6225 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6227 if (pAd->CommonCfg.PhyMode == PHY_11B)
6229 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6230 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6234 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6235 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6237 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6238 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6239 Ac2Cfg.field.Aifsn = 2;
6240 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6241 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6242 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6243 Ac3Cfg.field.Aifsn = 2;
6244 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6246 //========================================================
6247 // DMA Register has a copy too.
6248 //========================================================
6249 csr0.field.Ac0Txop = 0; // QID_AC_BE
6250 csr0.field.Ac1Txop = 0; // QID_AC_BK
6251 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6252 if (pAd->CommonCfg.PhyMode == PHY_11B)
6254 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6255 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6259 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6260 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6262 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6265 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6266 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6267 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6268 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6269 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6272 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6273 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6274 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6275 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6276 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6278 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6280 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6284 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6285 //========================================================
6286 // MAC Register has a copy.
6287 //========================================================
6289 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6290 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6292 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6294 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6295 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6296 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6297 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6299 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6300 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6301 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6302 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6304 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6305 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6306 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6307 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6310 // Tuning for Wi-Fi WMM S06
6311 if (pAd->CommonCfg.bWiFiTest &&
6312 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6313 Ac2Cfg.field.Aifsn -= 1;
6315 // Tuning for TGn Wi-Fi 5.2.32
6316 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6317 if (STA_TGN_WIFI_ON(pAd) &&
6318 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6320 Ac0Cfg.field.Aifsn = 3;
6321 Ac2Cfg.field.AcTxop = 5;
6325 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6326 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6327 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6328 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6331 if (pAd->CommonCfg.bWiFiTest)
6333 if (Ac3Cfg.field.AcTxop == 102)
6335 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6336 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6337 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6338 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6339 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6342 //#endif // WIFI_TEST //
6344 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6345 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6346 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6347 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6350 //========================================================
6351 // DMA Register has a copy too.
6352 //========================================================
6353 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6354 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6355 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6357 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6358 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6359 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6362 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6363 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6364 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6366 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6368 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6371 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6372 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6373 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6374 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6375 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6378 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6379 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6380 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6383 // Tuning for Wi-Fi WMM S06
6384 if (pAd->CommonCfg.bWiFiTest &&
6385 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6386 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6388 // Tuning for TGn Wi-Fi 5.2.32
6389 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6390 if (STA_TGN_WIFI_ON(pAd) &&
6391 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6393 AifsnCsr.field.Aifsn0 = 3;
6394 AifsnCsr.field.Aifsn2 = 7;
6398 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6401 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6403 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6405 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6408 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6409 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6410 pEdcaParm->Aifsn[0],
6411 pEdcaParm->Cwmin[0],
6412 pEdcaParm->Cwmax[0],
6413 pEdcaParm->Txop[0]<<5,
6414 pEdcaParm->bACM[0]));
6415 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6416 pEdcaParm->Aifsn[1],
6417 pEdcaParm->Cwmin[1],
6418 pEdcaParm->Cwmax[1],
6419 pEdcaParm->Txop[1]<<5,
6420 pEdcaParm->bACM[1]));
6421 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6422 pEdcaParm->Aifsn[2],
6423 pEdcaParm->Cwmin[2],
6424 pEdcaParm->Cwmax[2],
6425 pEdcaParm->Txop[2]<<5,
6426 pEdcaParm->bACM[2]));
6427 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6428 pEdcaParm->Aifsn[3],
6429 pEdcaParm->Cwmin[3],
6430 pEdcaParm->Cwmax[3],
6431 pEdcaParm->Txop[3]<<5,
6432 pEdcaParm->bACM[3]));
6438 ==========================================================================
6441 IRQL = PASSIVE_LEVEL
6442 IRQL = DISPATCH_LEVEL
6444 ==========================================================================
6446 VOID AsicSetSlotTime(
6447 IN PRTMP_ADAPTER pAd,
6448 IN BOOLEAN bUseShortSlotTime)
6451 UINT32 RegValue = 0;
6453 if (pAd->CommonCfg.Channel > 14)
6454 bUseShortSlotTime = TRUE;
6456 if (bUseShortSlotTime)
6457 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6459 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6461 SlotTime = (bUseShortSlotTime)? 9 : 20;
6464 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6465 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6466 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6469 // In this case, we will think it is doing Wi-Fi test
6470 // And we will not set to short slot when bEnableTxBurst is TRUE.
6472 else if (pAd->CommonCfg.bEnableTxBurst)
6477 // For some reasons, always set it to short slot time.
6479 // ToDo: Should consider capability with 11B
6481 if (pAd->StaCfg.BssType == BSS_ADHOC)
6484 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6485 RegValue = RegValue & 0xFFFFFF00;
6487 RegValue |= SlotTime;
6489 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6493 ========================================================================
6495 Add Shared key information into ASIC.
6496 Update shared key, TxMic and RxMic to Asic Shared key table
6497 Update its cipherAlg to Asic Shared key Mode.
6500 ========================================================================
6502 VOID AsicAddSharedKeyEntry(
6503 IN PRTMP_ADAPTER pAd,
6511 ULONG offset; //, csr0;
6512 SHAREDKEY_MODE_STRUC csr1;
6514 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6515 //============================================================================================
6517 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6518 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6519 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]));
6522 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6523 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6527 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6528 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6530 //============================================================================================
6532 // fill key material - key + TX MIC + RX MIC
6537 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6538 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
6540 offset += MAX_LEN_OF_SHARE_KEY;
6543 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
6549 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
6555 // Update cipher algorithm. WSTA always use BSS0
6557 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6558 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6559 if ((BssIndex%2) == 0)
6562 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6563 else if (KeyIdx == 1)
6564 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6565 else if (KeyIdx == 2)
6566 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6568 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6573 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6574 else if (KeyIdx == 1)
6575 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6576 else if (KeyIdx == 2)
6577 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6579 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6581 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6582 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6586 // IRQL = DISPATCH_LEVEL
6587 VOID AsicRemoveSharedKeyEntry(
6588 IN PRTMP_ADAPTER pAd,
6593 SHAREDKEY_MODE_STRUC csr1;
6595 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6597 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6598 if ((BssIndex%2) == 0)
6601 csr1.field.Bss0Key0CipherAlg = 0;
6602 else if (KeyIdx == 1)
6603 csr1.field.Bss0Key1CipherAlg = 0;
6604 else if (KeyIdx == 2)
6605 csr1.field.Bss0Key2CipherAlg = 0;
6607 csr1.field.Bss0Key3CipherAlg = 0;
6612 csr1.field.Bss1Key0CipherAlg = 0;
6613 else if (KeyIdx == 1)
6614 csr1.field.Bss1Key1CipherAlg = 0;
6615 else if (KeyIdx == 2)
6616 csr1.field.Bss1Key2CipherAlg = 0;
6618 csr1.field.Bss1Key3CipherAlg = 0;
6620 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6621 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6622 ASSERT(BssIndex < 4);
6628 VOID AsicUpdateWCIDAttribute(
6629 IN PRTMP_ADAPTER pAd,
6633 IN BOOLEAN bUsePairewiseKeyTable)
6635 ULONG WCIDAttri = 0, offset;
6638 // Update WCID attribute.
6639 // Only TxKey could update WCID attribute.
6641 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6642 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6643 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6646 VOID AsicUpdateWCIDIVEIV(
6647 IN PRTMP_ADAPTER pAd,
6654 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6656 RTMP_IO_WRITE32(pAd, offset, uIV);
6657 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6660 VOID AsicUpdateRxWCIDTable(
6661 IN PRTMP_ADAPTER pAd,
6668 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6669 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6670 RTMP_IO_WRITE32(pAd, offset, Addr);
6671 Addr = pAddr[4] + (pAddr[5] << 8);
6672 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6677 ========================================================================
6679 Routine Description:
6680 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6683 pAd Pointer to our adapter
6684 WCID WCID Entry number.
6685 BssIndex BSSID index, station or none multiple BSSID support
6686 this value should be 0.
6687 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6688 pCipherKey Pointer to Cipher Key.
6689 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6690 otherwise PairewiseKey table
6691 bTxKey This is the transmit key if enabled.
6697 This routine will set the relative key stuff to Asic including WCID attribute,
6698 Cipher Key, Cipher algorithm and IV/EIV.
6700 IV/EIV will be update if this CipherKey is the transmission key because
6701 ASIC will base on IV's KeyID value to select Cipher Key.
6703 If bTxKey sets to FALSE, this is not the TX key, but it could be
6706 For AP mode bTxKey must be always set to TRUE.
6707 ========================================================================
6709 VOID AsicAddKeyEntry(
6710 IN PRTMP_ADAPTER pAd,
6714 IN PCIPHER_KEY pCipherKey,
6715 IN BOOLEAN bUsePairewiseKeyTable,
6720 PUCHAR pKey = pCipherKey->Key;
6721 PUCHAR pTxMic = pCipherKey->TxMic;
6722 PUCHAR pRxMic = pCipherKey->RxMic;
6723 PUCHAR pTxtsc = pCipherKey->TxTsc;
6724 UCHAR CipherAlg = pCipherKey->CipherAlg;
6725 SHAREDKEY_MODE_STRUC csr1;
6727 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
6729 // 1.) decide key table offset
6731 if (bUsePairewiseKeyTable)
6732 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6734 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
6737 // 2.) Set Key to Asic
6739 //for (i = 0; i < KeyLen; i++)
6742 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
6743 offset += MAX_LEN_OF_PEER_KEY;
6746 // 3.) Set MIC key if available
6750 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
6752 offset += LEN_TKIP_TXMICK;
6756 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
6761 // 4.) Modify IV/EIV if needs
6762 // This will force Asic to use this key ID by setting IV.
6773 IV4 = (KeyIdx << 6);
6774 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
6775 IV4 |= 0x20; // turn on extension bit means EIV existence
6777 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
6778 RTMP_IO_WRITE32(pAd, offset, tmpVal);
6784 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
6786 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
6789 if (!bUsePairewiseKeyTable)
6792 // Only update the shared key security mode
6794 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
6795 if ((BssIndex % 2) == 0)
6798 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6799 else if (KeyIdx == 1)
6800 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6801 else if (KeyIdx == 2)
6802 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6804 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6809 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6810 else if (KeyIdx == 1)
6811 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6812 else if (KeyIdx == 2)
6813 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6815 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6817 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
6820 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
6825 ========================================================================
6827 Add Pair-wise key material into ASIC.
6828 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
6831 ========================================================================
6833 VOID AsicAddPairwiseKeyEntry(
6834 IN PRTMP_ADAPTER pAd,
6837 IN CIPHER_KEY *pCipherKey)
6841 PUCHAR pKey = pCipherKey->Key;
6842 PUCHAR pTxMic = pCipherKey->TxMic;
6843 PUCHAR pRxMic = pCipherKey->RxMic;
6845 UCHAR CipherAlg = pCipherKey->CipherAlg;
6849 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6851 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
6853 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
6856 RTMP_IO_READ32(pAd, offset + i, &Value);
6859 offset += MAX_LEN_OF_PEER_KEY;
6865 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
6872 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
6876 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
6877 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6878 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]));
6881 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6882 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6886 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6887 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6891 ========================================================================
6893 Remove Pair-wise key material from ASIC.
6896 ========================================================================
6898 VOID AsicRemovePairwiseKeyEntry(
6899 IN PRTMP_ADAPTER pAd,
6906 // re-set the entry's WCID attribute as OPEN-NONE.
6907 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
6908 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
6909 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6912 BOOLEAN AsicSendCommandToMcu(
6913 IN PRTMP_ADAPTER pAd,
6919 HOST_CMD_CSR_STRUC H2MCmd;
6920 H2M_MAILBOX_STRUC H2MMailbox;
6924 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
6925 if (H2MMailbox.field.Owner == 0)
6934 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
6940 H2MMailbox.field.Owner = 1; // pass ownership to MCU
6941 H2MMailbox.field.CmdToken = Token;
6942 H2MMailbox.field.HighByte = Arg1;
6943 H2MMailbox.field.LowByte = Arg0;
6944 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
6947 H2MCmd.field.HostCommand = Command;
6948 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
6950 if (Command != 0x80)
6959 ========================================================================
6961 Routine Description:
6962 Verify the support rate for different PHY type
6965 pAd Pointer to our adapter
6970 IRQL = PASSIVE_LEVEL
6972 ========================================================================
6974 VOID RTMPCheckRates(
6975 IN PRTMP_ADAPTER pAd,
6976 IN OUT UCHAR SupRate[],
6977 IN OUT UCHAR *SupRateLen)
6979 UCHAR RateIdx, i, j;
6980 UCHAR NewRate[12], NewRateLen;
6984 if (pAd->CommonCfg.PhyMode == PHY_11B)
6989 // Check for support rates exclude basic rate bit
6990 for (i = 0; i < *SupRateLen; i++)
6991 for (j = 0; j < RateIdx; j++)
6992 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
6993 NewRate[NewRateLen++] = SupRate[i];
6995 *SupRateLen = NewRateLen;
6996 NdisMoveMemory(SupRate, NewRate, NewRateLen);
6999 BOOLEAN RTMPCheckChannel(
7000 IN PRTMP_ADAPTER pAd,
7001 IN UCHAR CentralChannel,
7005 UCHAR UpperChannel = 0, LowerChannel = 0;
7006 UCHAR NoEffectChannelinList = 0;
7008 // Find upper and lower channel according to 40MHz current operation.
7009 if (CentralChannel < Channel)
7011 UpperChannel = Channel;
7012 if (CentralChannel > 2)
7013 LowerChannel = CentralChannel - 2;
7017 else if (CentralChannel > Channel)
7019 UpperChannel = CentralChannel + 2;
7020 LowerChannel = Channel;
7023 for (k = 0;k < pAd->ChannelListNum;k++)
7025 if (pAd->ChannelList[k].Channel == UpperChannel)
7027 NoEffectChannelinList ++;
7029 if (pAd->ChannelList[k].Channel == LowerChannel)
7031 NoEffectChannelinList ++;
7035 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7036 if (NoEffectChannelinList == 2)
7043 ========================================================================
7045 Routine Description:
7046 Verify the support rate for HT phy type
7049 pAd Pointer to our adapter
7052 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7054 IRQL = PASSIVE_LEVEL
7056 ========================================================================
7058 BOOLEAN RTMPCheckHt(
7059 IN PRTMP_ADAPTER pAd,
7061 IN HT_CAPABILITY_IE *pHtCapability,
7062 IN ADD_HT_INFO_IE *pAddHtInfo)
7064 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7067 // If use AMSDU, set flag.
7068 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7069 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7070 // Save Peer Capability
7071 if (pHtCapability->HtCapInfo.ShortGIfor20)
7072 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7073 if (pHtCapability->HtCapInfo.ShortGIfor40)
7074 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7075 if (pHtCapability->HtCapInfo.TxSTBC)
7076 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7077 if (pHtCapability->HtCapInfo.RxSTBC)
7078 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7079 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7081 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7084 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7086 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7089 // Will check ChannelWidth for MCSSet[4] below
7090 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7091 switch (pAd->CommonCfg.RxStream)
7094 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7095 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7096 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7097 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7100 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7101 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7102 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7103 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7106 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7107 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7108 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7109 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7113 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7115 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7116 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7117 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7119 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7121 // Send Assoc Req with my HT capability.
7122 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7123 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7124 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7125 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7126 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7127 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7128 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7129 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7130 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7131 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7132 if (pAd->CommonCfg.bRdg)
7134 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7135 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7138 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7139 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7141 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7146 ========================================================================
7148 Routine Description:
7149 Verify the support rate for different PHY type
7152 pAd Pointer to our adapter
7157 IRQL = PASSIVE_LEVEL
7159 ========================================================================
7161 VOID RTMPUpdateMlmeRate(
7162 IN PRTMP_ADAPTER pAd)
7165 UCHAR ProperMlmeRate; //= RATE_54;
7166 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7167 BOOLEAN bMatch = FALSE;
7169 switch (pAd->CommonCfg.PhyMode)
7172 ProperMlmeRate = RATE_11;
7173 MinimumRate = RATE_1;
7175 case PHY_11BG_MIXED:
7176 case PHY_11ABGN_MIXED:
7177 case PHY_11BGN_MIXED:
7178 if ((pAd->MlmeAux.SupRateLen == 4) &&
7179 (pAd->MlmeAux.ExtRateLen == 0))
7181 ProperMlmeRate = RATE_11;
7183 ProperMlmeRate = RATE_24;
7185 if (pAd->MlmeAux.Channel <= 14)
7186 MinimumRate = RATE_1;
7188 MinimumRate = RATE_6;
7191 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7192 case PHY_11GN_MIXED:
7193 case PHY_11AGN_MIXED:
7194 case PHY_11AN_MIXED:
7196 ProperMlmeRate = RATE_24;
7197 MinimumRate = RATE_6;
7199 case PHY_11ABG_MIXED:
7200 ProperMlmeRate = RATE_24;
7201 if (pAd->MlmeAux.Channel <= 14)
7202 MinimumRate = RATE_1;
7204 MinimumRate = RATE_6;
7207 ProperMlmeRate = RATE_1;
7208 MinimumRate = RATE_1;
7212 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7214 for (j = 0; j < RateIdx; j++)
7216 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7218 if (j == ProperMlmeRate)
7230 if (bMatch == FALSE)
7232 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7234 for (j = 0; j < RateIdx; j++)
7236 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7238 if (j == ProperMlmeRate)
7251 if (bMatch == FALSE)
7253 ProperMlmeRate = MinimumRate;
7256 pAd->CommonCfg.MlmeRate = MinimumRate;
7257 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7258 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7260 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7261 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7262 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7263 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7267 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7268 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7269 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7270 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7273 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7277 IN PRTMP_ADAPTER pAd,
7284 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7289 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7291 larger = max(Rssi0, Rssi1);
7294 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7296 larger = max(larger, Rssi2);
7306 ========================================================================
7307 Routine Description:
7308 Periodic evaluate antenna link status
7311 pAd - Adapter pointer
7316 ========================================================================
7318 VOID AsicEvaluateRxAnt(
7319 IN PRTMP_ADAPTER pAd)
7324 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7325 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7326 fRTMP_ADAPTER_RADIO_OFF |
7327 fRTMP_ADAPTER_NIC_NOT_EXIST |
7328 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7331 if (pAd->StaCfg.Psm == PWR_SAVE)
7335 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7337 if(pAd->Antenna.field.RxPath == 3)
7341 else if(pAd->Antenna.field.RxPath == 2)
7345 else if(pAd->Antenna.field.RxPath == 1)
7349 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7351 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7354 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7355 pAd->RalinkCounters.OneSecTxRetryOkCount +
7356 pAd->RalinkCounters.OneSecTxFailCount;
7358 if (TxTotalCnt > 50)
7360 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7361 pAd->Mlme.bLowThroughput = FALSE;
7365 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7366 pAd->Mlme.bLowThroughput = TRUE;
7372 ========================================================================
7373 Routine Description:
7374 After evaluation, check antenna link status
7377 pAd - Adapter pointer
7382 ========================================================================
7384 VOID AsicRxAntEvalTimeout(
7385 IN PVOID SystemSpecific1,
7386 IN PVOID FunctionContext,
7387 IN PVOID SystemSpecific2,
7388 IN PVOID SystemSpecific3)
7390 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7392 CHAR larger = -127, rssi0, rssi1, rssi2;
7395 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7396 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7397 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7398 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7401 if (pAd->StaCfg.Psm == PWR_SAVE)
7405 // if the traffic is low, use average rssi as the criteria
7406 if (pAd->Mlme.bLowThroughput == TRUE)
7408 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7409 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7410 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7414 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7415 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7416 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7419 if(pAd->Antenna.field.RxPath == 3)
7421 larger = max(rssi0, rssi1);
7423 if (larger > (rssi2 + 20))
7424 pAd->Mlme.RealRxPath = 2;
7426 pAd->Mlme.RealRxPath = 3;
7428 else if(pAd->Antenna.field.RxPath == 2)
7430 if (rssi0 > (rssi1 + 20))
7431 pAd->Mlme.RealRxPath = 1;
7433 pAd->Mlme.RealRxPath = 2;
7436 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7438 if(pAd->Mlme.RealRxPath == 3)
7442 else if(pAd->Mlme.RealRxPath == 2)
7446 else if(pAd->Mlme.RealRxPath == 1)
7450 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7456 VOID APSDPeriodicExec(
7457 IN PVOID SystemSpecific1,
7458 IN PVOID FunctionContext,
7459 IN PVOID SystemSpecific2,
7460 IN PVOID SystemSpecific3)
7462 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7464 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7467 pAd->CommonCfg.TriggerTimerCount++;
7472 ========================================================================
7473 Routine Description:
7474 Set/reset MAC registers according to bPiggyBack parameter
7477 pAd - Adapter pointer
7478 bPiggyBack - Enable / Disable Piggy-Back
7483 ========================================================================
7485 VOID RTMPSetPiggyBack(
7486 IN PRTMP_ADAPTER pAd,
7487 IN BOOLEAN bPiggyBack)
7489 TX_LINK_CFG_STRUC TxLinkCfg;
7491 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7493 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7494 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7498 ========================================================================
7499 Routine Description:
7500 check if this entry need to switch rate automatically
7510 ========================================================================
7512 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7513 IN PRTMP_ADAPTER pAd,
7514 IN PMAC_TABLE_ENTRY pEntry)
7516 BOOLEAN result = TRUE;
7519 // only associated STA counts
7520 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7522 result = pAd->StaCfg.bAutoTxRateSwitch;
7532 BOOLEAN RTMPAutoRateSwitchCheck(
7533 IN PRTMP_ADAPTER pAd)
7535 if (pAd->StaCfg.bAutoTxRateSwitch)
7543 ========================================================================
7544 Routine Description:
7545 check if this entry need to fix tx legacy rate
7555 ========================================================================
7557 UCHAR RTMPStaFixedTxMode(
7558 IN PRTMP_ADAPTER pAd,
7559 IN PMAC_TABLE_ENTRY pEntry)
7561 UCHAR tx_mode = FIXED_TXMODE_HT;
7564 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7571 ========================================================================
7572 Routine Description:
7573 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
7583 ========================================================================
7585 VOID RTMPUpdateLegacyTxSetting(
7586 UCHAR fixed_tx_mode,
7587 PMAC_TABLE_ENTRY pEntry)
7589 HTTRANSMIT_SETTING TransmitSetting;
7591 if (fixed_tx_mode == FIXED_TXMODE_HT)
7594 TransmitSetting.word = 0;
7596 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
7597 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
7599 if (fixed_tx_mode == FIXED_TXMODE_CCK)
7601 TransmitSetting.field.MODE = MODE_CCK;
7602 // CCK mode allow MCS 0~3
7603 if (TransmitSetting.field.MCS > MCS_3)
7604 TransmitSetting.field.MCS = MCS_3;
7608 TransmitSetting.field.MODE = MODE_OFDM;
7609 // OFDM mode allow MCS 0~7
7610 if (TransmitSetting.field.MCS > MCS_7)
7611 TransmitSetting.field.MCS = MCS_7;
7614 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
7616 pEntry->HTPhyMode.word = TransmitSetting.word;
7617 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
7618 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
7623 ==========================================================================
7625 dynamic tune BBP R66 to find a balance between sensibility and
7628 IRQL = DISPATCH_LEVEL
7630 ==========================================================================
7632 VOID AsicStaBbpTuning(
7633 IN PRTMP_ADAPTER pAd)
7635 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
7638 // 2860C did not support Fase CCA, therefore can't tune
7639 if (pAd->MACVersion == 0x28600100)
7645 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
7648 if ((pAd->OpMode == OPMODE_STA)
7649 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7651 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
7654 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
7657 if (pAd->Antenna.field.RxPath > 1)
7658 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
7660 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
7662 if (pAd->LatchRfRegs.Channel <= 14)
7665 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
7666 // Otherwise, it will have some throughput side effect when low RSSI
7669 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7671 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
7672 if (OrigR66Value != R66)
7674 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
7679 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
7680 if (OrigR66Value != R66)
7682 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
7689 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7691 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
7692 if (OrigR66Value != R66)
7694 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7699 R66 = 0x2E + GET_LNA_GAIN(pAd);
7700 if (OrigR66Value != R66)
7702 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7709 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
7711 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7713 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
7714 if (OrigR66Value != R66)
7716 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7721 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
7722 if (OrigR66Value != R66)
7724 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7730 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7732 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
7733 if (OrigR66Value != R66)
7735 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7740 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
7741 if (OrigR66Value != R66)
7743 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7753 VOID RTMPSetAGCInitValue(
7754 IN PRTMP_ADAPTER pAd,
7759 if (pAd->LatchRfRegs.Channel <= 14)
7761 R66 = 0x2E + GET_LNA_GAIN(pAd);
7762 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7766 if (BandWidth == BW_20)
7768 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
7769 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7773 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
7774 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7780 VOID AsicTurnOffRFClk(
7781 IN PRTMP_ADAPTER pAd,
7786 UINT32 R1 = 0, R2 = 0, R3 = 0;
7788 RTMP_RF_REGS *RFRegTable;
7790 RFRegTable = RF2850RegTable;
7792 switch (pAd->RfIcType)
7799 for (index = 0; index < NUM_OF_2850_CHNL; index++)
7801 if (Channel == RFRegTable[index].Channel)
7803 R1 = RFRegTable[index].R1 & 0xffffdfff;
7804 R2 = RFRegTable[index].R2 & 0xfffbffff;
7805 R3 = RFRegTable[index].R3 & 0xfff3ffff;
7807 RTMP_RF_IO_WRITE32(pAd, R1);
7808 RTMP_RF_IO_WRITE32(pAd, R2);
7810 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
7811 // Set RF R2 bit18=0, R3 bit[18:19]=0
7812 //if (pAd->StaCfg.bRadio == FALSE)
7815 RTMP_RF_IO_WRITE32(pAd, R3);
7817 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
7818 Channel, pAd->RfIcType, R2, R3));
7821 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
7822 Channel, pAd->RfIcType, R2));
7834 VOID AsicTurnOnRFClk(
7835 IN PRTMP_ADAPTER pAd,
7840 UINT32 R1 = 0, R2 = 0, R3 = 0;
7842 RTMP_RF_REGS *RFRegTable;
7844 RFRegTable = RF2850RegTable;
7846 switch (pAd->RfIcType)
7853 for (index = 0; index < NUM_OF_2850_CHNL; index++)
7855 if (Channel == RFRegTable[index].Channel)
7857 R3 = pAd->LatchRfRegs.R3;
7860 RTMP_RF_IO_WRITE32(pAd, R3);
7862 R1 = RFRegTable[index].R1;
7863 RTMP_RF_IO_WRITE32(pAd, R1);
7865 R2 = RFRegTable[index].R2;
7866 if (pAd->Antenna.field.TxPath == 1)
7868 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
7871 if (pAd->Antenna.field.RxPath == 2)
7873 R2 |= 0x40; // write 1 to off Rxpath.
7875 else if (pAd->Antenna.field.RxPath == 1)
7877 R2 |= 0x20040; // write 1 to off RxPath
7879 RTMP_RF_IO_WRITE32(pAd, R2);
7890 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",