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;
342 extern UCHAR WPA_OUI[];
344 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
346 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
347 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
349 // Reset the RFIC setting to new series
350 RTMP_RF_REGS RF2850RegTable[] = {
351 // ch R1 R2 R3(TX0~4=0) R4
352 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
353 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
354 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
355 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
356 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
357 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
358 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
359 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
360 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
361 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
362 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
363 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
364 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
365 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
367 // 802.11 UNI / HyperLan 2
368 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
369 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
370 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
371 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
372 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
373 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
374 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
375 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
376 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
377 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
378 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
379 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
382 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
384 // 2008.04.30 modified
385 // The system team has AN to improve the EVM value
386 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
387 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
388 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
389 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
391 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
392 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
393 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
394 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
395 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
396 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
397 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
398 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
399 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
400 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
401 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
402 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
405 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
406 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
407 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
408 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
409 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
410 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
411 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
414 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
415 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
416 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
417 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
418 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
419 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
420 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
422 // still lack of MMAC(Japan) ch 34,38,42,46
424 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
426 FREQUENCY_ITEM FreqItems3020[] =
428 /**************************************************/
429 // ISM : 2.4 to 2.483 GHz //
430 /**************************************************/
432 /**************************************************/
433 //-CH---N-------R---K-----------
449 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
452 ==========================================================================
454 initialize the MLME task and its data structure (queue, spinlock,
455 timer, state machines).
460 always return NDIS_STATUS_SUCCESS
462 ==========================================================================
464 NDIS_STATUS MlmeInit(
465 IN PRTMP_ADAPTER pAd)
467 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
469 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
473 Status = MlmeQueueInit(&pAd->Mlme.Queue);
474 if(Status != NDIS_STATUS_SUCCESS)
477 pAd->Mlme.bRunning = FALSE;
478 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
480 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
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);
508 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
510 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
512 // only PCIe cards need these two timers
513 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
514 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
519 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
525 ==========================================================================
527 main loop of the MLME
529 Mlme has to be initialized, and there are something inside the queue
531 This function is invoked from MPSetInformation and MPReceive;
532 This task guarantee only one MlmeHandler will run.
534 IRQL = DISPATCH_LEVEL
536 ==========================================================================
539 IN PRTMP_ADAPTER pAd)
541 MLME_QUEUE_ELEM *Elem = NULL;
543 // Only accept MLME and Frame from peer side, no other (control/data) frame should
544 // get into this state machine
546 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
547 if(pAd->Mlme.bRunning)
549 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
554 pAd->Mlme.bRunning = TRUE;
556 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
558 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
560 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
561 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
562 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
564 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
568 //From message type, determine which state machine I should drive
569 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
572 // if dequeue success
573 switch (Elem->Machine)
575 // STA state machines
576 case ASSOC_STATE_MACHINE:
577 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
579 case AUTH_STATE_MACHINE:
580 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
582 case AUTH_RSP_STATE_MACHINE:
583 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
585 case SYNC_STATE_MACHINE:
586 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
588 case MLME_CNTL_STATE_MACHINE:
589 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
591 case WPA_PSK_STATE_MACHINE:
592 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
594 case AIRONET_STATE_MACHINE:
595 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
597 case ACTION_STATE_MACHINE:
598 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
605 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
610 Elem->Occupied = FALSE;
615 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
619 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
620 pAd->Mlme.bRunning = FALSE;
621 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
625 ==========================================================================
627 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
629 Adapter - NIC Adapter pointer
631 The MLME task will no longer work properly
635 ==========================================================================
638 IN PRTMP_ADAPTER pAd)
642 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
644 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
646 // disable BEACON generation and other BEACON related hardware timers
647 AsicDisableSync(pAd);
650 IF_DEV_CONFIG_OPMODE_ON_STA(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);
659 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
661 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
662 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
666 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
667 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
671 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
674 RTMPSetLED(pAd, LED_HALT);
675 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
678 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
680 MlmeQueueDestroy(&pAd->Mlme.Queue);
681 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
683 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
686 VOID MlmeResetRalinkCounters(
687 IN PRTMP_ADAPTER pAd)
689 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
690 // clear all OneSecxxx counters.
691 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
692 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
693 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
694 pAd->RalinkCounters.OneSecRxOkCnt = 0;
695 pAd->RalinkCounters.OneSecTxFailCount = 0;
696 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
697 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
698 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
700 // TODO: for debug only. to be removed
701 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
702 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
703 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
704 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
705 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
706 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
707 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
708 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
709 pAd->RalinkCounters.OneSecTxDoneCount = 0;
710 pAd->RalinkCounters.OneSecRxCount = 0;
711 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
712 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
717 unsigned long rx_AMSDU;
718 unsigned long rx_Total;
721 ==========================================================================
723 This routine is executed periodically to -
724 1. Decide if it's a right time to turn on PwrMgmt bit of all
726 2. Calculate ChannelQuality based on statistics of the last
727 period, so that TX rate won't toggling very frequently between a
728 successful TX and a failed TX.
729 3. If the calculated ChannelQuality indicated current connection not
730 healthy, then a ROAMing attempt is tried here.
732 IRQL = DISPATCH_LEVEL
734 ==========================================================================
736 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
737 VOID MlmePeriodicExec(
738 IN PVOID SystemSpecific1,
739 IN PVOID FunctionContext,
740 IN PVOID SystemSpecific2,
741 IN PVOID SystemSpecific3)
744 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
747 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
748 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
749 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
750 if(pAd->StaCfg.WepStatus<2)
752 pAd->StaCfg.WpaSupplicantUP = 0;
756 pAd->StaCfg.WpaSupplicantUP = 1;
759 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
761 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
762 // Move code to here, because following code will return when radio is off
763 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
764 (pAd->StaCfg.bHardwareRadio == TRUE) &&
765 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
766 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
767 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
771 // Read GPIO pin2 as Hardware controlled radio state
772 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
775 pAd->StaCfg.bHwRadio = TRUE;
779 pAd->StaCfg.bHwRadio = FALSE;
781 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
783 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
784 if (pAd->StaCfg.bRadio == TRUE)
787 // Update extra information
788 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
793 // Update extra information
794 pAd->ExtraInfo = HW_RADIO_OFF;
800 // Do nothing if the driver is starting halt state.
801 // This might happen when timer already been fired before cancel timer with mlmehalt
802 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
803 fRTMP_ADAPTER_RADIO_OFF |
804 fRTMP_ADAPTER_RADIO_MEASUREMENT |
805 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
808 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
810 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
812 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
813 pAd->SameRxByteCount++;
816 pAd->SameRxByteCount = 0;
818 // If after BBP, still not work...need to check to reset PBF&MAC.
819 if (pAd->SameRxByteCount == 702)
821 pAd->SameRxByteCount = 0;
826 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
827 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
829 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
831 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
832 pAd->SameRxByteCount = 700;
837 // Update lastReceiveByteCount.
838 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
840 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
842 pAd->CheckDmaBusyCount = 0;
843 AsicResetFromDMABusy(pAd);
847 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
849 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
851 // Do nothing if monitor mode is on
855 if (pAd->Mlme.PeriodicRound & 0x1)
857 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
858 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
859 (STA_TGN_WIFI_ON(pAd)) &&
860 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
863 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
864 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
866 else if ((STA_TGN_WIFI_ON(pAd)) &&
867 ((pAd->MACVersion & 0xffff) == 0x0101))
869 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
870 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
875 pAd->bUpdateBcnCntDone = FALSE;
877 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
878 pAd->Mlme.PeriodicRound ++;
880 // execute every 500ms
881 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
883 // perform dynamic tx rate switching based on past TX history
884 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
886 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
888 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
889 MlmeDynamicTxRateSwitching(pAd);
893 // Normal 1 second Mlme PeriodicExec.
894 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
896 pAd->Mlme.OneSecPeriodicRound ++;
906 // Media status changed, report to NDIS
907 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
909 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
910 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
912 pAd->IndicateMediaState = NdisMediaStateConnected;
913 RTMP_IndicateMediaState(pAd);
918 pAd->IndicateMediaState = NdisMediaStateDisconnected;
919 RTMP_IndicateMediaState(pAd);
923 NdisGetSystemUpTime(&pAd->Mlme.Now32);
925 // add the most up-to-date h/w raw counters into software variable, so that
926 // the dynamic tuning mechanism below are based on most up-to-date information
927 NICUpdateRawCounters(pAd);
929 // Need statistics after read counter. So put after NICUpdateRawCounters
930 ORIBATimerTimeout(pAd);
932 // The time period for checking antenna is according to traffic
933 if (pAd->Mlme.bEnableAutoAntennaCheck)
935 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
936 pAd->RalinkCounters.OneSecTxRetryOkCount +
937 pAd->RalinkCounters.OneSecTxFailCount;
941 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
943 AsicEvaluateRxAnt(pAd);
948 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
950 AsicEvaluateRxAnt(pAd);
955 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
956 STAMlmePeriodicExec(pAd);
958 MlmeResetRalinkCounters(pAd);
960 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
962 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
964 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
965 // and sending CTS-to-self over and over.
966 // Software Patch Solution:
967 // 1. Polling debug state register 0x10F4 every one second.
968 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
969 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
973 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
974 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
976 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
978 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
980 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
985 RT28XX_MLME_HANDLER(pAd);
989 pAd->bUpdateBcnCntDone = FALSE;
992 VOID STAMlmePeriodicExec(
997 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
999 // WPA MIC error should block association attempt for 60 seconds
1000 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1001 pAd->StaCfg.bBlockAssoc = FALSE;
1005 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1006 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1007 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1008 if(pAd->StaCfg.WepStatus<2)
1010 pAd->StaCfg.WpaSupplicantUP = 0;
1014 pAd->StaCfg.WpaSupplicantUP = 1;
1017 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1019 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1021 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1023 pAd->PreMediaState = pAd->IndicateMediaState;
1026 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1027 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1028 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1029 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1030 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1031 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1033 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1038 AsicStaBbpTuning(pAd);
1040 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1041 pAd->RalinkCounters.OneSecTxRetryOkCount +
1042 pAd->RalinkCounters.OneSecTxFailCount;
1044 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1046 // update channel quality for Roaming and UI LinkQuality display
1047 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1050 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1051 // Radio is currently in noisy environment
1052 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1053 AsicAdjustTxPower(pAd);
1057 // Is PSM bit consistent with user power management policy?
1058 // This is the only place that will set PSM bit ON.
1059 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1060 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1062 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1064 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1065 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1066 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1068 RTMPSetAGCInitValue(pAd, BW_20);
1069 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1073 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1075 // When APSD is enabled, the period changes as 20 sec
1076 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1077 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1081 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1082 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1084 if (pAd->CommonCfg.bWmmCapable)
1085 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1087 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1092 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1094 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1095 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1096 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1098 // Lost AP, send disconnect & link down event
1099 LinkDown(pAd, FALSE);
1102 union iwreq_data wrqu;
1103 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1104 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1107 MlmeAutoReconnectLastSSID(pAd);
1109 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1111 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1112 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1113 MlmeAutoReconnectLastSSID(pAd);
1116 // Add auto seamless roaming
1117 if (pAd->StaCfg.bFastRoaming)
1119 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1121 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));
1123 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1125 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1129 else if (ADHOC_ON(pAd))
1131 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1132 // the "TX BEACON competition" for the entire past 1 sec.
1133 // So that even when ASIC's BEACONgen engine been blocked
1134 // by peer's BEACON due to slower system clock, this STA still can send out
1135 // minimum BEACON to tell the peer I'm alive.
1136 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1137 // EnqueueBeaconFrame(pAd); // software send BEACON
1139 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1140 // restore outgoing BEACON to support B/G-mixed mode
1141 if ((pAd->CommonCfg.Channel <= 14) &&
1142 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1143 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1144 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1146 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1147 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1148 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1149 MlmeUpdateTxRates(pAd, FALSE, 0);
1150 MakeIbssBeacon(pAd); // re-build BEACON frame
1151 AsicEnableIbssSync(pAd); // copy to on-chip memory
1152 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1155 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1157 if ((pAd->StaCfg.AdhocBGJoined) &&
1158 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1160 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1161 pAd->StaCfg.AdhocBGJoined = FALSE;
1164 if ((pAd->StaCfg.Adhoc20NJoined) &&
1165 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1167 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1168 pAd->StaCfg.Adhoc20NJoined = FALSE;
1173 if ((pAd->CommonCfg.Channel > 14)
1174 && (pAd->CommonCfg.bIEEE80211H == 1)
1175 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1177 RadarDetectPeriodic(pAd);
1180 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1181 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1183 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1184 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1186 MLME_START_REQ_STRUCT StartReq;
1188 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1189 LinkDown(pAd, FALSE);
1191 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1192 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1193 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1196 else // no INFRA nor ADHOC connection
1199 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1200 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1201 goto SKIP_AUTO_SCAN_CONN;
1203 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1205 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1206 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1207 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1209 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1211 MLME_SCAN_REQ_STRUCT ScanReq;
1213 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1215 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1216 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1217 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1218 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1219 // Reset Missed scan number
1220 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1222 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1223 MlmeAutoReconnectLastSSID(pAd);
1225 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1227 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1230 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1234 MlmeAutoReconnectLastSSID(pAd);
1240 SKIP_AUTO_SCAN_CONN:
1242 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1244 pAd->MacTab.fAnyBASession = TRUE;
1245 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1247 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1249 pAd->MacTab.fAnyBASession = FALSE;
1250 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1258 IN PVOID SystemSpecific1,
1259 IN PVOID FunctionContext,
1260 IN PVOID SystemSpecific2,
1261 IN PVOID SystemSpecific3)
1264 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1266 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1267 RTMP_IndicateMediaState(pAd);
1268 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1271 // IRQL = DISPATCH_LEVEL
1273 IN PRTMP_ADAPTER pAd)
1275 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1276 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1278 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1280 MLME_CNTL_STATE_MACHINE,
1281 OID_802_11_BSSID_LIST_SCAN,
1284 RT28XX_MLME_HANDLER(pAd);
1288 // IRQL = DISPATCH_LEVEL
1289 VOID MlmeAutoReconnectLastSSID(
1290 IN PRTMP_ADAPTER pAd)
1294 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1295 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1296 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1298 NDIS_802_11_SSID OidSsid;
1299 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1300 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1302 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1304 MLME_CNTL_STATE_MACHINE,
1306 sizeof(NDIS_802_11_SSID),
1308 RT28XX_MLME_HANDLER(pAd);
1313 ==========================================================================
1314 Validate SSID for connection try and rescan purpose
1315 Valid SSID will have visible chars only.
1316 The valid length is from 0 to 32.
1317 IRQL = DISPATCH_LEVEL
1318 ==========================================================================
1320 BOOLEAN MlmeValidateSSID(
1326 if (SsidLen > MAX_LEN_OF_SSID)
1329 // Check each character value
1330 for (index = 0; index < SsidLen; index++)
1332 if (pSsid[index] < 0x20)
1340 VOID MlmeSelectTxRateTable(
1341 IN PRTMP_ADAPTER pAd,
1342 IN PMAC_TABLE_ENTRY pEntry,
1344 IN PUCHAR pTableSize,
1345 IN PUCHAR pInitTxRateIdx)
1349 // decide the rate table for tuning
1350 if (pAd->CommonCfg.TxRateTableSize > 0)
1352 *ppTable = RateSwitchTable;
1353 *pTableSize = RateSwitchTable[0];
1354 *pInitTxRateIdx = RateSwitchTable[1];
1359 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1361 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1362 !pAd->StaCfg.AdhocBOnlyJoined &&
1363 !pAd->StaCfg.AdhocBGJoined &&
1364 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1365 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1367 *ppTable = RateSwitchTable11N1S;
1368 *pTableSize = RateSwitchTable11N1S[0];
1369 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1372 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1373 !pAd->StaCfg.AdhocBOnlyJoined &&
1374 !pAd->StaCfg.AdhocBGJoined &&
1375 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1376 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1377 (pAd->Antenna.field.TxPath == 2))
1379 if (pAd->LatchRfRegs.Channel <= 14)
1381 *ppTable = RateSwitchTable11N2S;
1382 *pTableSize = RateSwitchTable11N2S[0];
1383 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1387 *ppTable = RateSwitchTable11N2SForABand;
1388 *pTableSize = RateSwitchTable11N2SForABand[0];
1389 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1394 if (pAd->CommonCfg.PhyMode == PHY_11B)
1396 *ppTable = RateSwitchTable11B;
1397 *pTableSize = RateSwitchTable11B[0];
1398 *pInitTxRateIdx = RateSwitchTable11B[1];
1401 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1403 // USe B Table when Only b-only Station in my IBSS .
1404 *ppTable = RateSwitchTable11B;
1405 *pTableSize = RateSwitchTable11B[0];
1406 *pInitTxRateIdx = RateSwitchTable11B[1];
1409 else if (pAd->LatchRfRegs.Channel <= 14)
1411 *ppTable = RateSwitchTable11BG;
1412 *pTableSize = RateSwitchTable11BG[0];
1413 *pInitTxRateIdx = RateSwitchTable11BG[1];
1418 *ppTable = RateSwitchTable11G;
1419 *pTableSize = RateSwitchTable11G[0];
1420 *pInitTxRateIdx = RateSwitchTable11G[1];
1426 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1427 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1429 *ppTable = RateSwitchTable11BGN1S;
1430 *pTableSize = RateSwitchTable11BGN1S[0];
1431 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1436 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1437 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1439 if (pAd->LatchRfRegs.Channel <= 14)
1441 *ppTable = RateSwitchTable11BGN2S;
1442 *pTableSize = RateSwitchTable11BGN2S[0];
1443 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1448 *ppTable = RateSwitchTable11BGN2SForABand;
1449 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1450 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1456 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1458 *ppTable = RateSwitchTable11N1S;
1459 *pTableSize = RateSwitchTable11N1S[0];
1460 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1465 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1467 if (pAd->LatchRfRegs.Channel <= 14)
1469 *ppTable = RateSwitchTable11N2S;
1470 *pTableSize = RateSwitchTable11N2S[0];
1471 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1475 *ppTable = RateSwitchTable11N2SForABand;
1476 *pTableSize = RateSwitchTable11N2SForABand[0];
1477 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1483 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1484 if ((pEntry->RateLen == 4)
1485 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1488 *ppTable = RateSwitchTable11B;
1489 *pTableSize = RateSwitchTable11B[0];
1490 *pInitTxRateIdx = RateSwitchTable11B[1];
1495 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1496 if ((pEntry->RateLen > 8)
1497 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1500 *ppTable = RateSwitchTable11BG;
1501 *pTableSize = RateSwitchTable11BG[0];
1502 *pInitTxRateIdx = RateSwitchTable11BG[1];
1507 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1508 if ((pEntry->RateLen == 8)
1509 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1512 *ppTable = RateSwitchTable11G;
1513 *pTableSize = RateSwitchTable11G[0];
1514 *pInitTxRateIdx = RateSwitchTable11G[1];
1519 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1521 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1522 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1524 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1526 *ppTable = RateSwitchTable11B;
1527 *pTableSize = RateSwitchTable11B[0];
1528 *pInitTxRateIdx = RateSwitchTable11B[1];
1530 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1532 *ppTable = RateSwitchTable11G;
1533 *pTableSize = RateSwitchTable11G[0];
1534 *pInitTxRateIdx = RateSwitchTable11G[1];
1539 *ppTable = RateSwitchTable11BG;
1540 *pTableSize = RateSwitchTable11BG[0];
1541 *pInitTxRateIdx = RateSwitchTable11BG[1];
1546 if (pAd->LatchRfRegs.Channel <= 14)
1548 if (pAd->CommonCfg.TxStream == 1)
1550 *ppTable = RateSwitchTable11N1S;
1551 *pTableSize = RateSwitchTable11N1S[0];
1552 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1553 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1557 *ppTable = RateSwitchTable11N2S;
1558 *pTableSize = RateSwitchTable11N2S[0];
1559 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1560 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1565 if (pAd->CommonCfg.TxStream == 1)
1567 *ppTable = RateSwitchTable11N1S;
1568 *pTableSize = RateSwitchTable11N1S[0];
1569 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1570 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1574 *ppTable = RateSwitchTable11N2SForABand;
1575 *pTableSize = RateSwitchTable11N2SForABand[0];
1576 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1577 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1581 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1582 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1588 ==========================================================================
1590 This routine checks if there're other APs out there capable for
1591 roaming. Caller should call this routine only when Link up in INFRA mode
1592 and channel quality is below CQI_GOOD_THRESHOLD.
1594 IRQL = DISPATCH_LEVEL
1597 ==========================================================================
1599 VOID MlmeCheckForRoaming(
1600 IN PRTMP_ADAPTER pAd,
1604 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1607 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1608 // put all roaming candidates into RoamTab, and sort in RSSI order
1609 BssTableInit(pRoamTab);
1610 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1612 pBss = &pAd->ScanTab.BssEntry[i];
1614 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1615 continue; // AP disappear
1616 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1617 continue; // RSSI too weak. forget it.
1618 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1619 continue; // skip current AP
1620 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1621 continue; // only AP with stronger RSSI is eligible for roaming
1623 // AP passing all above rules is put into roaming candidate table
1624 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1625 pRoamTab->BssNr += 1;
1628 if (pRoamTab->BssNr > 0)
1630 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1631 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1633 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1634 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1635 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1636 RT28XX_MLME_HANDLER(pAd);
1639 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1643 ==========================================================================
1645 This routine checks if there're other APs out there capable for
1646 roaming. Caller should call this routine only when link up in INFRA mode
1647 and channel quality is below CQI_GOOD_THRESHOLD.
1649 IRQL = DISPATCH_LEVEL
1652 ==========================================================================
1654 VOID MlmeCheckForFastRoaming(
1655 IN PRTMP_ADAPTER pAd,
1659 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1662 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1663 // put all roaming candidates into RoamTab, and sort in RSSI order
1664 BssTableInit(pRoamTab);
1665 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1667 pBss = &pAd->ScanTab.BssEntry[i];
1669 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1670 continue; // RSSI too weak. forget it.
1671 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1672 continue; // skip current AP
1673 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1674 continue; // skip different SSID
1675 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1676 continue; // skip AP without better RSSI
1678 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));
1679 // AP passing all above rules is put into roaming candidate table
1680 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1681 pRoamTab->BssNr += 1;
1684 if (pRoamTab->BssNr > 0)
1686 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1687 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1689 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1690 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1691 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1692 RT28XX_MLME_HANDLER(pAd);
1695 // Maybe site survey required
1698 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1700 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1701 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1702 pAd->StaCfg.ScanCnt = 2;
1703 pAd->StaCfg.LastScanTime = Now;
1708 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1712 ==========================================================================
1714 This routine calculates TxPER, RxPER of the past N-sec period. And
1715 according to the calculation result, ChannelQuality is calculated here
1716 to decide if current AP is still doing the job.
1718 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1720 StaCfg.ChannelQuality - 0..100
1722 IRQL = DISPATCH_LEVEL
1724 NOTE: This routine decide channle quality based on RX CRC error ratio.
1725 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1726 is performed right before this routine, so that this routine can decide
1727 channel quality based on the most up-to-date information
1728 ==========================================================================
1730 VOID MlmeCalculateChannelQuality(
1731 IN PRTMP_ADAPTER pAd,
1734 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1738 ULONG BeaconLostTime = BEACON_LOST_TIME;
1740 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1743 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1745 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1746 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1754 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1755 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1759 // calculate RX PER - don't take RxPER into consideration if too few sample
1761 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1765 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1768 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1770 if (INFRA_ON(pAd) &&
1771 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1772 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1774 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1775 pAd->Mlme.ChannelQuality = 0;
1782 else if (MaxRssi < -90)
1785 NorRssi = (MaxRssi + 90) * 2;
1787 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1788 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1789 TX_WEIGHTING * (100 - TxPRR) +
1790 RX_WEIGHTING* (100 - RxPER)) / 100;
1791 if (pAd->Mlme.ChannelQuality >= 100)
1792 pAd->Mlme.ChannelQuality = 100;
1798 IN PRTMP_ADAPTER pAd,
1799 IN PMAC_TABLE_ENTRY pEntry,
1800 IN PRTMP_TX_RATE_SWITCH pTxRate)
1802 UCHAR MaxMode = MODE_OFDM;
1804 MaxMode = MODE_HTGREENFIELD;
1806 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1807 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1809 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1811 if (pTxRate->CurrMCS < MCS_AUTO)
1812 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1814 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1815 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1819 // If peer adhoc is b-only mode, we can't send 11g rate.
1820 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1821 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1824 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1826 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1827 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1828 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1830 // Patch speed error in status page
1831 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1835 if (pTxRate->Mode <= MaxMode)
1836 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1838 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1839 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1841 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1843 // Reexam each bandwidth's SGI support.
1844 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1846 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1847 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1848 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1849 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1852 // Turn RTS/CTS rate to 6Mbps.
1853 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1855 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1856 if (pAd->MacTab.fAnyBASession)
1858 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1862 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1865 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1867 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1868 if (pAd->MacTab.fAnyBASession)
1870 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1874 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1877 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1879 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1882 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1884 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1887 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1888 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1889 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1890 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1892 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1893 pAd->WIFItestbed.bGreenField)
1894 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1897 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1901 ==========================================================================
1903 This routine calculates the acumulated TxPER of eaxh TxRate. And
1904 according to the calculation result, change CommonCfg.TxRate which
1905 is the stable TX Rate we expect the Radio situation could sustained.
1907 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1911 IRQL = DISPATCH_LEVEL
1914 call this routine every second
1915 ==========================================================================
1917 VOID MlmeDynamicTxRateSwitching(
1918 IN PRTMP_ADAPTER pAd)
1920 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1921 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1922 ULONG TxErrorRatio = 0;
1923 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1924 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1926 UCHAR TableSize = 0;
1927 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1928 CHAR Rssi, RssiOffset = 0;
1929 TX_STA_CNT1_STRUC StaTx1;
1930 TX_STA_CNT0_STRUC TxStaCnt0;
1931 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1932 MAC_TABLE_ENTRY *pEntry;
1934 /*if (pAd->Antenna.field.RxPath > 1)
1935 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
1937 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
1940 // walk through MAC table, see if need to change AP's TX rate toward each entry
1942 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1944 pEntry = &pAd->MacTab.Content[i];
1946 // check if this entry need to switch rate automatically
1947 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1950 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1952 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
1954 // Update statistic counter
1955 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1956 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1957 pAd->bUpdateBcnCntDone = TRUE;
1958 TxRetransmit = StaTx1.field.TxRetransmit;
1959 TxSuccess = StaTx1.field.TxSuccess;
1960 TxFailCount = TxStaCnt0.field.TxFailCount;
1961 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1963 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1964 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1965 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1966 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1967 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1968 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1970 // if no traffic in the past 1-sec period, don't change TX rate,
1971 // but clear all bad history. because the bad history may affect the next
1972 // Chariot throughput test
1973 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1974 pAd->RalinkCounters.OneSecTxRetryOkCount +
1975 pAd->RalinkCounters.OneSecTxFailCount;
1978 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1982 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
1984 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1985 pEntry->OneSecTxRetryOkCount +
1986 pEntry->OneSecTxFailCount;
1989 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1992 CurrRateIdx = pEntry->CurrTxRateIndex;
1994 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1996 if (CurrRateIdx >= TableSize)
1998 CurrRateIdx = TableSize - 1;
2001 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2002 // So need to sync here.
2003 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2004 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2005 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2009 // Need to sync Real Tx rate and our record.
2010 // Then return for next DRS.
2011 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2012 pEntry->CurrTxRateIndex = InitTxRateIdx;
2013 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2015 // reset all OneSecTx counters
2016 RESET_ONE_SEC_TX_CNT(pEntry);
2020 // decide the next upgrade rate and downgrade rate, if any
2021 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2023 UpRateIdx = CurrRateIdx + 1;
2024 DownRateIdx = CurrRateIdx -1;
2026 else if (CurrRateIdx == 0)
2028 UpRateIdx = CurrRateIdx + 1;
2029 DownRateIdx = CurrRateIdx;
2031 else if (CurrRateIdx == (TableSize - 1))
2033 UpRateIdx = CurrRateIdx;
2034 DownRateIdx = CurrRateIdx - 1;
2037 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2039 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2041 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2042 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2046 TrainUp = pCurrTxRate->TrainUp;
2047 TrainDown = pCurrTxRate->TrainDown;
2050 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2053 // Keep the last time TxRateChangeAction status.
2055 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2060 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2061 // (criteria copied from RT2500 for Netopia case)
2063 if (TxTotalCnt <= 15)
2067 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2068 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2069 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2070 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2072 // check the existence and index of each needed MCS
2073 while (idx < pTable[0])
2075 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2077 if (pCurrTxRate->CurrMCS == MCS_0)
2081 else if (pCurrTxRate->CurrMCS == MCS_1)
2085 else if (pCurrTxRate->CurrMCS == MCS_2)
2089 else if (pCurrTxRate->CurrMCS == MCS_3)
2093 else if (pCurrTxRate->CurrMCS == MCS_4)
2097 else if (pCurrTxRate->CurrMCS == MCS_5)
2101 else if (pCurrTxRate->CurrMCS == MCS_6)
2105 //else if (pCurrTxRate->CurrMCS == MCS_7)
2106 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2110 else if (pCurrTxRate->CurrMCS == MCS_12)
2114 else if (pCurrTxRate->CurrMCS == MCS_13)
2118 else if (pCurrTxRate->CurrMCS == MCS_14)
2122 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2123 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
2127 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2131 else if (pCurrTxRate->CurrMCS == MCS_21)
2135 else if (pCurrTxRate->CurrMCS == MCS_22)
2139 else if (pCurrTxRate->CurrMCS == MCS_23)
2146 if (pAd->LatchRfRegs.Channel <= 14)
2148 if (pAd->NicConfig2.field.ExternalLNAForG)
2159 if (pAd->NicConfig2.field.ExternalLNAForA)
2170 if ((pTable == RateSwitchTable11BGN3S) ||
2171 (pTable == RateSwitchTable11N3S) ||
2172 (pTable == RateSwitchTable))
2173 {// N mode with 3 stream // 3*3
2174 if (MCS23 && (Rssi >= -70))
2176 else if (MCS22 && (Rssi >= -72))
2178 else if (MCS21 && (Rssi >= -76))
2180 else if (MCS20 && (Rssi >= -78))
2182 else if (MCS4 && (Rssi >= -82))
2184 else if (MCS3 && (Rssi >= -84))
2186 else if (MCS2 && (Rssi >= -86))
2188 else if (MCS1 && (Rssi >= -88))
2193 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2194 {// N mode with 2 stream
2195 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2197 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2199 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2201 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2203 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2205 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2207 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2209 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2214 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2215 {// N mode with 1 stream
2216 if (MCS7 && (Rssi > (-72+RssiOffset)))
2218 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2220 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2222 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2224 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2226 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2228 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2235 if (MCS7 && (Rssi > -70))
2237 else if (MCS6 && (Rssi > -74))
2239 else if (MCS5 && (Rssi > -78))
2241 else if (MCS4 && (Rssi > -82))
2243 else if (MCS4 == 0) // for B-only mode
2245 else if (MCS3 && (Rssi > -85))
2247 else if (MCS2 && (Rssi > -87))
2249 else if (MCS1 && (Rssi > -90))
2256 pEntry->CurrTxRateIndex = TxRateIdx;
2257 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2258 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2261 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2262 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2263 pEntry->fLastSecAccordingRSSI = TRUE;
2264 // reset all OneSecTx counters
2265 RESET_ONE_SEC_TX_CNT(pEntry);
2270 if (pEntry->fLastSecAccordingRSSI == TRUE)
2272 pEntry->fLastSecAccordingRSSI = FALSE;
2273 pEntry->LastSecTxRateChangeAction = 0;
2274 // reset all OneSecTx counters
2275 RESET_ONE_SEC_TX_CNT(pEntry);
2282 BOOLEAN bTrainUpDown = FALSE;
2284 pEntry->CurrTxRateStableTime ++;
2286 // downgrade TX quality if PER >= Rate-Down threshold
2287 if (TxErrorRatio >= TrainDown)
2289 bTrainUpDown = TRUE;
2290 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2292 // upgrade TX quality if PER <= Rate-Up threshold
2293 else if (TxErrorRatio <= TrainUp)
2295 bTrainUpDown = TRUE;
2296 bUpgradeQuality = TRUE;
2297 if (pEntry->TxQuality[CurrRateIdx])
2298 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2300 if (pEntry->TxRateUpPenalty)
2301 pEntry->TxRateUpPenalty --;
2302 else if (pEntry->TxQuality[UpRateIdx])
2303 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2306 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2310 // perform DRS - consider TxRate Down first, then rate up.
2311 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2313 pEntry->CurrTxRateIndex = DownRateIdx;
2315 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2317 pEntry->CurrTxRateIndex = UpRateIdx;
2322 // if rate-up happen, clear all bad history of all TX rates
2323 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2325 pEntry->CurrTxRateStableTime = 0;
2326 pEntry->TxRateUpPenalty = 0;
2327 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2328 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2329 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2332 // For TxRate fast train up
2334 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2336 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2338 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2340 bTxRateChanged = TRUE;
2342 // if rate-down happen, only clear DownRate's bad history
2343 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2345 pEntry->CurrTxRateStableTime = 0;
2346 pEntry->TxRateUpPenalty = 0; // no penalty
2347 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2348 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2349 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2352 // For TxRate fast train down
2354 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2356 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2358 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2360 bTxRateChanged = TRUE;
2364 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2365 bTxRateChanged = FALSE;
2368 pEntry->LastTxOkCount = TxSuccess;
2370 // reset all OneSecTx counters
2371 RESET_ONE_SEC_TX_CNT(pEntry);
2373 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2374 if (bTxRateChanged && pNextTxRate)
2376 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2382 ========================================================================
2383 Routine Description:
2384 Station side, Auto TxRate faster train up timer call back function.
2387 SystemSpecific1 - Not used.
2388 FunctionContext - Pointer to our Adapter context.
2389 SystemSpecific2 - Not used.
2390 SystemSpecific3 - Not used.
2395 ========================================================================
2397 VOID StaQuickResponeForRateUpExec(
2398 IN PVOID SystemSpecific1,
2399 IN PVOID FunctionContext,
2400 IN PVOID SystemSpecific2,
2401 IN PVOID SystemSpecific3)
2403 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2404 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2406 ULONG TxErrorRatio = 0;
2407 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2408 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2410 UCHAR TableSize = 0;
2411 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2412 TX_STA_CNT1_STRUC StaTx1;
2413 TX_STA_CNT0_STRUC TxStaCnt0;
2415 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2416 MAC_TABLE_ENTRY *pEntry;
2419 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2422 // walk through MAC table, see if need to change AP's TX rate toward each entry
2424 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2426 pEntry = &pAd->MacTab.Content[i];
2428 // check if this entry need to switch rate automatically
2429 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2432 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2433 if (pAd->Antenna.field.TxPath > 1)
2434 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2436 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2438 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2440 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2442 // decide the next upgrade rate and downgrade rate, if any
2443 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2445 UpRateIdx = CurrRateIdx + 1;
2446 DownRateIdx = CurrRateIdx -1;
2448 else if (CurrRateIdx == 0)
2450 UpRateIdx = CurrRateIdx + 1;
2451 DownRateIdx = CurrRateIdx;
2453 else if (CurrRateIdx == (TableSize - 1))
2455 UpRateIdx = CurrRateIdx;
2456 DownRateIdx = CurrRateIdx - 1;
2459 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2461 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2463 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2464 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2468 TrainUp = pCurrTxRate->TrainUp;
2469 TrainDown = pCurrTxRate->TrainDown;
2472 if (pAd->MacTab.Size == 1)
2474 // Update statistic counter
2475 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2476 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2478 TxRetransmit = StaTx1.field.TxRetransmit;
2479 TxSuccess = StaTx1.field.TxSuccess;
2480 TxFailCount = TxStaCnt0.field.TxFailCount;
2481 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2483 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2484 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2485 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2486 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2487 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2488 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2491 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2495 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2496 pEntry->OneSecTxRetryOkCount +
2497 pEntry->OneSecTxFailCount;
2500 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2505 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2506 // (criteria copied from RT2500 for Netopia case)
2508 if (TxTotalCnt <= 12)
2510 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2511 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2513 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2515 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2516 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2518 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2520 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2523 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2529 ULONG OneSecTxNoRetryOKRationCount;
2531 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2536 // downgrade TX quality if PER >= Rate-Down threshold
2537 if (TxErrorRatio >= TrainDown)
2539 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2542 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2544 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2546 // perform DRS - consider TxRate Down first, then rate up.
2547 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2549 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2551 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2552 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2557 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2559 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2563 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2565 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2570 // if rate-up happen, clear all bad history of all TX rates
2571 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2573 pAd->DrsCounters.TxRateUpPenalty = 0;
2574 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2575 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2577 // if rate-down happen, only clear DownRate's bad history
2578 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2580 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2582 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2583 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2584 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2588 bTxRateChanged = FALSE;
2591 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2592 if (bTxRateChanged && pNextTxRate)
2594 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2600 ==========================================================================
2602 This routine is executed periodically inside MlmePeriodicExec() after
2603 association with an AP.
2604 It checks if StaCfg.Psm is consistent with user policy (recorded in
2605 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2606 there're some conditions to consider:
2607 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2608 the time when Mibss==TRUE
2609 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2610 if outgoing traffic available in TxRing or MgmtRing.
2612 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2614 IRQL = DISPATCH_LEVEL
2616 ==========================================================================
2618 VOID MlmeCheckPsmChange(
2619 IN PRTMP_ADAPTER pAd,
2625 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2626 // 2. user wants either MAX_PSP or FAST_PSP
2627 // 3. but current psm is not in PWR_SAVE
2628 // 4. CNTL state machine is not doing SCANning
2629 // 5. no TX SUCCESS event for the past 1-sec period
2630 #ifdef NDIS51_MINIPORT
2631 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2632 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2635 PowerMode = pAd->StaCfg.WindowsPowerMode;
2637 if (INFRA_ON(pAd) &&
2638 (PowerMode != Ndis802_11PowerModeCAM) &&
2639 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2640 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2642 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2643 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2644 MlmeSetPsmBit(pAd, PWR_SAVE);
2645 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2647 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2651 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2656 // IRQL = PASSIVE_LEVEL
2657 // IRQL = DISPATCH_LEVEL
2659 IN PRTMP_ADAPTER pAd,
2662 AUTO_RSP_CFG_STRUC csr4;
2664 pAd->StaCfg.Psm = psm;
2665 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2666 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2667 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2668 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2671 // IRQL = DISPATCH_LEVEL
2672 VOID MlmeSetTxPreamble(
2673 IN PRTMP_ADAPTER pAd,
2674 IN USHORT TxPreamble)
2676 AUTO_RSP_CFG_STRUC csr4;
2679 // Always use Long preamble before verifiation short preamble functionality works well.
2680 // Todo: remove the following line if short preamble functionality works
2682 //TxPreamble = Rt802_11PreambleLong;
2684 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2685 if (TxPreamble == Rt802_11PreambleLong)
2687 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2688 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2689 csr4.field.AutoResponderPreamble = 0;
2693 // NOTE: 1Mbps should always use long preamble
2694 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2695 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2696 csr4.field.AutoResponderPreamble = 1;
2699 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2703 ==========================================================================
2705 Update basic rate bitmap
2706 ==========================================================================
2709 VOID UpdateBasicRateBitmap(
2710 IN PRTMP_ADAPTER pAdapter)
2713 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2714 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2715 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2716 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2717 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2720 /* if A mode, always use fix BasicRateBitMap */
2721 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2722 if (pAdapter->CommonCfg.Channel > 14)
2723 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2726 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2728 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2732 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2738 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2740 if (bitmap & (1 << i))
2742 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2744 if (sup_p[j] == rate[i])
2749 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2751 if (ext_p[j] == rate[i])
2757 } /* End of UpdateBasicRateBitmap */
2759 // IRQL = PASSIVE_LEVEL
2760 // IRQL = DISPATCH_LEVEL
2761 // bLinkUp is to identify the inital link speed.
2762 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2763 VOID MlmeUpdateTxRates(
2764 IN PRTMP_ADAPTER pAd,
2769 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2770 UCHAR MinSupport = RATE_54;
2771 ULONG BasicRateBitmap = 0;
2772 UCHAR CurrBasicRate = RATE_1;
2773 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2774 PHTTRANSMIT_SETTING pHtPhy = NULL;
2775 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2776 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2777 BOOLEAN *auto_rate_cur_p;
2778 UCHAR HtMcs = MCS_AUTO;
2780 // find max desired rate
2781 UpdateBasicRateBitmap(pAd);
2784 auto_rate_cur_p = NULL;
2785 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2787 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2789 case 2: Rate = RATE_1; num++; break;
2790 case 4: Rate = RATE_2; num++; break;
2791 case 11: Rate = RATE_5_5; num++; break;
2792 case 22: Rate = RATE_11; num++; break;
2793 case 12: Rate = RATE_6; num++; break;
2794 case 18: Rate = RATE_9; num++; break;
2795 case 24: Rate = RATE_12; num++; break;
2796 case 36: Rate = RATE_18; num++; break;
2797 case 48: Rate = RATE_24; num++; break;
2798 case 72: Rate = RATE_36; num++; break;
2799 case 96: Rate = RATE_48; num++; break;
2800 case 108: Rate = RATE_54; num++; break;
2801 //default: Rate = RATE_1; break;
2803 if (MaxDesire < Rate) MaxDesire = Rate;
2806 //===========================================================================
2807 //===========================================================================
2808 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2810 pHtPhy = &pAd->StaCfg.HTPhyMode;
2811 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2812 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2814 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2815 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2817 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2818 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2819 (MaxDesire > RATE_11))
2821 MaxDesire = RATE_11;
2825 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2826 pMinHtPhy->word = 0;
2827 pMaxHtPhy->word = 0;
2830 // Auto rate switching is enabled only if more than one DESIRED RATES are
2831 // specified; otherwise disabled
2834 *auto_rate_cur_p = FALSE;
2838 *auto_rate_cur_p = TRUE;
2842 if (HtMcs != MCS_AUTO)
2844 *auto_rate_cur_p = FALSE;
2848 *auto_rate_cur_p = TRUE;
2852 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2854 pSupRate = &pAd->StaActive.SupRate[0];
2855 pExtRate = &pAd->StaActive.ExtRate[0];
2856 SupRateLen = pAd->StaActive.SupRateLen;
2857 ExtRateLen = pAd->StaActive.ExtRateLen;
2861 pSupRate = &pAd->CommonCfg.SupRate[0];
2862 pExtRate = &pAd->CommonCfg.ExtRate[0];
2863 SupRateLen = pAd->CommonCfg.SupRateLen;
2864 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2867 // find max supported rate
2868 for (i=0; i<SupRateLen; i++)
2870 switch (pSupRate[i] & 0x7f)
2872 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2873 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2874 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2875 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2876 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2877 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2878 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2879 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2880 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2881 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2882 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2883 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2884 default: Rate = RATE_1; break;
2886 if (MaxSupport < Rate) MaxSupport = Rate;
2888 if (MinSupport > Rate) MinSupport = Rate;
2891 for (i=0; i<ExtRateLen; i++)
2893 switch (pExtRate[i] & 0x7f)
2895 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2896 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2897 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2898 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2899 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2900 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2901 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2902 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2903 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2904 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2905 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2906 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2907 default: Rate = RATE_1; break;
2909 if (MaxSupport < Rate) MaxSupport = Rate;
2911 if (MinSupport > Rate) MinSupport = Rate;
2914 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2916 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2917 // the DURATION field of outgoing uniicast DATA/MGMT frame
2918 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2920 if (BasicRateBitmap & (0x01 << i))
2921 CurrBasicRate = (UCHAR)i;
2922 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2925 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2926 // max tx rate = min {max desire rate, max supported rate}
2927 if (MaxSupport < MaxDesire)
2928 pAd->CommonCfg.MaxTxRate = MaxSupport;
2930 pAd->CommonCfg.MaxTxRate = MaxDesire;
2932 pAd->CommonCfg.MinTxRate = MinSupport;
2933 if (*auto_rate_cur_p)
2937 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2938 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2940 if (bLinkUp == TRUE)
2941 pAd->CommonCfg.TxRate = RATE_24;
2943 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2946 pAd->CommonCfg.TxRate = RATE_11;
2948 pAd->CommonCfg.TxRate = RATE_24;
2950 // should never exceed MaxTxRate (consider 11B-only mode)
2951 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2952 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2954 pAd->CommonCfg.TxRateIndex = 0;
2958 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2959 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2960 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2962 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2963 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2964 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2965 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
2968 if (pAd->CommonCfg.TxRate <= RATE_11)
2970 pMaxHtPhy->field.MODE = MODE_CCK;
2971 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
2972 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
2976 pMaxHtPhy->field.MODE = MODE_OFDM;
2977 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
2978 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
2979 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
2981 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
2984 pHtPhy->word = (pMaxHtPhy->word);
2985 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
2987 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
2988 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
2989 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
2993 switch (pAd->CommonCfg.PhyMode)
2995 case PHY_11BG_MIXED:
2997 case PHY_11BGN_MIXED:
2998 pAd->CommonCfg.MlmeRate = RATE_1;
2999 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3000 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3001 pAd->CommonCfg.RtsRate = RATE_11;
3005 case PHY_11AGN_MIXED:
3006 case PHY_11GN_MIXED:
3008 case PHY_11AN_MIXED:
3010 pAd->CommonCfg.MlmeRate = RATE_6;
3011 pAd->CommonCfg.RtsRate = RATE_6;
3012 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3013 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3015 case PHY_11ABG_MIXED:
3016 case PHY_11ABGN_MIXED:
3017 if (pAd->CommonCfg.Channel <= 14)
3019 pAd->CommonCfg.MlmeRate = RATE_1;
3020 pAd->CommonCfg.RtsRate = RATE_1;
3021 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3022 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3026 pAd->CommonCfg.MlmeRate = RATE_6;
3027 pAd->CommonCfg.RtsRate = RATE_6;
3028 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3029 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3033 pAd->CommonCfg.MlmeRate = RATE_6;
3034 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3035 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3036 pAd->CommonCfg.RtsRate = RATE_1;
3040 // Keep Basic Mlme Rate.
3042 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3043 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3044 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3046 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3047 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3050 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3051 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3052 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3053 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3054 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3055 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3056 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 ));
3060 ==========================================================================
3062 This function update HT Rate setting.
3063 Input Wcid value is valid for 2 case :
3064 1. it's used for Station in infra mode that copy AP rate to Mactable.
3065 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3067 IRQL = DISPATCH_LEVEL
3069 ==========================================================================
3071 VOID MlmeUpdateHtTxRates(
3072 IN PRTMP_ADAPTER pAd,
3075 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3077 RT_HT_CAPABILITY *pRtHtCap = NULL;
3078 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3081 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3082 PHTTRANSMIT_SETTING pHtPhy = NULL;
3083 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3084 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3085 BOOLEAN *auto_rate_cur_p;
3087 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3089 auto_rate_cur_p = NULL;
3091 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3093 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3094 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3095 pHtPhy = &pAd->StaCfg.HTPhyMode;
3096 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3097 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3099 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3102 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3104 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3107 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3108 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3109 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3110 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3111 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3112 pMaxHtPhy->field.STBC = STBC_USE;
3114 pMaxHtPhy->field.STBC = STBC_NONE;
3118 if (pDesireHtPhy->bHtEnable == FALSE)
3121 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3122 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3123 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3124 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3125 pMaxHtPhy->field.STBC = STBC_USE;
3127 pMaxHtPhy->field.STBC = STBC_NONE;
3130 // Decide MAX ht rate.
3131 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3132 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3134 pMaxHtPhy->field.MODE = MODE_HTMIX;
3136 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3137 pMaxHtPhy->field.BW = BW_40;
3139 pMaxHtPhy->field.BW = BW_20;
3141 if (pMaxHtPhy->field.BW == BW_20)
3142 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3144 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3146 for (i=23; i>=0; i--) // 3*3
3149 bitmask = (1<<(i-(j*8)));
3151 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3153 pMaxHtPhy->field.MCS = i;
3161 // Copy MIN ht rate. rt2860???
3162 pMinHtPhy->field.BW = BW_20;
3163 pMinHtPhy->field.MCS = 0;
3164 pMinHtPhy->field.STBC = 0;
3165 pMinHtPhy->field.ShortGI = 0;
3166 //If STA assigns fixed rate. update to fixed here.
3167 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3169 if (pDesireHtPhy->MCSSet[4] != 0)
3171 pMaxHtPhy->field.MCS = 32;
3172 pMinHtPhy->field.MCS = 32;
3173 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3176 for (i=23; (CHAR)i >= 0; i--) // 3*3
3179 bitmask = (1<<(i-(j*8)));
3180 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3182 pMaxHtPhy->field.MCS = i;
3183 pMinHtPhy->field.MCS = i;
3192 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3193 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3194 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3195 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3196 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3198 // use default now. rt2860
3199 if (pDesireHtPhy->MCSSet[0] != 0xff)
3200 *auto_rate_cur_p = FALSE;
3202 *auto_rate_cur_p = TRUE;
3204 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3205 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3206 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3207 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3210 // IRQL = DISPATCH_LEVEL
3212 IN PRTMP_ADAPTER pAd)
3214 RT28XX_MLME_RADIO_OFF(pAd);
3217 // IRQL = DISPATCH_LEVEL
3219 IN PRTMP_ADAPTER pAd)
3221 RT28XX_MLME_RADIO_ON(pAd);
3224 // ===========================================================================================
3226 // ===========================================================================================
3229 /*! \brief initialize BSS table
3230 * \param p_tab pointer to the table
3235 IRQL = PASSIVE_LEVEL
3236 IRQL = DISPATCH_LEVEL
3245 Tab->BssOverlapNr = 0;
3246 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3248 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3249 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3254 IN PRTMP_ADAPTER pAd,
3259 Tab->numAsOriginator = 0;
3260 Tab->numAsRecipient = 0;
3261 NdisAllocateSpinLock(&pAd->BATabLock);
3262 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3264 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3265 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3267 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3269 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3273 /*! \brief search the BSS table by SSID
3274 * \param p_tab pointer to the bss table
3275 * \param ssid SSID string
3276 * \return index of the table, BSS_NOT_FOUND if not in the table
3279 * \note search by sequential search
3281 IRQL = DISPATCH_LEVEL
3284 ULONG BssTableSearch(
3291 for (i = 0; i < Tab->BssNr; i++)
3294 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3295 // We should distinguish this case.
3297 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3298 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3299 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3304 return (ULONG)BSS_NOT_FOUND;
3307 ULONG BssSsidTableSearch(
3316 for (i = 0; i < Tab->BssNr; i++)
3319 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3320 // We should distinguish this case.
3322 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3323 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3324 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3325 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3330 return (ULONG)BSS_NOT_FOUND;
3333 ULONG BssTableSearchWithSSID(
3342 for (i = 0; i < Tab->BssNr; i++)
3344 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3345 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3346 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3347 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3348 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3349 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3354 return (ULONG)BSS_NOT_FOUND;
3357 // IRQL = DISPATCH_LEVEL
3358 VOID BssTableDeleteEntry(
3359 IN OUT BSS_TABLE *Tab,
3365 for (i = 0; i < Tab->BssNr; i++)
3367 if ((Tab->BssEntry[i].Channel == Channel) &&
3368 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3370 for (j = i; j < Tab->BssNr - 1; j++)
3372 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3374 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3382 ========================================================================
3383 Routine Description:
3384 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3387 // IRQL = DISPATCH_LEVEL
3388 ========================================================================
3390 VOID BATableDeleteORIEntry(
3391 IN OUT PRTMP_ADAPTER pAd,
3392 IN BA_ORI_ENTRY *pBAORIEntry)
3395 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3397 NdisAcquireSpinLock(&pAd->BATabLock);
3398 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3400 pAd->BATable.numAsOriginator -= 1;
3401 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3402 // Erase Bitmap flag.
3404 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3405 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3406 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3407 pBAORIEntry->Token = 1;
3408 // Not clear Sequence here.
3409 NdisReleaseSpinLock(&pAd->BATabLock);
3419 IRQL = DISPATCH_LEVEL
3423 IN PRTMP_ADAPTER pAd,
3424 OUT BSS_ENTRY *pBss,
3429 IN USHORT BeaconPeriod,
3430 IN PCF_PARM pCfParm,
3432 IN USHORT CapabilityInfo,
3434 IN UCHAR SupRateLen,
3436 IN UCHAR ExtRateLen,
3437 IN HT_CAPABILITY_IE *pHtCapability,
3438 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3439 IN UCHAR HtCapabilityLen,
3440 IN UCHAR AddHtInfoLen,
3441 IN UCHAR NewExtChanOffset,
3444 IN LARGE_INTEGER TimeStamp,
3446 IN PEDCA_PARM pEdcaParm,
3447 IN PQOS_CAPABILITY_PARM pQosCapability,
3448 IN PQBSS_LOAD_PARM pQbssLoad,
3449 IN USHORT LengthVIE,
3450 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3452 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3453 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3457 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3458 // Or send beacon /probe response with SSID len matching real SSID length,
3459 // but SSID is all zero. such as "00-00-00-00" with length 4.
3460 // We have to prevent this case overwrite correct table
3461 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3463 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3464 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3465 pBss->SsidLen = SsidLen;
3471 pBss->BssType = BssType;
3472 pBss->BeaconPeriod = BeaconPeriod;
3473 if (BssType == BSS_INFRA)
3475 if (pCfParm->bValid)
3477 pBss->CfpCount = pCfParm->CfpCount;
3478 pBss->CfpPeriod = pCfParm->CfpPeriod;
3479 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3480 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3485 pBss->AtimWin = AtimWin;
3488 pBss->CapabilityInfo = CapabilityInfo;
3489 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3490 // Combine with AuthMode, they will decide the connection methods.
3491 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3492 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3493 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3494 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3496 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3497 pBss->SupRateLen = SupRateLen;
3498 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3499 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3500 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3501 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3502 pBss->NewExtChanOffset = NewExtChanOffset;
3503 pBss->ExtRateLen = ExtRateLen;
3504 pBss->Channel = Channel;
3505 pBss->CentralChannel = Channel;
3507 // Update CkipFlag. if not exists, the value is 0x0
3508 pBss->CkipFlag = CkipFlag;
3510 // New for microsoft Fixed IEs
3511 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3512 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3513 pBss->FixIEs.Capabilities = CapabilityInfo;
3515 // New for microsoft Variable IEs
3518 pBss->VarIELen = LengthVIE;
3519 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3526 pBss->AddHtInfoLen = 0;
3527 pBss->HtCapabilityLen = 0;
3529 if (HtCapabilityLen> 0)
3531 pBss->HtCapabilityLen = HtCapabilityLen;
3532 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3533 if (AddHtInfoLen > 0)
3535 pBss->AddHtInfoLen = AddHtInfoLen;
3536 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3538 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3540 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3542 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3544 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3549 BssCipherParse(pBss);
3553 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3555 pBss->EdcaParm.bValid = FALSE;
3557 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3559 pBss->QosCapability.bValid = FALSE;
3561 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3563 pBss->QbssLoad.bValid = FALSE;
3565 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3571 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3572 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3574 pEid = (PEID_STRUCT) pVIE;
3576 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3581 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3583 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3585 pBss->WpaIE.IELen = 0;
3588 pBss->WpaIE.IELen = pEid->Len + 2;
3589 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3593 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3595 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3597 pBss->RsnIE.IELen = 0;
3600 pBss->RsnIE.IELen = pEid->Len + 2;
3601 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3605 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3606 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3612 * \brief insert an entry into the bss table
3613 * \param p_tab The BSS table
3614 * \param Bssid BSSID
3616 * \param ssid_len Length of SSID
3618 * \param beacon_period
3625 * \param channel_idx
3629 * \note If SSID is identical, the old entry will be replaced by the new one
3631 IRQL = DISPATCH_LEVEL
3634 ULONG BssTableSetEntry(
3635 IN PRTMP_ADAPTER pAd,
3641 IN USHORT BeaconPeriod,
3644 IN USHORT CapabilityInfo,
3646 IN UCHAR SupRateLen,
3648 IN UCHAR ExtRateLen,
3649 IN HT_CAPABILITY_IE *pHtCapability,
3650 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3651 IN UCHAR HtCapabilityLen,
3652 IN UCHAR AddHtInfoLen,
3653 IN UCHAR NewExtChanOffset,
3656 IN LARGE_INTEGER TimeStamp,
3658 IN PEDCA_PARM pEdcaParm,
3659 IN PQOS_CAPABILITY_PARM pQosCapability,
3660 IN PQBSS_LOAD_PARM pQbssLoad,
3661 IN USHORT LengthVIE,
3662 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3666 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3667 if (Idx == BSS_NOT_FOUND)
3669 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3672 // It may happen when BSS Table was full.
3673 // The desired AP will not be added into BSS Table
3674 // In this case, if we found the desired AP then overwrite BSS Table.
3676 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3678 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3679 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3681 Idx = Tab->BssOverlapNr;
3682 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3683 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3684 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3685 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3691 return BSS_NOT_FOUND;
3695 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3696 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3697 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3702 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3703 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3704 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3710 // IRQL = DISPATCH_LEVEL
3711 VOID BssTableSsidSort(
3712 IN PRTMP_ADAPTER pAd,
3713 OUT BSS_TABLE *OutTab,
3718 BssTableInit(OutTab);
3720 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3722 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3723 BOOLEAN bIsHiddenApIncluded = FALSE;
3725 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3726 (pAd->MlmeAux.Channel > 14) &&
3727 RadarChannelCheck(pAd, pInBss->Channel))
3731 bIsHiddenApIncluded = TRUE;
3734 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3735 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3737 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3739 // 2.4G/5G N only mode
3740 if ((pInBss->HtCapabilityLen == 0) &&
3741 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3743 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3748 // Check the Authmode first
3749 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3751 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3752 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3756 // Check cipher suite, AP must have more secured cipher than station setting
3757 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3759 // If it's not mixed mode, we should only let BSS pass with the same encryption
3760 if (pInBss->WPA.bMixMode == FALSE)
3761 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3764 // check group cipher
3765 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3766 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3767 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3770 // check pairwise cipher, skip if none matched
3771 // If profile set to AES, let it pass without question.
3772 // If profile set to TKIP, we must find one mateched
3773 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3774 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3775 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3778 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3780 // If it's not mixed mode, we should only let BSS pass with the same encryption
3781 if (pInBss->WPA2.bMixMode == FALSE)
3782 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3785 // check group cipher
3786 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3787 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3788 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3791 // check pairwise cipher, skip if none matched
3792 // If profile set to AES, let it pass without question.
3793 // If profile set to TKIP, we must find one mateched
3794 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3795 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3796 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3800 // Bss Type matched, SSID matched.
3801 // We will check wepstatus for qualification Bss
3802 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3804 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3806 // For the SESv2 case, we will not qualify WepStatus.
3812 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3813 // It definitely will fail. So, skip it.
3814 // CCX also require not even try to connect it!!
3818 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3819 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3820 if ((pInBss->CentralChannel != pInBss->Channel) &&
3821 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3823 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3825 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3827 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3831 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3838 // copy matching BSS from InTab to OutTab
3839 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3843 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3845 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3847 // 2.4G/5G N only mode
3848 if ((pInBss->HtCapabilityLen == 0) &&
3849 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3851 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3856 // Check the Authmode first
3857 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3859 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3860 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3864 // Check cipher suite, AP must have more secured cipher than station setting
3865 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3867 // If it's not mixed mode, we should only let BSS pass with the same encryption
3868 if (pInBss->WPA.bMixMode == FALSE)
3869 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3872 // check group cipher
3873 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3876 // check pairwise cipher, skip if none matched
3877 // If profile set to AES, let it pass without question.
3878 // If profile set to TKIP, we must find one mateched
3879 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3880 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3881 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3884 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3886 // If it's not mixed mode, we should only let BSS pass with the same encryption
3887 if (pInBss->WPA2.bMixMode == FALSE)
3888 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3891 // check group cipher
3892 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3895 // check pairwise cipher, skip if none matched
3896 // If profile set to AES, let it pass without question.
3897 // If profile set to TKIP, we must find one mateched
3898 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3899 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3900 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3904 // Bss Type matched, SSID matched.
3905 // We will check wepstatus for qualification Bss
3906 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3909 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3910 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3911 if ((pInBss->CentralChannel != pInBss->Channel) &&
3912 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3914 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3916 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3918 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3922 // copy matching BSS from InTab to OutTab
3923 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3928 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3932 BssTableSortByRssi(OutTab);
3936 // IRQL = DISPATCH_LEVEL
3937 VOID BssTableSortByRssi(
3938 IN OUT BSS_TABLE *OutTab)
3943 for (i = 0; i < OutTab->BssNr - 1; i++)
3945 for (j = i+1; j < OutTab->BssNr; j++)
3947 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
3949 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
3950 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
3951 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
3957 VOID BssCipherParse(
3958 IN OUT PBSS_ENTRY pBss)
3962 PRSN_IE_HEADER_STRUCT pRsnHeader;
3963 PCIPHER_SUITE_STRUCT pCipher;
3964 PAKM_SUITE_STRUCT pAKM;
3967 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
3970 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
3974 pBss->WepStatus = Ndis802_11WEPEnabled;
3978 pBss->WepStatus = Ndis802_11WEPDisabled;
3980 // Set default to disable & open authentication before parsing variable IE
3981 pBss->AuthMode = Ndis802_11AuthModeOpen;
3982 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
3985 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
3986 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
3987 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
3988 pBss->WPA.RsnCapability = 0;
3989 pBss->WPA.bMixMode = FALSE;
3991 // Init WPA2 setting
3992 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
3993 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
3994 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
3995 pBss->WPA2.RsnCapability = 0;
3996 pBss->WPA2.bMixMode = FALSE;
3999 Length = (INT) pBss->VarIELen;
4003 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4004 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4005 pEid = (PEID_STRUCT) pTmp;
4009 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4010 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4016 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4017 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4018 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4019 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4022 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4023 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4024 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4027 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4028 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4029 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4035 // if Cisco IE_WPA, break
4038 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4043 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4045 // if unsupported vendor specific IE
4048 // Skip OUI, version, and multicast suite
4049 // This part should be improved in the future when AP supported multiple cipher suite.
4050 // For now, it's OK since almost all APs have fixed cipher suite supported.
4051 // pTmp = (PUCHAR) pEid->Octet;
4054 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4062 // Parse group cipher
4066 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4069 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4072 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4075 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4080 // number of unicast suite
4083 // skip all unicast cipher suites
4084 //Count = *(PUSHORT) pTmp;
4085 Count = (pTmp[1]<<8) + pTmp[0];
4086 pTmp += sizeof(USHORT);
4088 // Parsing all unicast cipher suite
4093 TmpCipher = Ndis802_11WEPDisabled;
4097 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4098 TmpCipher = Ndis802_11Encryption1Enabled;
4101 TmpCipher = Ndis802_11Encryption2Enabled;
4104 TmpCipher = Ndis802_11Encryption3Enabled;
4109 if (TmpCipher > pBss->WPA.PairCipher)
4111 // Move the lower cipher suite to PairCipherAux
4112 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4113 pBss->WPA.PairCipher = TmpCipher;
4117 pBss->WPA.PairCipherAux = TmpCipher;
4123 // 4. get AKM suite counts
4124 //Count = *(PUSHORT) pTmp;
4125 Count = (pTmp[1]<<8) + pTmp[0];
4126 pTmp += sizeof(USHORT);
4132 // Set AP support WPA mode
4133 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4134 pBss->AuthMode = Ndis802_11AuthModeWPA;
4136 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4139 // Set AP support WPA mode
4140 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4141 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4143 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4150 // Fixed for WPA-None
4151 if (pBss->BssType == BSS_ADHOC)
4153 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4154 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4155 pBss->WepStatus = pBss->WPA.GroupCipher;
4156 // Patched bugs for old driver
4157 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4158 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4161 pBss->WepStatus = pBss->WPA.PairCipher;
4163 // Check the Pair & Group, if different, turn on mixed mode flag
4164 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4165 pBss->WPA.bMixMode = TRUE;
4170 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4172 // 0. Version must be 1
4173 if (le2cpu16(pRsnHeader->Version) != 1)
4175 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4177 // 1. Check group cipher
4178 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4179 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4182 // Parse group cipher
4183 switch (pCipher->Type)
4186 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4189 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4192 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4195 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4200 // set to correct offset for next parsing
4201 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4203 // 2. Get pairwise cipher counts
4204 //Count = *(PUSHORT) pTmp;
4205 Count = (pTmp[1]<<8) + pTmp[0];
4206 pTmp += sizeof(USHORT);
4208 // 3. Get pairwise cipher
4209 // Parsing all unicast cipher suite
4213 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4214 TmpCipher = Ndis802_11WEPDisabled;
4215 switch (pCipher->Type)
4218 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4219 TmpCipher = Ndis802_11Encryption1Enabled;
4222 TmpCipher = Ndis802_11Encryption2Enabled;
4225 TmpCipher = Ndis802_11Encryption3Enabled;
4230 if (TmpCipher > pBss->WPA2.PairCipher)
4232 // Move the lower cipher suite to PairCipherAux
4233 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4234 pBss->WPA2.PairCipher = TmpCipher;
4238 pBss->WPA2.PairCipherAux = TmpCipher;
4240 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4244 // 4. get AKM suite counts
4245 //Count = *(PUSHORT) pTmp;
4246 Count = (pTmp[1]<<8) + pTmp[0];
4247 pTmp += sizeof(USHORT);
4249 // 5. Get AKM ciphers
4250 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4251 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4257 // Set AP support WPA mode
4258 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4259 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4261 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4264 // Set AP support WPA mode
4265 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4266 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4268 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4273 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4275 // Fixed for WPA-None
4276 if (pBss->BssType == BSS_ADHOC)
4278 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4279 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4280 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4281 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4282 pBss->WepStatus = pBss->WPA.GroupCipher;
4283 // Patched bugs for old driver
4284 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4285 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4287 pBss->WepStatus = pBss->WPA2.PairCipher;
4289 // 6. Get RSN capability
4290 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4291 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4292 pTmp += sizeof(USHORT);
4294 // Check the Pair & Group, if different, turn on mixed mode flag
4295 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4296 pBss->WPA2.bMixMode = TRUE;
4302 Length -= (pEid->Len + 2);
4306 // ===========================================================================================
4308 // ===========================================================================================
4310 /*! \brief generates a random mac address value for IBSS BSSID
4311 * \param Addr the bssid location
4316 VOID MacAddrRandomBssid(
4317 IN PRTMP_ADAPTER pAd,
4322 for (i = 0; i < MAC_ADDR_LEN; i++)
4324 pAddr[i] = RandomByte(pAd);
4327 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4330 /*! \brief init the management mac frame header
4331 * \param p_hdr mac header
4332 * \param subtype subtype of the frame
4333 * \param p_ds destination address, don't care if it is a broadcast address
4335 * \pre the station has the following information in the pAd->StaCfg
4339 * \note this function initializes the following field
4341 IRQL = PASSIVE_LEVEL
4342 IRQL = DISPATCH_LEVEL
4345 VOID MgtMacHeaderInit(
4346 IN PRTMP_ADAPTER pAd,
4347 IN OUT PHEADER_802_11 pHdr80211,
4353 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4355 pHdr80211->FC.Type = BTYPE_MGMT;
4356 pHdr80211->FC.SubType = SubType;
4357 pHdr80211->FC.ToDs = ToDs;
4358 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4360 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4361 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4363 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4366 // ===========================================================================================
4368 // ===========================================================================================
4370 /*!***************************************************************************
4371 * This routine build an outgoing frame, and fill all information specified
4372 * in argument list to the frame body. The actual frame size is the summation
4375 * Buffer - pointer to a pre-allocated memory segment
4376 * args - a list of <int arg_size, arg> pairs.
4377 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4378 * function will FAIL!!!
4380 * Size of the buffer
4382 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4384 IRQL = PASSIVE_LEVEL
4385 IRQL = DISPATCH_LEVEL
4387 ****************************************************************************/
4388 ULONG MakeOutgoingFrame(
4390 OUT ULONG *FrameLen, ...)
4397 // calculates the total length
4399 va_start(Args, FrameLen);
4402 leng = va_arg(Args, int);
4403 if (leng == END_OF_ARGS)
4407 p = va_arg(Args, PVOID);
4408 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4409 TotLeng = TotLeng + leng;
4412 va_end(Args); /* clean up */
4413 *FrameLen = TotLeng;
4417 // ===========================================================================================
4419 // ===========================================================================================
4421 /*! \brief Initialize The MLME Queue, used by MLME Functions
4422 * \param *Queue The MLME Queue
4423 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4426 * \note Because this is done only once (at the init stage), no need to be locked
4428 IRQL = PASSIVE_LEVEL
4431 NDIS_STATUS MlmeQueueInit(
4432 IN MLME_QUEUE *Queue)
4436 NdisAllocateSpinLock(&Queue->Lock);
4442 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4444 Queue->Entry[i].Occupied = FALSE;
4445 Queue->Entry[i].MsgLen = 0;
4446 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4449 return NDIS_STATUS_SUCCESS;
4452 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4453 * \param *Queue The MLME Queue
4454 * \param Machine The State Machine Id
4455 * \param MsgType The Message Type
4456 * \param MsgLen The Message length
4457 * \param *Msg The message pointer
4458 * \return TRUE if enqueue is successful, FALSE if the queue is full
4461 * \note The message has to be initialized
4463 IRQL = PASSIVE_LEVEL
4464 IRQL = DISPATCH_LEVEL
4467 BOOLEAN MlmeEnqueue(
4468 IN PRTMP_ADAPTER pAd,
4475 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4477 // Do nothing if the driver is starting halt state.
4478 // This might happen when timer already been fired before cancel timer with mlmehalt
4479 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4482 // First check the size, it MUST not exceed the mlme queue size
4483 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4485 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4489 if (MlmeQueueFull(Queue))
4494 NdisAcquireSpinLock(&(Queue->Lock));
4498 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4503 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4504 Queue->Entry[Tail].Occupied = TRUE;
4505 Queue->Entry[Tail].Machine = Machine;
4506 Queue->Entry[Tail].MsgType = MsgType;
4507 Queue->Entry[Tail].MsgLen = MsgLen;
4511 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4514 NdisReleaseSpinLock(&(Queue->Lock));
4518 /*! \brief This function is used when Recv gets a MLME message
4519 * \param *Queue The MLME Queue
4520 * \param TimeStampHigh The upper 32 bit of timestamp
4521 * \param TimeStampLow The lower 32 bit of timestamp
4522 * \param Rssi The receiving RSSI strength
4523 * \param MsgLen The length of the message
4524 * \param *Msg The message pointer
4525 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4529 IRQL = DISPATCH_LEVEL
4532 BOOLEAN MlmeEnqueueForRecv(
4533 IN PRTMP_ADAPTER pAd,
4535 IN ULONG TimeStampHigh,
4536 IN ULONG TimeStampLow,
4545 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4547 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4549 // Do nothing if the driver is starting halt state.
4550 // This might happen when timer already been fired before cancel timer with mlmehalt
4551 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4553 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4557 // First check the size, it MUST not exceed the mlme queue size
4558 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4560 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4564 if (MlmeQueueFull(Queue))
4569 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4571 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4573 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4578 // OK, we got all the informations, it is time to put things into queue
4579 NdisAcquireSpinLock(&(Queue->Lock));
4583 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4587 Queue->Entry[Tail].Occupied = TRUE;
4588 Queue->Entry[Tail].Machine = Machine;
4589 Queue->Entry[Tail].MsgType = MsgType;
4590 Queue->Entry[Tail].MsgLen = MsgLen;
4591 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4592 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4593 Queue->Entry[Tail].Rssi0 = Rssi0;
4594 Queue->Entry[Tail].Rssi1 = Rssi1;
4595 Queue->Entry[Tail].Rssi2 = Rssi2;
4596 Queue->Entry[Tail].Signal = Signal;
4597 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4599 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4603 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4606 NdisReleaseSpinLock(&(Queue->Lock));
4608 RT28XX_MLME_HANDLER(pAd);
4614 /*! \brief Dequeue a message from the MLME Queue
4615 * \param *Queue The MLME Queue
4616 * \param *Elem The message dequeued from MLME Queue
4617 * \return TRUE if the Elem contains something, FALSE otherwise
4621 IRQL = DISPATCH_LEVEL
4624 BOOLEAN MlmeDequeue(
4625 IN MLME_QUEUE *Queue,
4626 OUT MLME_QUEUE_ELEM **Elem)
4628 NdisAcquireSpinLock(&(Queue->Lock));
4629 *Elem = &(Queue->Entry[Queue->Head]);
4632 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4636 NdisReleaseSpinLock(&(Queue->Lock));
4640 // IRQL = DISPATCH_LEVEL
4641 VOID MlmeRestartStateMachine(
4642 IN PRTMP_ADAPTER pAd)
4644 MLME_QUEUE_ELEM *Elem = NULL;
4647 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4649 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4650 if(pAd->Mlme.bRunning)
4652 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4657 pAd->Mlme.bRunning = TRUE;
4659 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4661 // Remove all Mlme queues elements
4662 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4664 //From message type, determine which state machine I should drive
4665 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4667 // free MLME element
4668 Elem->Occupied = FALSE;
4673 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4677 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4679 // Cancel all timer events
4680 // Be careful to cancel new added timer
4681 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4682 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4683 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4684 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4685 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4686 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4689 // Change back to original channel in case of doing scan
4690 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4691 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4693 // Resume MSDU which is turned off durning scan
4694 RTMPResumeMsduTransmission(pAd);
4696 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4698 // Set all state machines back IDLE
4699 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4700 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4701 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4702 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4703 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4704 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4707 // Remove running state
4708 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4709 pAd->Mlme.bRunning = FALSE;
4710 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4713 /*! \brief test if the MLME Queue is empty
4714 * \param *Queue The MLME Queue
4715 * \return TRUE if the Queue is empty, FALSE otherwise
4719 IRQL = DISPATCH_LEVEL
4722 BOOLEAN MlmeQueueEmpty(
4723 IN MLME_QUEUE *Queue)
4727 NdisAcquireSpinLock(&(Queue->Lock));
4728 Ans = (Queue->Num == 0);
4729 NdisReleaseSpinLock(&(Queue->Lock));
4734 /*! \brief test if the MLME Queue is full
4735 * \param *Queue The MLME Queue
4736 * \return TRUE if the Queue is empty, FALSE otherwise
4740 IRQL = PASSIVE_LEVEL
4741 IRQL = DISPATCH_LEVEL
4744 BOOLEAN MlmeQueueFull(
4745 IN MLME_QUEUE *Queue)
4749 NdisAcquireSpinLock(&(Queue->Lock));
4750 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4751 NdisReleaseSpinLock(&(Queue->Lock));
4756 /*! \brief The destructor of MLME Queue
4761 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4763 IRQL = PASSIVE_LEVEL
4766 VOID MlmeQueueDestroy(
4767 IN MLME_QUEUE *pQueue)
4769 NdisAcquireSpinLock(&(pQueue->Lock));
4773 NdisReleaseSpinLock(&(pQueue->Lock));
4774 NdisFreeSpinLock(&(pQueue->Lock));
4777 /*! \brief To substitute the message type if the message is coming from external
4778 * \param pFrame The frame received
4779 * \param *Machine The state machine
4780 * \param *MsgType the message type for the state machine
4781 * \return TRUE if the substitution is successful, FALSE otherwise
4785 IRQL = DISPATCH_LEVEL
4788 BOOLEAN MsgTypeSubst(
4789 IN PRTMP_ADAPTER pAd,
4790 IN PFRAME_802_11 pFrame,
4798 // Pointer to start of data frames including SNAP header
4799 pData = (PUCHAR) pFrame + LENGTH_802_11;
4801 // The only data type will pass to this function is EAPOL frame
4802 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4804 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4806 // Cisco Aironet SNAP header
4807 *Machine = AIRONET_STATE_MACHINE;
4808 *MsgType = MT2_AIRONET_MSG;
4812 *Machine = WPA_PSK_STATE_MACHINE;
4813 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4814 return(WpaMsgTypeSubst(EAPType, MsgType));
4818 switch (pFrame->Hdr.FC.SubType)
4820 case SUBTYPE_ASSOC_REQ:
4821 *Machine = ASSOC_STATE_MACHINE;
4822 *MsgType = MT2_PEER_ASSOC_REQ;
4824 case SUBTYPE_ASSOC_RSP:
4825 *Machine = ASSOC_STATE_MACHINE;
4826 *MsgType = MT2_PEER_ASSOC_RSP;
4828 case SUBTYPE_REASSOC_REQ:
4829 *Machine = ASSOC_STATE_MACHINE;
4830 *MsgType = MT2_PEER_REASSOC_REQ;
4832 case SUBTYPE_REASSOC_RSP:
4833 *Machine = ASSOC_STATE_MACHINE;
4834 *MsgType = MT2_PEER_REASSOC_RSP;
4836 case SUBTYPE_PROBE_REQ:
4837 *Machine = SYNC_STATE_MACHINE;
4838 *MsgType = MT2_PEER_PROBE_REQ;
4840 case SUBTYPE_PROBE_RSP:
4841 *Machine = SYNC_STATE_MACHINE;
4842 *MsgType = MT2_PEER_PROBE_RSP;
4844 case SUBTYPE_BEACON:
4845 *Machine = SYNC_STATE_MACHINE;
4846 *MsgType = MT2_PEER_BEACON;
4849 *Machine = SYNC_STATE_MACHINE;
4850 *MsgType = MT2_PEER_ATIM;
4852 case SUBTYPE_DISASSOC:
4853 *Machine = ASSOC_STATE_MACHINE;
4854 *MsgType = MT2_PEER_DISASSOC_REQ;
4857 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4858 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4859 if (Seq == 1 || Seq == 3)
4861 *Machine = AUTH_RSP_STATE_MACHINE;
4862 *MsgType = MT2_PEER_AUTH_ODD;
4864 else if (Seq == 2 || Seq == 4)
4866 *Machine = AUTH_STATE_MACHINE;
4867 *MsgType = MT2_PEER_AUTH_EVEN;
4874 case SUBTYPE_DEAUTH:
4875 *Machine = AUTH_RSP_STATE_MACHINE;
4876 *MsgType = MT2_PEER_DEAUTH;
4878 case SUBTYPE_ACTION:
4879 *Machine = ACTION_STATE_MACHINE;
4880 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4881 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4883 *MsgType = MT2_ACT_INVALID;
4887 *MsgType = (pFrame->Octet[0]&0x7F);
4898 // ===========================================================================================
4900 // ===========================================================================================
4902 /*! \brief Initialize the state machine.
4903 * \param *S pointer to the state machine
4904 * \param Trans State machine transition function
4905 * \param StNr number of states
4906 * \param MsgNr number of messages
4907 * \param DefFunc default function, when there is invalid state/message combination
4908 * \param InitState initial state of the state machine
4909 * \param Base StateMachine base, internal use only
4910 * \pre p_sm should be a legal pointer
4913 IRQL = PASSIVE_LEVEL
4916 VOID StateMachineInit(
4917 IN STATE_MACHINE *S,
4918 IN STATE_MACHINE_FUNC Trans[],
4921 IN STATE_MACHINE_FUNC DefFunc,
4927 // set number of states and messages
4932 S->TransFunc = Trans;
4934 // init all state transition to default function
4935 for (i = 0; i < StNr; i++)
4937 for (j = 0; j < MsgNr; j++)
4939 S->TransFunc[i * MsgNr + j] = DefFunc;
4943 // set the starting state
4944 S->CurrState = InitState;
4947 /*! \brief This function fills in the function pointer into the cell in the state machine
4948 * \param *S pointer to the state machine
4950 * \param Msg incoming message
4951 * \param f the function to be executed when (state, message) combination occurs at the state machine
4952 * \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
4955 IRQL = PASSIVE_LEVEL
4958 VOID StateMachineSetAction(
4959 IN STATE_MACHINE *S,
4962 IN STATE_MACHINE_FUNC Func)
4966 MsgIdx = Msg - S->Base;
4968 if (St < S->NrState && MsgIdx < S->NrMsg)
4970 // boundary checking before setting the action
4971 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
4975 /*! \brief This function does the state transition
4976 * \param *Adapter the NIC adapter pointer
4977 * \param *S the state machine
4978 * \param *Elem the message to be executed
4981 IRQL = DISPATCH_LEVEL
4984 VOID StateMachinePerformAction(
4985 IN PRTMP_ADAPTER pAd,
4986 IN STATE_MACHINE *S,
4987 IN MLME_QUEUE_ELEM *Elem)
4989 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
4993 ==========================================================================
4995 The drop function, when machine executes this, the message is simply
4996 ignored. This function does nothing, the message is freed in
4997 StateMachinePerformAction()
4998 ==========================================================================
5001 IN PRTMP_ADAPTER pAd,
5002 IN MLME_QUEUE_ELEM *Elem)
5006 // ===========================================================================================
5008 // ===========================================================================================
5011 ==========================================================================
5014 IRQL = PASSIVE_LEVEL
5016 ==========================================================================
5019 IN PRTMP_ADAPTER pAd,
5023 pAd->Mlme.ShiftReg = 1;
5025 pAd->Mlme.ShiftReg = Seed;
5029 ==========================================================================
5031 ==========================================================================
5034 IN PRTMP_ADAPTER pAd)
5041 if (pAd->Mlme.ShiftReg == 0)
5042 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5044 for (i = 0; i < 8; i++)
5046 if (pAd->Mlme.ShiftReg & 0x00000001)
5048 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5053 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5056 R = (R << 1) | Result;
5062 VOID AsicUpdateAutoFallBackTable(
5063 IN PRTMP_ADAPTER pAd,
5064 IN PUCHAR pRateTable)
5067 HT_FBK_CFG0_STRUC HtCfg0;
5068 HT_FBK_CFG1_STRUC HtCfg1;
5069 LG_FBK_CFG0_STRUC LgCfg0;
5070 LG_FBK_CFG1_STRUC LgCfg1;
5071 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5073 // set to initial value
5074 HtCfg0.word = 0x65432100;
5075 HtCfg1.word = 0xedcba988;
5076 LgCfg0.word = 0xedcba988;
5077 LgCfg1.word = 0x00002100;
5079 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5080 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5082 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5083 switch (pCurrTxRate->Mode)
5089 switch(pCurrTxRate->CurrMCS)
5092 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5095 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5098 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5101 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5104 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5107 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5110 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5113 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5121 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5123 switch(pCurrTxRate->CurrMCS)
5126 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5129 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5132 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5135 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5138 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5141 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5144 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5147 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5150 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5153 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5156 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5159 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5162 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5165 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5168 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5171 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5174 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5181 pNextTxRate = pCurrTxRate;
5184 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5185 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5186 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5187 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5191 ========================================================================
5193 Routine Description:
5194 Set MAC register value according operation mode.
5195 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5196 If MM or GF mask is not set, those passing argument doesn't not take effect.
5198 Operation mode meaning:
5199 = 0 : Pure HT, no preotection.
5200 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5201 = 0x10: No Transmission in 40M is protected.
5202 = 0x11: Transmission in both 40M and 20M shall be protected
5204 we should choose not to use GF. But still set correct ASIC registers.
5205 ========================================================================
5207 VOID AsicUpdateProtect(
5208 IN PRTMP_ADAPTER pAd,
5209 IN USHORT OperationMode,
5211 IN BOOLEAN bDisableBGProtect,
5212 IN BOOLEAN bNonGFExist)
5214 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5220 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5225 if (pAd->BATable.numAsOriginator)
5228 // enable the RTS/CTS to avoid channel collision
5230 SetMask = ALLN_SETPROTECT;
5234 // Config ASIC RTS threshold register
5235 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5236 MacReg &= 0xFF0000FF;
5238 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5240 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5242 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5243 (pAd->CommonCfg.bAggregationCapable == TRUE))
5244 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5246 MacReg |= (0x1000 << 8);
5250 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5254 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5256 // Initial common protection settings
5257 RTMPZeroMemory(Protect, sizeof(Protect));
5260 ProtCfg.field.TxopAllowGF40 = 1;
5261 ProtCfg.field.TxopAllowGF20 = 1;
5262 ProtCfg.field.TxopAllowMM40 = 1;
5263 ProtCfg.field.TxopAllowMM20 = 1;
5264 ProtCfg.field.TxopAllowOfdm = 1;
5265 ProtCfg.field.TxopAllowCck = 1;
5266 ProtCfg.field.RTSThEn = 1;
5267 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5269 // update PHY mode and rate
5270 if (pAd->CommonCfg.Channel > 14)
5271 ProtCfg.field.ProtectRate = 0x4000;
5272 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5274 // Handle legacy(B/G) protection
5275 if (bDisableBGProtect)
5277 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5278 ProtCfg.field.ProtectCtrl = 0;
5279 Protect[0] = ProtCfg.word;
5280 Protect[1] = ProtCfg.word;
5284 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5285 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5286 Protect[0] = ProtCfg.word;
5287 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5288 Protect[1] = ProtCfg.word;
5291 // Decide HT frame protection.
5292 if ((SetMask & ALLN_SETPROTECT) != 0)
5294 switch(OperationMode)
5298 // 1.All STAs in the BSS are 20/40 MHz HT
5299 // 2. in ai 20/40MHz BSS
5300 // 3. all STAs are 20MHz in a 20MHz BSS
5301 // Pure HT. no protection.
5305 // PROT_TXOP(25:20) -- 010111
5306 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5307 // PROT_CTRL(17:16) -- 00 (None)
5308 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5309 Protect[2] = 0x01744004;
5313 // PROT_TXOP(25:20) -- 111111
5314 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5315 // PROT_CTRL(17:16) -- 00 (None)
5316 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5317 Protect[3] = 0x03f44084;
5321 // PROT_TXOP(25:20) -- 010111
5322 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5323 // PROT_CTRL(17:16) -- 00 (None)
5324 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5325 Protect[4] = 0x01744004;
5329 // PROT_TXOP(25:20) -- 111111
5330 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5331 // PROT_CTRL(17:16) -- 00 (None)
5332 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5333 Protect[5] = 0x03f44084;
5337 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5338 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5339 Protect[4] = 0x01754004;
5340 Protect[5] = 0x03f54084;
5342 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5346 // This is "HT non-member protection mode."
5347 // If there may be non-HT STAs my BSS
5348 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5349 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5350 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5352 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5353 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5355 //Assign Protection method for 20&40 MHz packets
5356 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5357 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5358 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5359 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5360 Protect[2] = ProtCfg.word;
5361 Protect[3] = ProtCfg4.word;
5362 Protect[4] = ProtCfg.word;
5363 Protect[5] = ProtCfg4.word;
5364 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5368 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5369 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5370 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5372 //Assign Protection method for 40MHz packets
5373 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5374 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5375 Protect[2] = ProtCfg.word;
5376 Protect[3] = ProtCfg4.word;
5379 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5380 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5382 Protect[4] = ProtCfg.word;
5383 Protect[5] = ProtCfg4.word;
5385 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5389 // HT mixed mode. PROTECT ALL!
5391 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5392 ProtCfg4.word = 0x03f44084;
5393 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5394 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5396 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5397 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5399 //Assign Protection method for 20&40 MHz packets
5400 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5401 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5402 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5403 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5404 Protect[2] = ProtCfg.word;
5405 Protect[3] = ProtCfg4.word;
5406 Protect[4] = ProtCfg.word;
5407 Protect[5] = ProtCfg4.word;
5408 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5412 // Special on for Atheros problem n chip.
5413 Protect[2] = 0x01754004;
5414 Protect[3] = 0x03f54084;
5415 Protect[4] = 0x01754004;
5416 Protect[5] = 0x03f54084;
5417 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5422 offset = CCK_PROT_CFG;
5423 for (i = 0;i < 6;i++)
5425 if ((SetMask & (1<< i)))
5427 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5433 ==========================================================================
5436 IRQL = PASSIVE_LEVEL
5437 IRQL = DISPATCH_LEVEL
5439 ==========================================================================
5441 VOID AsicSwitchChannel(
5442 IN PRTMP_ADAPTER pAd,
5446 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5447 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5449 UINT32 Value = 0; //BbpReg, Value;
5450 RTMP_RF_REGS *RFRegTable;
5452 // Search Tx power value
5453 for (index = 0; index < pAd->ChannelListNum; index++)
5455 if (Channel == pAd->ChannelList[index].Channel)
5457 TxPwer = pAd->ChannelList[index].Power;
5458 TxPwer2 = pAd->ChannelList[index].Power2;
5463 if (index == MAX_NUM_OF_CHANNELS)
5465 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5469 RFRegTable = RF2850RegTable;
5471 switch (pAd->RfIcType)
5478 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5480 if (Channel == RFRegTable[index].Channel)
5482 R2 = RFRegTable[index].R2;
5483 if (pAd->Antenna.field.TxPath == 1)
5485 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5488 if (pAd->Antenna.field.RxPath == 2)
5490 R2 |= 0x40; // write 1 to off Rxpath.
5492 else if (pAd->Antenna.field.RxPath == 1)
5494 R2 |= 0x20040; // write 1 to off RxPath
5499 // initialize R3, R4
5500 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5501 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5503 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5505 if ((TxPwer >= -7) && (TxPwer < 0))
5507 TxPwer = (7+TxPwer);
5508 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5509 R3 |= (TxPwer << 10);
5510 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5514 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5515 R3 |= (TxPwer << 10) | (1 << 9);
5519 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5521 TxPwer2 = (7+TxPwer2);
5522 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5523 R4 |= (TxPwer2 << 7);
5524 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5528 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5529 R4 |= (TxPwer2 << 7) | (1 << 6);
5534 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5535 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5538 // Based on BBP current mode before changing RF channel.
5539 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5545 pAd->LatchRfRegs.Channel = Channel;
5546 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5547 pAd->LatchRfRegs.R2 = R2;
5548 pAd->LatchRfRegs.R3 = R3;
5549 pAd->LatchRfRegs.R4 = R4;
5551 // Set RF value 1's set R3[bit2] = [0]
5552 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5553 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5554 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5555 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5559 // Set RF value 2's set R3[bit2] = [1]
5560 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5561 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5562 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5563 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5567 // Set RF value 3's set R3[bit2] = [0]
5568 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5569 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5570 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5571 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5583 // Change BBP setting during siwtch from a->g, g->a
5586 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5588 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5589 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5590 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5591 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.
5592 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5594 // Rx High power VGA offset for LNA select
5595 if (pAd->NicConfig2.field.ExternalLNAForG)
5597 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5598 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5602 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5603 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5606 // 5G band selection PIN, bit1 and bit2 are complement
5607 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5610 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5612 // Turn off unused PA or LNA when only 1T or 1R
5613 if (pAd->Antenna.field.TxPath == 1)
5615 TxPinCfg &= 0xFFFFFFF3;
5617 if (pAd->Antenna.field.RxPath == 1)
5619 TxPinCfg &= 0xFFFFF3FF;
5622 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5626 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5628 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5629 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5630 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5631 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.
5632 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5634 // Rx High power VGA offset for LNA select
5635 if (pAd->NicConfig2.field.ExternalLNAForA)
5637 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5641 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5644 // 5G band selection PIN, bit1 and bit2 are complement
5645 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5648 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5650 // Turn off unused PA or LNA when only 1T or 1R
5651 if (pAd->Antenna.field.TxPath == 1)
5653 TxPinCfg &= 0xFFFFFFF3;
5655 if (pAd->Antenna.field.RxPath == 1)
5657 TxPinCfg &= 0xFFFFF3FF;
5660 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5663 // R66 should be set according to Channel and use 20MHz when scanning
5664 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5666 RTMPSetAGCInitValue(pAd, BW_20);
5668 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5671 // On 11A, We should delay and wait RF/BBP to be stable
5672 // and the appropriate time should be 1000 micro seconds
5673 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5675 RTMPusecDelay(1000);
5677 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",
5680 (R3 & 0x00003e00) >> 9,
5681 (R4 & 0x000007c0) >> 6,
5682 pAd->Antenna.field.TxPath,
5683 pAd->LatchRfRegs.R1,
5684 pAd->LatchRfRegs.R2,
5685 pAd->LatchRfRegs.R3,
5686 pAd->LatchRfRegs.R4));
5690 ==========================================================================
5692 This function is required for 2421 only, and should not be used during
5693 site survey. It's only required after NIC decided to stay at a channel
5694 for a longer period.
5695 When this function is called, it's always after AsicSwitchChannel().
5697 IRQL = PASSIVE_LEVEL
5698 IRQL = DISPATCH_LEVEL
5700 ==========================================================================
5702 VOID AsicLockChannel(
5703 IN PRTMP_ADAPTER pAd,
5709 ==========================================================================
5712 IRQL = PASSIVE_LEVEL
5713 IRQL = DISPATCH_LEVEL
5715 ==========================================================================
5717 VOID AsicAntennaSelect(
5718 IN PRTMP_ADAPTER pAd,
5724 ========================================================================
5726 Routine Description:
5727 Antenna miscellaneous setting.
5730 pAd Pointer to our adapter
5731 BandState Indicate current Band State.
5736 IRQL <= DISPATCH_LEVEL
5739 1.) Frame End type control
5740 only valid for G only (RF_2527 & RF_2529)
5741 0: means DPDT, set BBP R4 bit 5 to 1
5742 1: means SPDT, set BBP R4 bit 5 to 0
5745 ========================================================================
5747 VOID AsicAntennaSetting(
5748 IN PRTMP_ADAPTER pAd,
5749 IN ABGBAND_STATE BandState)
5753 VOID AsicRfTuningExec(
5754 IN PVOID SystemSpecific1,
5755 IN PVOID FunctionContext,
5756 IN PVOID SystemSpecific2,
5757 IN PVOID SystemSpecific3)
5762 ==========================================================================
5764 Gives CCK TX rate 2 more dB TX power.
5765 This routine works only in LINK UP in INFRASTRUCTURE mode.
5767 calculate desired Tx power in RF R3.Tx0~5, should consider -
5768 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5769 1. TxPowerPercentage
5770 2. auto calibration based on TSSI feedback
5771 3. extra 2 db for CCK
5772 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5774 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5775 it should be called AFTER MlmeDynamicTxRatSwitching()
5776 ==========================================================================
5778 VOID AsicAdjustTxPower(
5779 IN PRTMP_ADAPTER pAd)
5783 BOOLEAN bAutoTxAgc = FALSE;
5784 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5785 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5786 PCHAR pTxAgcCompensate;
5790 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5791 || (pAd->bPCIclkOff == TRUE)
5792 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
5793 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
5796 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5798 if (pAd->CommonCfg.CentralChannel > 14)
5800 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5801 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5802 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5803 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5804 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5808 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5809 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5810 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5811 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5812 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5817 if (pAd->CommonCfg.Channel > 14)
5819 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5820 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5821 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5822 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5823 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5827 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5828 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5829 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5830 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5831 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5835 // TX power compensation for temperature variation based on TSSI. try every 4 second
5836 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5838 if (pAd->CommonCfg.Channel <= 14)
5841 bAutoTxAgc = pAd->bAutoTxAgcG;
5842 TssiRef = pAd->TssiRefG;
5843 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5844 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5845 TxAgcStep = pAd->TxAgcStepG;
5846 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5851 bAutoTxAgc = pAd->bAutoTxAgcA;
5852 TssiRef = pAd->TssiRefA;
5853 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
5854 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
5855 TxAgcStep = pAd->TxAgcStepA;
5856 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5861 /* BbpR1 is unsigned char */
5862 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
5864 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
5865 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
5866 /* step value is defined in pAd->TxAgcStepG for tx power value */
5868 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
5869 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
5870 above value are examined in mass factory production */
5871 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
5873 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
5874 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
5875 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
5877 if (BbpR49 > pTssiMinusBoundary[1])
5879 // Reading is larger than the reference value
5880 // check for how large we need to decrease the Tx power
5881 for (idx = 1; idx < 5; idx++)
5883 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
5886 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
5887 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
5889 DeltaPwr += (*pTxAgcCompensate);
5890 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
5891 BbpR49, TssiRef, TxAgcStep, idx-1));
5893 else if (BbpR49 < pTssiPlusBoundary[1])
5895 // Reading is smaller than the reference value
5896 // check for how large we need to increase the Tx power
5897 for (idx = 1; idx < 5; idx++)
5899 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
5902 // The index is the step we should increase, idx = 0 means there is nothing to compensate
5903 *pTxAgcCompensate = TxAgcStep * (idx-1);
5904 DeltaPwr += (*pTxAgcCompensate);
5905 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5906 BbpR49, TssiRef, TxAgcStep, idx-1));
5910 *pTxAgcCompensate = 0;
5911 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5912 BbpR49, TssiRef, TxAgcStep, 0));
5918 if (pAd->CommonCfg.Channel <= 14)
5920 bAutoTxAgc = pAd->bAutoTxAgcG;
5921 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5925 bAutoTxAgc = pAd->bAutoTxAgcA;
5926 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5930 DeltaPwr += (*pTxAgcCompensate);
5933 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
5936 /* calculate delta power based on the percentage specified from UI */
5937 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
5938 // We lower TX power here according to the percentage specified from UI
5939 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
5941 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
5943 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
5947 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
5951 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
5955 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
5960 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
5965 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
5967 /* reset different new tx power for different TX rate */
5970 if (TxPwr[i] != 0xffffffff)
5974 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
5976 if ((Value + DeltaPwr) < 0)
5978 Value = 0; /* min */
5980 else if ((Value + DeltaPwr) > 0xF)
5982 Value = 0xF; /* max */
5986 Value += DeltaPwr; /* temperature compensation */
5989 /* fill new value to CSR offset */
5990 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
5993 /* write tx power value to CSR */
5994 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
5995 TX power for OFDM 6M/9M
5996 TX power for CCK5.5M/11M
5997 TX power for CCK1M/2M */
5998 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
5999 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6006 ==========================================================================
6008 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6009 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6010 the wakeup timer timeout. Driver has to issue a separate command to wake
6013 IRQL = DISPATCH_LEVEL
6015 ==========================================================================
6017 VOID AsicSleepThenAutoWakeup(
6018 IN PRTMP_ADAPTER pAd,
6019 IN USHORT TbttNumToNextWakeUp)
6021 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6025 ==========================================================================
6027 AsicForceWakeup() is used whenever manual wakeup is required
6028 AsicForceSleep() should only be used when not in INFRA BSS. When
6029 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6030 ==========================================================================
6032 VOID AsicForceSleep(
6033 IN PRTMP_ADAPTER pAd)
6039 ==========================================================================
6041 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6044 IRQL = PASSIVE_LEVEL
6045 IRQL = DISPATCH_LEVEL
6046 ==========================================================================
6048 VOID AsicForceWakeup(
6049 IN PRTMP_ADAPTER pAd,
6052 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6053 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6057 ==========================================================================
6061 IRQL = DISPATCH_LEVEL
6063 ==========================================================================
6066 IN PRTMP_ADAPTER pAd,
6070 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6071 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6073 Addr4 = (ULONG)(pBssid[0]) |
6074 (ULONG)(pBssid[1] << 8) |
6075 (ULONG)(pBssid[2] << 16) |
6076 (ULONG)(pBssid[3] << 24);
6077 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6080 // always one BSSID in STA mode
6081 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6083 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6086 VOID AsicSetMcastWC(
6087 IN PRTMP_ADAPTER pAd)
6089 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6092 pEntry->Sst = SST_ASSOC;
6093 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6094 pEntry->PsMode = PWR_ACTIVE;
6095 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6096 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6100 ==========================================================================
6103 IRQL = DISPATCH_LEVEL
6105 ==========================================================================
6107 VOID AsicDelWcidTab(
6108 IN PRTMP_ADAPTER pAd,
6111 ULONG Addr0 = 0x0, Addr1 = 0x0;
6114 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6115 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6116 RTMP_IO_WRITE32(pAd, offset, Addr0);
6118 RTMP_IO_WRITE32(pAd, offset, Addr1);
6122 ==========================================================================
6125 IRQL = DISPATCH_LEVEL
6127 ==========================================================================
6130 IN PRTMP_ADAPTER pAd)
6132 TX_LINK_CFG_STRUC TxLinkCfg;
6135 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6136 TxLinkCfg.field.TxRDGEn = 1;
6137 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6139 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6142 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6144 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6148 ==========================================================================
6151 IRQL = DISPATCH_LEVEL
6153 ==========================================================================
6155 VOID AsicDisableRDG(
6156 IN PRTMP_ADAPTER pAd)
6158 TX_LINK_CFG_STRUC TxLinkCfg;
6162 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6163 TxLinkCfg.field.TxRDGEn = 0;
6164 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6166 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6169 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6170 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6173 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6174 if (pAd->CommonCfg.bEnableTxBurst)
6177 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6181 ==========================================================================
6184 IRQL = PASSIVE_LEVEL
6185 IRQL = DISPATCH_LEVEL
6187 ==========================================================================
6189 VOID AsicDisableSync(
6190 IN PRTMP_ADAPTER pAd)
6192 BCN_TIME_CFG_STRUC csr;
6194 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6196 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6197 // that NIC will never wakes up because TSF stops and no more
6199 pAd->TbttTickCount = 0;
6200 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6201 csr.field.bBeaconGen = 0;
6202 csr.field.bTBTTEnable = 0;
6203 csr.field.TsfSyncMode = 0;
6204 csr.field.bTsfTicking = 0;
6205 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6210 ==========================================================================
6213 IRQL = DISPATCH_LEVEL
6215 ==========================================================================
6217 VOID AsicEnableBssSync(
6218 IN PRTMP_ADAPTER pAd)
6220 BCN_TIME_CFG_STRUC csr;
6222 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6224 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6226 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6228 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6229 csr.field.bTsfTicking = 1;
6230 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6231 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6232 csr.field.bTBTTEnable = 1;
6235 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6239 ==========================================================================
6242 BEACON frame in shared memory should be built ok before this routine
6243 can be called. Otherwise, a garbage frame maybe transmitted out every
6246 IRQL = DISPATCH_LEVEL
6248 ==========================================================================
6250 VOID AsicEnableIbssSync(
6251 IN PRTMP_ADAPTER pAd)
6253 BCN_TIME_CFG_STRUC csr9;
6257 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6259 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6260 csr9.field.bBeaconGen = 0;
6261 csr9.field.bTBTTEnable = 0;
6262 csr9.field.bTsfTicking = 0;
6263 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6265 // move BEACON TXD and frame content to on-chip memory
6266 ptr = (PUCHAR)&pAd->BeaconTxWI;
6267 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6269 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6270 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6274 // start right after the 16-byte TXWI field
6275 ptr = pAd->BeaconBuf;
6276 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6278 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6279 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6283 // start sending BEACON
6284 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6285 csr9.field.bTsfTicking = 1;
6286 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6287 csr9.field.bTBTTEnable = 1;
6288 csr9.field.bBeaconGen = 1;
6289 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6293 ==========================================================================
6296 IRQL = PASSIVE_LEVEL
6297 IRQL = DISPATCH_LEVEL
6299 ==========================================================================
6301 VOID AsicSetEdcaParm(
6302 IN PRTMP_ADAPTER pAd,
6303 IN PEDCA_PARM pEdcaParm)
6305 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6306 AC_TXOP_CSR0_STRUC csr0;
6307 AC_TXOP_CSR1_STRUC csr1;
6308 AIFSN_CSR_STRUC AifsnCsr;
6309 CWMIN_CSR_STRUC CwminCsr;
6310 CWMAX_CSR_STRUC CwmaxCsr;
6317 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6319 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6320 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6321 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6323 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6324 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6327 //========================================================
6328 // MAC Register has a copy .
6329 //========================================================
6330 if( pAd->CommonCfg.bEnableTxBurst )
6332 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6333 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6336 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6337 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6338 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6339 Ac0Cfg.field.Aifsn = 2;
6340 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6342 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6343 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6344 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6345 Ac1Cfg.field.Aifsn = 2;
6346 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6348 if (pAd->CommonCfg.PhyMode == PHY_11B)
6350 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6351 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6355 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6356 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6358 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6359 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6360 Ac2Cfg.field.Aifsn = 2;
6361 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6362 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6363 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6364 Ac3Cfg.field.Aifsn = 2;
6365 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6367 //========================================================
6368 // DMA Register has a copy too.
6369 //========================================================
6370 csr0.field.Ac0Txop = 0; // QID_AC_BE
6371 csr0.field.Ac1Txop = 0; // QID_AC_BK
6372 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6373 if (pAd->CommonCfg.PhyMode == PHY_11B)
6375 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6376 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6380 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6381 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6383 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6386 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6387 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6388 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6389 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6390 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6393 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6394 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6395 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6396 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6397 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6399 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6401 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6405 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6406 //========================================================
6407 // MAC Register has a copy.
6408 //========================================================
6410 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6411 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6413 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6415 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6416 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6417 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6418 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6420 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6421 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6422 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6423 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6425 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6426 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6427 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6428 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6430 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6432 // Tuning for Wi-Fi WMM S06
6433 if (pAd->CommonCfg.bWiFiTest &&
6434 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6435 Ac2Cfg.field.Aifsn -= 1;
6437 // Tuning for TGn Wi-Fi 5.2.32
6438 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6439 if (STA_TGN_WIFI_ON(pAd) &&
6440 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6442 Ac0Cfg.field.Aifsn = 3;
6443 Ac2Cfg.field.AcTxop = 5;
6447 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6448 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6449 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6450 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6453 if (pAd->CommonCfg.bWiFiTest)
6455 if (Ac3Cfg.field.AcTxop == 102)
6457 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6458 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6459 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6460 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6461 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6464 //#endif // WIFI_TEST //
6466 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6467 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6468 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6469 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6472 //========================================================
6473 // DMA Register has a copy too.
6474 //========================================================
6475 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6476 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6477 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6479 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6480 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6481 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6484 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6485 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6486 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6488 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6489 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6491 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6494 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6495 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6496 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6497 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6498 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6501 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6502 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6503 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6505 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6507 // Tuning for Wi-Fi WMM S06
6508 if (pAd->CommonCfg.bWiFiTest &&
6509 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6510 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6512 // Tuning for TGn Wi-Fi 5.2.32
6513 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6514 if (STA_TGN_WIFI_ON(pAd) &&
6515 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6517 AifsnCsr.field.Aifsn0 = 3;
6518 AifsnCsr.field.Aifsn2 = 7;
6522 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6523 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6525 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6527 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6530 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6531 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6532 pEdcaParm->Aifsn[0],
6533 pEdcaParm->Cwmin[0],
6534 pEdcaParm->Cwmax[0],
6535 pEdcaParm->Txop[0]<<5,
6536 pEdcaParm->bACM[0]));
6537 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6538 pEdcaParm->Aifsn[1],
6539 pEdcaParm->Cwmin[1],
6540 pEdcaParm->Cwmax[1],
6541 pEdcaParm->Txop[1]<<5,
6542 pEdcaParm->bACM[1]));
6543 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6544 pEdcaParm->Aifsn[2],
6545 pEdcaParm->Cwmin[2],
6546 pEdcaParm->Cwmax[2],
6547 pEdcaParm->Txop[2]<<5,
6548 pEdcaParm->bACM[2]));
6549 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6550 pEdcaParm->Aifsn[3],
6551 pEdcaParm->Cwmin[3],
6552 pEdcaParm->Cwmax[3],
6553 pEdcaParm->Txop[3]<<5,
6554 pEdcaParm->bACM[3]));
6560 ==========================================================================
6563 IRQL = PASSIVE_LEVEL
6564 IRQL = DISPATCH_LEVEL
6566 ==========================================================================
6568 VOID AsicSetSlotTime(
6569 IN PRTMP_ADAPTER pAd,
6570 IN BOOLEAN bUseShortSlotTime)
6573 UINT32 RegValue = 0;
6575 if (pAd->CommonCfg.Channel > 14)
6576 bUseShortSlotTime = TRUE;
6578 if (bUseShortSlotTime)
6579 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6581 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6583 SlotTime = (bUseShortSlotTime)? 9 : 20;
6585 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6587 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6588 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6589 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6592 // In this case, we will think it is doing Wi-Fi test
6593 // And we will not set to short slot when bEnableTxBurst is TRUE.
6595 else if (pAd->CommonCfg.bEnableTxBurst)
6600 // For some reasons, always set it to short slot time.
6602 // ToDo: Should consider capability with 11B
6604 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6606 if (pAd->StaCfg.BssType == BSS_ADHOC)
6610 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6611 RegValue = RegValue & 0xFFFFFF00;
6613 RegValue |= SlotTime;
6615 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6619 ========================================================================
6621 Add Shared key information into ASIC.
6622 Update shared key, TxMic and RxMic to Asic Shared key table
6623 Update its cipherAlg to Asic Shared key Mode.
6626 ========================================================================
6628 VOID AsicAddSharedKeyEntry(
6629 IN PRTMP_ADAPTER pAd,
6637 ULONG offset; //, csr0;
6638 SHAREDKEY_MODE_STRUC csr1;
6641 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6642 //============================================================================================
6644 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6645 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6646 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]));
6649 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6650 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6654 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6655 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6657 //============================================================================================
6659 // fill key material - key + TX MIC + RX MIC
6661 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6662 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6664 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6667 offset += MAX_LEN_OF_SHARE_KEY;
6672 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6681 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6687 // Update cipher algorithm. WSTA always use BSS0
6689 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6690 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6691 if ((BssIndex%2) == 0)
6694 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6695 else if (KeyIdx == 1)
6696 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6697 else if (KeyIdx == 2)
6698 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6700 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6705 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6706 else if (KeyIdx == 1)
6707 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6708 else if (KeyIdx == 2)
6709 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6711 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6713 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6714 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6718 // IRQL = DISPATCH_LEVEL
6719 VOID AsicRemoveSharedKeyEntry(
6720 IN PRTMP_ADAPTER pAd,
6725 SHAREDKEY_MODE_STRUC csr1;
6727 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6729 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6730 if ((BssIndex%2) == 0)
6733 csr1.field.Bss0Key0CipherAlg = 0;
6734 else if (KeyIdx == 1)
6735 csr1.field.Bss0Key1CipherAlg = 0;
6736 else if (KeyIdx == 2)
6737 csr1.field.Bss0Key2CipherAlg = 0;
6739 csr1.field.Bss0Key3CipherAlg = 0;
6744 csr1.field.Bss1Key0CipherAlg = 0;
6745 else if (KeyIdx == 1)
6746 csr1.field.Bss1Key1CipherAlg = 0;
6747 else if (KeyIdx == 2)
6748 csr1.field.Bss1Key2CipherAlg = 0;
6750 csr1.field.Bss1Key3CipherAlg = 0;
6752 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6753 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6754 ASSERT(BssIndex < 4);
6760 VOID AsicUpdateWCIDAttribute(
6761 IN PRTMP_ADAPTER pAd,
6765 IN BOOLEAN bUsePairewiseKeyTable)
6767 ULONG WCIDAttri = 0, offset;
6770 // Update WCID attribute.
6771 // Only TxKey could update WCID attribute.
6773 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6774 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6775 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6778 VOID AsicUpdateWCIDIVEIV(
6779 IN PRTMP_ADAPTER pAd,
6786 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6788 RTMP_IO_WRITE32(pAd, offset, uIV);
6789 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6792 VOID AsicUpdateRxWCIDTable(
6793 IN PRTMP_ADAPTER pAd,
6800 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6801 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6802 RTMP_IO_WRITE32(pAd, offset, Addr);
6803 Addr = pAddr[4] + (pAddr[5] << 8);
6804 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6809 ========================================================================
6811 Routine Description:
6812 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6815 pAd Pointer to our adapter
6816 WCID WCID Entry number.
6817 BssIndex BSSID index, station or none multiple BSSID support
6818 this value should be 0.
6819 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6820 pCipherKey Pointer to Cipher Key.
6821 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6822 otherwise PairewiseKey table
6823 bTxKey This is the transmit key if enabled.
6829 This routine will set the relative key stuff to Asic including WCID attribute,
6830 Cipher Key, Cipher algorithm and IV/EIV.
6832 IV/EIV will be update if this CipherKey is the transmission key because
6833 ASIC will base on IV's KeyID value to select Cipher Key.
6835 If bTxKey sets to FALSE, this is not the TX key, but it could be
6838 For AP mode bTxKey must be always set to TRUE.
6839 ========================================================================
6841 VOID AsicAddKeyEntry(
6842 IN PRTMP_ADAPTER pAd,
6846 IN PCIPHER_KEY pCipherKey,
6847 IN BOOLEAN bUsePairewiseKeyTable,
6852 PUCHAR pKey = pCipherKey->Key;
6853 PUCHAR pTxMic = pCipherKey->TxMic;
6854 PUCHAR pRxMic = pCipherKey->RxMic;
6855 PUCHAR pTxtsc = pCipherKey->TxTsc;
6856 UCHAR CipherAlg = pCipherKey->CipherAlg;
6857 SHAREDKEY_MODE_STRUC csr1;
6860 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
6862 // 1.) decide key table offset
6864 if (bUsePairewiseKeyTable)
6865 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6867 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
6870 // 2.) Set Key to Asic
6872 //for (i = 0; i < KeyLen; i++)
6873 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
6875 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6877 offset += MAX_LEN_OF_PEER_KEY;
6880 // 3.) Set MIC key if available
6884 for (i = 0; i < 8; i++)
6886 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6889 offset += LEN_TKIP_TXMICK;
6893 for (i = 0; i < 8; i++)
6895 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6901 // 4.) Modify IV/EIV if needs
6902 // This will force Asic to use this key ID by setting IV.
6906 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6910 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
6911 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
6912 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
6914 IV4 = (KeyIdx << 6);
6915 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
6916 IV4 |= 0x20; // turn on extension bit means EIV existence
6918 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
6924 for (i = 0; i < 4; i++)
6926 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
6929 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
6932 if (!bUsePairewiseKeyTable)
6935 // Only update the shared key security mode
6937 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
6938 if ((BssIndex % 2) == 0)
6941 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6942 else if (KeyIdx == 1)
6943 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6944 else if (KeyIdx == 2)
6945 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6947 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6952 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6953 else if (KeyIdx == 1)
6954 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6955 else if (KeyIdx == 2)
6956 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6958 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6960 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
6963 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
6968 ========================================================================
6970 Add Pair-wise key material into ASIC.
6971 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
6974 ========================================================================
6976 VOID AsicAddPairwiseKeyEntry(
6977 IN PRTMP_ADAPTER pAd,
6980 IN CIPHER_KEY *pCipherKey)
6984 PUCHAR pKey = pCipherKey->Key;
6985 PUCHAR pTxMic = pCipherKey->TxMic;
6986 PUCHAR pRxMic = pCipherKey->RxMic;
6988 UCHAR CipherAlg = pCipherKey->CipherAlg;
6992 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6993 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
6995 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6997 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7000 RTMP_IO_READ32(pAd, offset + i, &Value);
7003 offset += MAX_LEN_OF_PEER_KEY;
7010 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7018 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7022 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7023 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7024 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]));
7027 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7028 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7032 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7033 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7037 ========================================================================
7039 Remove Pair-wise key material from ASIC.
7042 ========================================================================
7044 VOID AsicRemovePairwiseKeyEntry(
7045 IN PRTMP_ADAPTER pAd,
7052 // re-set the entry's WCID attribute as OPEN-NONE.
7053 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7054 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7055 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7058 BOOLEAN AsicSendCommandToMcu(
7059 IN PRTMP_ADAPTER pAd,
7065 HOST_CMD_CSR_STRUC H2MCmd;
7066 H2M_MAILBOX_STRUC H2MMailbox;
7071 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7072 if (H2MMailbox.field.Owner == 0)
7084 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7086 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7088 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7089 // Reset DMA/CPU ring index
7090 RTMPRingCleanUp(pAd, QID_AC_BK);
7091 RTMPRingCleanUp(pAd, QID_AC_BE);
7092 RTMPRingCleanUp(pAd, QID_AC_VI);
7093 RTMPRingCleanUp(pAd, QID_AC_VO);
7094 RTMPRingCleanUp(pAd, QID_HCCA);
7095 RTMPRingCleanUp(pAd, QID_MGMT);
7096 RTMPRingCleanUp(pAd, QID_RX);
7099 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7101 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7102 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7107 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7108 H2MMailbox.field.CmdToken = Token;
7109 H2MMailbox.field.HighByte = Arg1;
7110 H2MMailbox.field.LowByte = Arg0;
7111 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7114 H2MCmd.field.HostCommand = Command;
7115 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7117 if (Command != 0x80)
7124 BOOLEAN AsicCheckCommanOk(
7125 IN PRTMP_ADAPTER pAd,
7128 UINT32 CmdStatus = 0, CID = 0, i;
7129 UINT32 ThisCIDMask = 0;
7134 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7135 // Find where the command is. Because this is randomly specified by firmware.
7136 if ((CID & CID0MASK) == Command)
7138 ThisCIDMask = CID0MASK;
7141 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7143 ThisCIDMask = CID1MASK;
7146 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7148 ThisCIDMask = CID2MASK;
7151 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7153 ThisCIDMask = CID3MASK;
7161 // Get CommandStatus Value
7162 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7164 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7167 // If Status is 1, the comamnd is success.
7168 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7169 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7171 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7172 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7173 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7176 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7180 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7182 // Clear Command and Status.
7183 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7184 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7190 ========================================================================
7192 Routine Description:
7193 Verify the support rate for different PHY type
7196 pAd Pointer to our adapter
7201 IRQL = PASSIVE_LEVEL
7203 ========================================================================
7205 VOID RTMPCheckRates(
7206 IN PRTMP_ADAPTER pAd,
7207 IN OUT UCHAR SupRate[],
7208 IN OUT UCHAR *SupRateLen)
7210 UCHAR RateIdx, i, j;
7211 UCHAR NewRate[12], NewRateLen;
7215 if (pAd->CommonCfg.PhyMode == PHY_11B)
7220 // Check for support rates exclude basic rate bit
7221 for (i = 0; i < *SupRateLen; i++)
7222 for (j = 0; j < RateIdx; j++)
7223 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7224 NewRate[NewRateLen++] = SupRate[i];
7226 *SupRateLen = NewRateLen;
7227 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7230 BOOLEAN RTMPCheckChannel(
7231 IN PRTMP_ADAPTER pAd,
7232 IN UCHAR CentralChannel,
7236 UCHAR UpperChannel = 0, LowerChannel = 0;
7237 UCHAR NoEffectChannelinList = 0;
7239 // Find upper and lower channel according to 40MHz current operation.
7240 if (CentralChannel < Channel)
7242 UpperChannel = Channel;
7243 if (CentralChannel > 2)
7244 LowerChannel = CentralChannel - 2;
7248 else if (CentralChannel > Channel)
7250 UpperChannel = CentralChannel + 2;
7251 LowerChannel = Channel;
7254 for (k = 0;k < pAd->ChannelListNum;k++)
7256 if (pAd->ChannelList[k].Channel == UpperChannel)
7258 NoEffectChannelinList ++;
7260 if (pAd->ChannelList[k].Channel == LowerChannel)
7262 NoEffectChannelinList ++;
7266 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7267 if (NoEffectChannelinList == 2)
7274 ========================================================================
7276 Routine Description:
7277 Verify the support rate for HT phy type
7280 pAd Pointer to our adapter
7283 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7285 IRQL = PASSIVE_LEVEL
7287 ========================================================================
7289 BOOLEAN RTMPCheckHt(
7290 IN PRTMP_ADAPTER pAd,
7292 IN HT_CAPABILITY_IE *pHtCapability,
7293 IN ADD_HT_INFO_IE *pAddHtInfo)
7295 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7298 // If use AMSDU, set flag.
7299 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7300 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7301 // Save Peer Capability
7302 if (pHtCapability->HtCapInfo.ShortGIfor20)
7303 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7304 if (pHtCapability->HtCapInfo.ShortGIfor40)
7305 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7306 if (pHtCapability->HtCapInfo.TxSTBC)
7307 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7308 if (pHtCapability->HtCapInfo.RxSTBC)
7309 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7310 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7312 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7315 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7317 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7320 // Will check ChannelWidth for MCSSet[4] below
7321 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7322 switch (pAd->CommonCfg.RxStream)
7325 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7326 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7327 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7328 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7331 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7332 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7333 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7334 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7337 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7338 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7339 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7340 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7344 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7346 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7347 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7348 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7350 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7352 // Send Assoc Req with my HT capability.
7353 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7354 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7355 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7356 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7357 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7358 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7359 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7360 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7361 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7362 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7363 if (pAd->CommonCfg.bRdg)
7365 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7366 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7369 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7370 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7372 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7377 ========================================================================
7379 Routine Description:
7380 Verify the support rate for different PHY type
7383 pAd Pointer to our adapter
7388 IRQL = PASSIVE_LEVEL
7390 ========================================================================
7392 VOID RTMPUpdateMlmeRate(
7393 IN PRTMP_ADAPTER pAd)
7396 UCHAR ProperMlmeRate; //= RATE_54;
7397 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7398 BOOLEAN bMatch = FALSE;
7400 switch (pAd->CommonCfg.PhyMode)
7403 ProperMlmeRate = RATE_11;
7404 MinimumRate = RATE_1;
7406 case PHY_11BG_MIXED:
7407 case PHY_11ABGN_MIXED:
7408 case PHY_11BGN_MIXED:
7409 if ((pAd->MlmeAux.SupRateLen == 4) &&
7410 (pAd->MlmeAux.ExtRateLen == 0))
7412 ProperMlmeRate = RATE_11;
7414 ProperMlmeRate = RATE_24;
7416 if (pAd->MlmeAux.Channel <= 14)
7417 MinimumRate = RATE_1;
7419 MinimumRate = RATE_6;
7422 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7423 case PHY_11GN_MIXED:
7424 case PHY_11AGN_MIXED:
7425 case PHY_11AN_MIXED:
7427 ProperMlmeRate = RATE_24;
7428 MinimumRate = RATE_6;
7430 case PHY_11ABG_MIXED:
7431 ProperMlmeRate = RATE_24;
7432 if (pAd->MlmeAux.Channel <= 14)
7433 MinimumRate = RATE_1;
7435 MinimumRate = RATE_6;
7438 ProperMlmeRate = RATE_1;
7439 MinimumRate = RATE_1;
7443 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7445 for (j = 0; j < RateIdx; j++)
7447 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7449 if (j == ProperMlmeRate)
7461 if (bMatch == FALSE)
7463 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7465 for (j = 0; j < RateIdx; j++)
7467 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7469 if (j == ProperMlmeRate)
7482 if (bMatch == FALSE)
7484 ProperMlmeRate = MinimumRate;
7487 pAd->CommonCfg.MlmeRate = MinimumRate;
7488 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7489 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7491 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7492 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7493 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7494 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7498 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7499 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7500 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7501 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7504 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7508 IN PRTMP_ADAPTER pAd,
7515 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7520 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7522 larger = max(Rssi0, Rssi1);
7525 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7527 larger = max(larger, Rssi2);
7537 ========================================================================
7538 Routine Description:
7539 Periodic evaluate antenna link status
7542 pAd - Adapter pointer
7547 ========================================================================
7549 VOID AsicEvaluateRxAnt(
7550 IN PRTMP_ADAPTER pAd)
7554 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7556 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7557 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7558 fRTMP_ADAPTER_RADIO_OFF |
7559 fRTMP_ADAPTER_NIC_NOT_EXIST |
7560 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7563 if (pAd->StaCfg.Psm == PWR_SAVE)
7567 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7569 if(pAd->Antenna.field.RxPath == 3)
7573 else if(pAd->Antenna.field.RxPath == 2)
7577 else if(pAd->Antenna.field.RxPath == 1)
7581 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7583 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7584 pAd->StaCfg.BBPR3 = BBPR3;
7586 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7589 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7590 pAd->RalinkCounters.OneSecTxRetryOkCount +
7591 pAd->RalinkCounters.OneSecTxFailCount;
7593 if (TxTotalCnt > 50)
7595 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7596 pAd->Mlme.bLowThroughput = FALSE;
7600 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7601 pAd->Mlme.bLowThroughput = TRUE;
7607 ========================================================================
7608 Routine Description:
7609 After evaluation, check antenna link status
7612 pAd - Adapter pointer
7617 ========================================================================
7619 VOID AsicRxAntEvalTimeout(
7620 IN PVOID SystemSpecific1,
7621 IN PVOID FunctionContext,
7622 IN PVOID SystemSpecific2,
7623 IN PVOID SystemSpecific3)
7625 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7627 CHAR larger = -127, rssi0, rssi1, rssi2;
7629 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7631 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7632 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7633 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7634 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7637 if (pAd->StaCfg.Psm == PWR_SAVE)
7641 // if the traffic is low, use average rssi as the criteria
7642 if (pAd->Mlme.bLowThroughput == TRUE)
7644 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7645 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7646 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7650 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7651 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7652 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7655 if(pAd->Antenna.field.RxPath == 3)
7657 larger = max(rssi0, rssi1);
7659 if (larger > (rssi2 + 20))
7660 pAd->Mlme.RealRxPath = 2;
7662 pAd->Mlme.RealRxPath = 3;
7664 else if(pAd->Antenna.field.RxPath == 2)
7666 if (rssi0 > (rssi1 + 20))
7667 pAd->Mlme.RealRxPath = 1;
7669 pAd->Mlme.RealRxPath = 2;
7672 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7674 if(pAd->Mlme.RealRxPath == 3)
7678 else if(pAd->Mlme.RealRxPath == 2)
7682 else if(pAd->Mlme.RealRxPath == 1)
7686 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7687 pAd->StaCfg.BBPR3 = BBPR3;
7693 VOID APSDPeriodicExec(
7694 IN PVOID SystemSpecific1,
7695 IN PVOID FunctionContext,
7696 IN PVOID SystemSpecific2,
7697 IN PVOID SystemSpecific3)
7699 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7701 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7704 pAd->CommonCfg.TriggerTimerCount++;
7709 ========================================================================
7710 Routine Description:
7711 Set/reset MAC registers according to bPiggyBack parameter
7714 pAd - Adapter pointer
7715 bPiggyBack - Enable / Disable Piggy-Back
7720 ========================================================================
7722 VOID RTMPSetPiggyBack(
7723 IN PRTMP_ADAPTER pAd,
7724 IN BOOLEAN bPiggyBack)
7726 TX_LINK_CFG_STRUC TxLinkCfg;
7728 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7730 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7731 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7735 ========================================================================
7736 Routine Description:
7737 check if this entry need to switch rate automatically
7747 ========================================================================
7749 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7750 IN PRTMP_ADAPTER pAd,
7751 IN PMAC_TABLE_ENTRY pEntry)
7753 BOOLEAN result = TRUE;
7755 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7757 // only associated STA counts
7758 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7760 result = pAd->StaCfg.bAutoTxRateSwitch;
7770 BOOLEAN RTMPAutoRateSwitchCheck(
7771 IN PRTMP_ADAPTER pAd)
7773 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7775 if (pAd->StaCfg.bAutoTxRateSwitch)
7784 ========================================================================
7785 Routine Description:
7786 check if this entry need to fix tx legacy rate
7796 ========================================================================
7798 UCHAR RTMPStaFixedTxMode(
7799 IN PRTMP_ADAPTER pAd,
7800 IN PMAC_TABLE_ENTRY pEntry)
7802 UCHAR tx_mode = FIXED_TXMODE_HT;
7804 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7806 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7813 ========================================================================
7814 Routine Description:
7815 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
7825 ========================================================================
7827 VOID RTMPUpdateLegacyTxSetting(
7828 UCHAR fixed_tx_mode,
7829 PMAC_TABLE_ENTRY pEntry)
7831 HTTRANSMIT_SETTING TransmitSetting;
7833 if (fixed_tx_mode == FIXED_TXMODE_HT)
7836 TransmitSetting.word = 0;
7838 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
7839 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
7841 if (fixed_tx_mode == FIXED_TXMODE_CCK)
7843 TransmitSetting.field.MODE = MODE_CCK;
7844 // CCK mode allow MCS 0~3
7845 if (TransmitSetting.field.MCS > MCS_3)
7846 TransmitSetting.field.MCS = MCS_3;
7850 TransmitSetting.field.MODE = MODE_OFDM;
7851 // OFDM mode allow MCS 0~7
7852 if (TransmitSetting.field.MCS > MCS_7)
7853 TransmitSetting.field.MCS = MCS_7;
7856 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
7858 pEntry->HTPhyMode.word = TransmitSetting.word;
7859 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
7860 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
7865 ==========================================================================
7867 dynamic tune BBP R66 to find a balance between sensibility and
7870 IRQL = DISPATCH_LEVEL
7872 ==========================================================================
7874 VOID AsicStaBbpTuning(
7875 IN PRTMP_ADAPTER pAd)
7877 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
7880 // 2860C did not support Fase CCA, therefore can't tune
7881 if (pAd->MACVersion == 0x28600100)
7887 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
7890 if ((pAd->OpMode == OPMODE_STA)
7891 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7893 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
7894 && (pAd->bPCIclkOff == FALSE))
7896 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
7899 if (pAd->Antenna.field.RxPath > 1)
7900 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
7902 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
7904 if (pAd->LatchRfRegs.Channel <= 14)
7907 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7909 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
7910 if (OrigR66Value != R66)
7912 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7917 R66 = 0x2E + GET_LNA_GAIN(pAd);
7918 if (OrigR66Value != R66)
7920 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7927 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
7929 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7931 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
7932 if (OrigR66Value != R66)
7934 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7939 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
7940 if (OrigR66Value != R66)
7942 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7948 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7950 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
7951 if (OrigR66Value != R66)
7953 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7958 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
7959 if (OrigR66Value != R66)
7961 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7971 VOID AsicResetFromDMABusy(
7972 IN PRTMP_ADAPTER pAd)
7975 BOOLEAN bCtrl = FALSE;
7977 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
7979 // Be sure restore link control value so we can write register.
7980 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
7981 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
7983 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
7984 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
7985 RTMPusecDelay(6000);
7986 pAd->bPCIclkOff = FALSE;
7990 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7992 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7994 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7995 // Reset DMA/CPU ring index
7996 RTMPRingCleanUp(pAd, QID_AC_BK);
7997 RTMPRingCleanUp(pAd, QID_AC_BE);
7998 RTMPRingCleanUp(pAd, QID_AC_VI);
7999 RTMPRingCleanUp(pAd, QID_AC_VO);
8000 RTMPRingCleanUp(pAd, QID_HCCA);
8001 RTMPRingCleanUp(pAd, QID_MGMT);
8002 RTMPRingCleanUp(pAd, QID_RX);
8005 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8007 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8009 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8010 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8011 RTMPPCIeLinkCtrlSetting(pAd, 3);
8013 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8014 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8015 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8019 IN PRTMP_ADAPTER pAd)
8021 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8023 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8024 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8025 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8027 // After hard-reset BBP, initialize all BBP values.
8028 NICRestoreBBPValue(pAd);
8029 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8033 IN PRTMP_ADAPTER pAd)
8037 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8038 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8040 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8042 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8044 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8048 IN PRTMP_ADAPTER pAd)
8050 ULONG Value1, Value2;
8053 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8054 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8057 // sum should be equals to 0xff, which is the total buffer size.
8058 if ((Value1 + Value2) < 0xff)
8060 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8061 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8063 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8065 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8067 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8071 VOID RTMPSetAGCInitValue(
8072 IN PRTMP_ADAPTER pAd,
8077 if (pAd->LatchRfRegs.Channel <= 14)
8079 R66 = 0x2E + GET_LNA_GAIN(pAd);
8080 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8084 if (BandWidth == BW_20)
8086 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8087 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8091 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8092 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8098 VOID AsicTurnOffRFClk(
8099 IN PRTMP_ADAPTER pAd,
8104 UINT32 R1 = 0, R2 = 0, R3 = 0;
8106 RTMP_RF_REGS *RFRegTable;
8108 RFRegTable = RF2850RegTable;
8110 switch (pAd->RfIcType)
8117 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8119 if (Channel == RFRegTable[index].Channel)
8121 R1 = RFRegTable[index].R1 & 0xffffdfff;
8122 R2 = RFRegTable[index].R2 & 0xfffbffff;
8123 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8125 RTMP_RF_IO_WRITE32(pAd, R1);
8126 RTMP_RF_IO_WRITE32(pAd, R2);
8128 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8129 // Set RF R2 bit18=0, R3 bit[18:19]=0
8130 //if (pAd->StaCfg.bRadio == FALSE)
8133 RTMP_RF_IO_WRITE32(pAd, R3);
8135 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8136 Channel, pAd->RfIcType, R2, R3));
8139 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8140 Channel, pAd->RfIcType, R2));
8152 VOID AsicTurnOnRFClk(
8153 IN PRTMP_ADAPTER pAd,
8158 UINT32 R1 = 0, R2 = 0, R3 = 0;
8160 RTMP_RF_REGS *RFRegTable;
8162 RFRegTable = RF2850RegTable;
8164 switch (pAd->RfIcType)
8171 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8173 if (Channel == RFRegTable[index].Channel)
8175 R3 = pAd->LatchRfRegs.R3;
8178 RTMP_RF_IO_WRITE32(pAd, R3);
8180 R1 = RFRegTable[index].R1;
8181 RTMP_RF_IO_WRITE32(pAd, R1);
8183 R2 = RFRegTable[index].R2;
8184 if (pAd->Antenna.field.TxPath == 1)
8186 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8189 if (pAd->Antenna.field.RxPath == 2)
8191 R2 |= 0x40; // write 1 to off Rxpath.
8193 else if (pAd->Antenna.field.RxPath == 1)
8195 R2 |= 0x20040; // write 1 to off RxPath
8197 RTMP_RF_IO_WRITE32(pAd, R2);
8208 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",