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 WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
47 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
48 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
49 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
50 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
51 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
52 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
54 UCHAR RateSwitchTable[] = {
55 // 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)
56 0x11, 0x00, 0, 0, 0, // Initial used item after association
57 0x00, 0x00, 0, 40, 101,
58 0x01, 0x00, 1, 40, 50,
59 0x02, 0x00, 2, 35, 45,
60 0x03, 0x00, 3, 20, 45,
61 0x04, 0x21, 0, 30, 50,
62 0x05, 0x21, 1, 20, 50,
63 0x06, 0x21, 2, 20, 50,
64 0x07, 0x21, 3, 15, 50,
65 0x08, 0x21, 4, 15, 30,
66 0x09, 0x21, 5, 10, 25,
69 0x0c, 0x20, 12, 15, 30,
70 0x0d, 0x20, 13, 8, 20,
71 0x0e, 0x20, 14, 8, 20,
72 0x0f, 0x20, 15, 8, 25,
73 0x10, 0x22, 15, 8, 25,
91 UCHAR RateSwitchTable11B[] = {
92 // 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)
93 0x04, 0x03, 0, 0, 0, // Initial used item after association
94 0x00, 0x00, 0, 40, 101,
95 0x01, 0x00, 1, 40, 50,
96 0x02, 0x00, 2, 35, 45,
97 0x03, 0x00, 3, 20, 45,
100 UCHAR RateSwitchTable11BG[] = {
101 // 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)
102 0x0a, 0x00, 0, 0, 0, // Initial used item after association
103 0x00, 0x00, 0, 40, 101,
104 0x01, 0x00, 1, 40, 50,
105 0x02, 0x00, 2, 35, 45,
106 0x03, 0x00, 3, 20, 45,
107 0x04, 0x10, 2, 20, 35,
108 0x05, 0x10, 3, 16, 35,
109 0x06, 0x10, 4, 10, 25,
110 0x07, 0x10, 5, 16, 25,
111 0x08, 0x10, 6, 10, 25,
112 0x09, 0x10, 7, 10, 13,
115 UCHAR RateSwitchTable11G[] = {
116 // 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)
117 0x08, 0x00, 0, 0, 0, // Initial used item after association
118 0x00, 0x10, 0, 20, 101,
119 0x01, 0x10, 1, 20, 35,
120 0x02, 0x10, 2, 20, 35,
121 0x03, 0x10, 3, 16, 35,
122 0x04, 0x10, 4, 10, 25,
123 0x05, 0x10, 5, 16, 25,
124 0x06, 0x10, 6, 10, 25,
125 0x07, 0x10, 7, 10, 13,
128 UCHAR RateSwitchTable11N1S[] = {
129 // 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)
130 0x09, 0x00, 0, 0, 0, // Initial used item after association
131 0x00, 0x21, 0, 30, 101,
132 0x01, 0x21, 1, 20, 50,
133 0x02, 0x21, 2, 20, 50,
134 0x03, 0x21, 3, 15, 50,
135 0x04, 0x21, 4, 15, 30,
136 0x05, 0x21, 5, 10, 25,
137 0x06, 0x21, 6, 8, 14,
138 0x07, 0x21, 7, 8, 14,
139 0x08, 0x23, 7, 8, 14,
142 UCHAR RateSwitchTable11N2S[] = {
143 // 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)
144 0x0a, 0x00, 0, 0, 0, // Initial used item after association
145 0x00, 0x21, 0, 30, 101,
146 0x01, 0x21, 1, 20, 50,
147 0x02, 0x21, 2, 20, 50,
148 0x03, 0x21, 3, 15, 50,
149 0x04, 0x21, 4, 15, 30,
150 0x05, 0x20, 12, 15, 30,
151 0x06, 0x20, 13, 8, 20,
152 0x07, 0x20, 14, 8, 20,
153 0x08, 0x20, 15, 8, 25,
154 0x09, 0x22, 15, 8, 25,
157 UCHAR RateSwitchTable11N3S[] = {
158 // 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)
159 0x0a, 0x00, 0, 0, 0, // Initial used item after association
160 0x00, 0x21, 0, 30, 101,
161 0x01, 0x21, 1, 20, 50,
162 0x02, 0x21, 2, 20, 50,
163 0x03, 0x21, 3, 15, 50,
164 0x04, 0x21, 4, 15, 30,
165 0x05, 0x20, 12, 15, 30,
166 0x06, 0x20, 13, 8, 20,
167 0x07, 0x20, 14, 8, 20,
168 0x08, 0x20, 15, 8, 25,
169 0x09, 0x22, 15, 8, 25,
172 UCHAR RateSwitchTable11N2SForABand[] = {
173 // 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)
174 0x0b, 0x09, 0, 0, 0, // Initial used item after association
175 0x00, 0x21, 0, 30, 101,
176 0x01, 0x21, 1, 20, 50,
177 0x02, 0x21, 2, 20, 50,
178 0x03, 0x21, 3, 15, 50,
179 0x04, 0x21, 4, 15, 30,
180 0x05, 0x21, 5, 15, 30,
181 0x06, 0x20, 12, 15, 30,
182 0x07, 0x20, 13, 8, 20,
183 0x08, 0x20, 14, 8, 20,
184 0x09, 0x20, 15, 8, 25,
185 0x0a, 0x22, 15, 8, 25,
188 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
189 // 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)
190 0x0b, 0x09, 0, 0, 0, // Initial used item after association
191 0x00, 0x21, 0, 30, 101,
192 0x01, 0x21, 1, 20, 50,
193 0x02, 0x21, 2, 20, 50,
194 0x03, 0x21, 3, 15, 50,
195 0x04, 0x21, 4, 15, 30,
196 0x05, 0x21, 5, 15, 30,
197 0x06, 0x20, 12, 15, 30,
198 0x07, 0x20, 13, 8, 20,
199 0x08, 0x20, 14, 8, 20,
200 0x09, 0x20, 15, 8, 25,
201 0x0a, 0x22, 15, 8, 25,
204 UCHAR RateSwitchTable11BGN1S[] = {
205 // 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)
206 0x0d, 0x00, 0, 0, 0, // Initial used item after association
207 0x00, 0x00, 0, 40, 101,
208 0x01, 0x00, 1, 40, 50,
209 0x02, 0x00, 2, 35, 45,
210 0x03, 0x00, 3, 20, 45,
211 0x04, 0x21, 0, 30,101, //50
212 0x05, 0x21, 1, 20, 50,
213 0x06, 0x21, 2, 20, 50,
214 0x07, 0x21, 3, 15, 50,
215 0x08, 0x21, 4, 15, 30,
216 0x09, 0x21, 5, 10, 25,
217 0x0a, 0x21, 6, 8, 14,
218 0x0b, 0x21, 7, 8, 14,
219 0x0c, 0x23, 7, 8, 14,
222 UCHAR RateSwitchTable11BGN2S[] = {
223 // 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)
224 0x0a, 0x00, 0, 0, 0, // Initial used item after association
225 0x00, 0x21, 0, 30,101, //50
226 0x01, 0x21, 1, 20, 50,
227 0x02, 0x21, 2, 20, 50,
228 0x03, 0x21, 3, 15, 50,
229 0x04, 0x21, 4, 15, 30,
230 0x05, 0x20, 12, 15, 30,
231 0x06, 0x20, 13, 8, 20,
232 0x07, 0x20, 14, 8, 20,
233 0x08, 0x20, 15, 8, 25,
234 0x09, 0x22, 15, 8, 25,
237 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
238 // 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)
239 0x0a, 0x00, 0, 0, 0, // Initial used item after association
240 0x00, 0x21, 0, 30,101, //50
241 0x01, 0x21, 1, 20, 50,
242 0x02, 0x21, 2, 20, 50,
243 0x03, 0x21, 3, 20, 50,
244 0x04, 0x21, 4, 15, 50,
245 0x05, 0x20, 20, 15, 30,
246 0x06, 0x20, 21, 8, 20,
247 0x07, 0x20, 22, 8, 20,
248 0x08, 0x20, 23, 8, 25,
249 0x09, 0x22, 23, 8, 25,
252 UCHAR RateSwitchTable11BGN2SForABand[] = {
253 // 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)
254 0x0b, 0x09, 0, 0, 0, // Initial used item after association
255 0x00, 0x21, 0, 30,101, //50
256 0x01, 0x21, 1, 20, 50,
257 0x02, 0x21, 2, 20, 50,
258 0x03, 0x21, 3, 15, 50,
259 0x04, 0x21, 4, 15, 30,
260 0x05, 0x21, 5, 15, 30,
261 0x06, 0x20, 12, 15, 30,
262 0x07, 0x20, 13, 8, 20,
263 0x08, 0x20, 14, 8, 20,
264 0x09, 0x20, 15, 8, 25,
265 0x0a, 0x22, 15, 8, 25,
268 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
269 // 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)
270 0x0c, 0x09, 0, 0, 0, // Initial used item after association
271 0x00, 0x21, 0, 30,101, //50
272 0x01, 0x21, 1, 20, 50,
273 0x02, 0x21, 2, 20, 50,
274 0x03, 0x21, 3, 15, 50,
275 0x04, 0x21, 4, 15, 30,
276 0x05, 0x21, 5, 15, 30,
277 0x06, 0x21, 12, 15, 30,
278 0x07, 0x20, 20, 15, 30,
279 0x08, 0x20, 21, 8, 20,
280 0x09, 0x20, 22, 8, 20,
281 0x0a, 0x20, 23, 8, 25,
282 0x0b, 0x22, 23, 8, 25,
285 PUCHAR ReasonString[] = {
287 /* 1 */ "Unspecified Reason",
288 /* 2 */ "Previous Auth no longer valid",
289 /* 3 */ "STA is leaving / has left",
290 /* 4 */ "DIS-ASSOC due to inactivity",
291 /* 5 */ "AP unable to hanle all associations",
292 /* 6 */ "class 2 error",
293 /* 7 */ "class 3 error",
294 /* 8 */ "STA is leaving / has left",
295 /* 9 */ "require auth before assoc/re-assoc",
299 /* 13 */ "invalid IE",
300 /* 14 */ "MIC error",
301 /* 15 */ "4-way handshake timeout",
302 /* 16 */ "2-way (group key) handshake timeout",
303 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
307 extern UCHAR OfdmRateToRxwiMCS[];
308 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
309 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
310 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
311 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
312 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
314 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
315 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
316 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
318 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
319 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
320 // clean environment.
321 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
322 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
324 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
325 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
327 UCHAR SsidIe = IE_SSID;
328 UCHAR SupRateIe = IE_SUPP_RATES;
329 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
330 UCHAR HtCapIe = IE_HT_CAP;
331 UCHAR AddHtInfoIe = IE_ADD_HT;
332 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
333 UCHAR ErpIe = IE_ERP;
334 UCHAR DsIe = IE_DS_PARM;
335 UCHAR TimIe = IE_TIM;
336 UCHAR WpaIe = IE_WPA;
337 UCHAR Wpa2Ie = IE_WPA2;
338 UCHAR IbssIe = IE_IBSS_PARM;
339 UCHAR Ccx2Ie = IE_CCX_V2;
341 extern UCHAR WPA_OUI[];
343 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
345 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
346 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
348 // Reset the RFIC setting to new series
349 RTMP_RF_REGS RF2850RegTable[] = {
350 // ch R1 R2 R3(TX0~4=0) R4
351 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
352 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
353 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
354 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
355 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
356 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
357 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
358 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
359 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
360 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
361 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
362 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
363 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
364 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
366 // 802.11 UNI / HyperLan 2
367 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
368 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
369 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
370 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
371 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
372 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
373 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
374 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
375 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
376 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
377 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
378 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
381 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
383 // 2008.04.30 modified
384 // The system team has AN to improve the EVM value
385 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
386 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
387 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
388 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
390 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
391 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
392 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
393 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
394 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
395 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
396 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
397 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
398 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
399 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
400 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
401 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
404 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
405 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
406 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
407 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
408 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
409 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
410 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
413 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
414 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
415 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
416 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
417 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
418 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
419 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
421 // still lack of MMAC(Japan) ch 34,38,42,46
423 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
425 FREQUENCY_ITEM FreqItems3020[] =
427 /**************************************************/
428 // ISM : 2.4 to 2.483 GHz //
429 /**************************************************/
431 /**************************************************/
432 //-CH---N-------R---K-----------
448 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
451 ==========================================================================
453 initialize the MLME task and its data structure (queue, spinlock,
454 timer, state machines).
459 always return NDIS_STATUS_SUCCESS
461 ==========================================================================
463 NDIS_STATUS MlmeInit(
464 IN PRTMP_ADAPTER pAd)
466 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
468 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
472 Status = MlmeQueueInit(&pAd->Mlme.Queue);
473 if(Status != NDIS_STATUS_SUCCESS)
476 pAd->Mlme.bRunning = FALSE;
477 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
480 BssTableInit(&pAd->ScanTab);
482 // init STA state machines
483 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
484 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
485 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
486 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
487 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
488 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
490 // Since we are using switch/case to implement it, the init is different from the above
491 // state machine init
492 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
495 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
497 // Init mlme periodic timer
498 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
500 // Set mlme periodic timer
501 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
503 // software-based RX Antenna diversity
504 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
508 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
510 // only PCIe cards need these two timers
511 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
512 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
518 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
524 ==========================================================================
526 main loop of the MLME
528 Mlme has to be initialized, and there are something inside the queue
530 This function is invoked from MPSetInformation and MPReceive;
531 This task guarantee only one MlmeHandler will run.
533 IRQL = DISPATCH_LEVEL
535 ==========================================================================
538 IN PRTMP_ADAPTER pAd)
540 MLME_QUEUE_ELEM *Elem = NULL;
542 // Only accept MLME and Frame from peer side, no other (control/data) frame should
543 // get into this state machine
545 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
546 if(pAd->Mlme.bRunning)
548 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
553 pAd->Mlme.bRunning = TRUE;
555 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
557 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
559 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
560 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
561 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
563 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
567 //From message type, determine which state machine I should drive
568 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
571 if (Elem->MsgType == MT2_RESET_CONF)
573 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
574 MlmeRestartStateMachine(pAd);
575 Elem->Occupied = FALSE;
581 // if dequeue success
582 switch (Elem->Machine)
584 // STA state machines
585 case ASSOC_STATE_MACHINE:
586 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
588 case AUTH_STATE_MACHINE:
589 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
591 case AUTH_RSP_STATE_MACHINE:
592 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
594 case SYNC_STATE_MACHINE:
595 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
597 case MLME_CNTL_STATE_MACHINE:
598 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
600 case WPA_PSK_STATE_MACHINE:
601 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
603 case AIRONET_STATE_MACHINE:
604 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
606 case ACTION_STATE_MACHINE:
607 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
614 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
619 Elem->Occupied = FALSE;
624 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
628 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
629 pAd->Mlme.bRunning = FALSE;
630 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
634 ==========================================================================
636 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
638 Adapter - NIC Adapter pointer
640 The MLME task will no longer work properly
644 ==========================================================================
647 IN PRTMP_ADAPTER pAd)
651 UINT32 TxPinCfg = 0x00050F0F;
654 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
656 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
658 // disable BEACON generation and other BEACON related hardware timers
659 AsicDisableSync(pAd);
663 // Cancel pending timers
664 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
665 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
666 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
667 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
668 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
669 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
671 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
673 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
674 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
679 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
680 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
684 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
687 RTMPSetLED(pAd, LED_HALT);
688 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
691 LED_CFG_STRUC LedCfg;
692 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
693 LedCfg.field.LedPolar = 0;
694 LedCfg.field.RLedMode = 0;
695 LedCfg.field.GLedMode = 0;
696 LedCfg.field.YLedMode = 0;
697 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
704 if (IS_RT3070(pAd) || IS_RT3071(pAd))
706 TxPinCfg &= 0xFFFFF0F0;
707 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
712 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
714 MlmeQueueDestroy(&pAd->Mlme.Queue);
715 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
717 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
720 VOID MlmeResetRalinkCounters(
721 IN PRTMP_ADAPTER pAd)
723 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
724 // clear all OneSecxxx counters.
725 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
726 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
727 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
728 pAd->RalinkCounters.OneSecRxOkCnt = 0;
729 pAd->RalinkCounters.OneSecTxFailCount = 0;
730 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
731 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
732 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
734 // TODO: for debug only. to be removed
735 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
736 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
737 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
738 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
739 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
740 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
741 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
742 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
743 pAd->RalinkCounters.OneSecTxDoneCount = 0;
744 pAd->RalinkCounters.OneSecRxCount = 0;
745 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
746 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
751 unsigned long rx_AMSDU;
752 unsigned long rx_Total;
755 ==========================================================================
757 This routine is executed periodically to -
758 1. Decide if it's a right time to turn on PwrMgmt bit of all
760 2. Calculate ChannelQuality based on statistics of the last
761 period, so that TX rate won't toggling very frequently between a
762 successful TX and a failed TX.
763 3. If the calculated ChannelQuality indicated current connection not
764 healthy, then a ROAMing attempt is tried here.
766 IRQL = DISPATCH_LEVEL
768 ==========================================================================
770 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
771 VOID MlmePeriodicExec(
772 IN PVOID SystemSpecific1,
773 IN PVOID FunctionContext,
774 IN PVOID SystemSpecific2,
775 IN PVOID SystemSpecific3)
778 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
782 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
783 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
784 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
785 if(pAd->StaCfg.WepStatus<2)
787 pAd->StaCfg.WpaSupplicantUP = 0;
791 pAd->StaCfg.WpaSupplicantUP = 1;
795 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
796 // Move code to here, because following code will return when radio is off
797 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
798 (pAd->StaCfg.bHardwareRadio == TRUE) &&
799 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
800 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
801 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
805 // Read GPIO pin2 as Hardware controlled radio state
806 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
809 pAd->StaCfg.bHwRadio = TRUE;
813 pAd->StaCfg.bHwRadio = FALSE;
815 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
817 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
818 if (pAd->StaCfg.bRadio == TRUE)
821 // Update extra information
822 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
827 // Update extra information
828 pAd->ExtraInfo = HW_RADIO_OFF;
835 // Do nothing if the driver is starting halt state.
836 // This might happen when timer already been fired before cancel timer with mlmehalt
837 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
838 fRTMP_ADAPTER_RADIO_OFF |
839 fRTMP_ADAPTER_RADIO_MEASUREMENT |
840 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
845 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
847 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
848 pAd->SameRxByteCount++;
851 pAd->SameRxByteCount = 0;
853 // If after BBP, still not work...need to check to reset PBF&MAC.
854 if (pAd->SameRxByteCount == 702)
856 pAd->SameRxByteCount = 0;
861 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
862 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
864 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
866 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
867 pAd->SameRxByteCount = 700;
872 // Update lastReceiveByteCount.
873 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
875 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
877 pAd->CheckDmaBusyCount = 0;
878 AsicResetFromDMABusy(pAd);
882 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
885 // Do nothing if monitor mode is on
889 if (pAd->Mlme.PeriodicRound & 0x1)
891 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
892 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
893 (STA_TGN_WIFI_ON(pAd)) &&
894 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
897 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
898 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
900 else if ((STA_TGN_WIFI_ON(pAd)) &&
901 ((pAd->MACVersion & 0xffff) == 0x0101))
903 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
904 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
909 pAd->bUpdateBcnCntDone = FALSE;
911 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
912 pAd->Mlme.PeriodicRound ++;
915 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
916 NICUpdateFifoStaCounters(pAd);
918 // execute every 500ms
919 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
921 // perform dynamic tx rate switching based on past TX history
923 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
925 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
926 MlmeDynamicTxRateSwitching(pAd);
930 // Normal 1 second Mlme PeriodicExec.
931 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
933 pAd->Mlme.OneSecPeriodicRound ++;
943 // Media status changed, report to NDIS
944 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
946 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
947 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
949 pAd->IndicateMediaState = NdisMediaStateConnected;
950 RTMP_IndicateMediaState(pAd);
955 pAd->IndicateMediaState = NdisMediaStateDisconnected;
956 RTMP_IndicateMediaState(pAd);
960 NdisGetSystemUpTime(&pAd->Mlme.Now32);
962 // add the most up-to-date h/w raw counters into software variable, so that
963 // the dynamic tuning mechanism below are based on most up-to-date information
964 NICUpdateRawCounters(pAd);
967 RT2870_WatchDog(pAd);
970 // Need statistics after read counter. So put after NICUpdateRawCounters
971 ORIBATimerTimeout(pAd);
973 // The time period for checking antenna is according to traffic
974 if (pAd->Mlme.bEnableAutoAntennaCheck)
976 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
977 pAd->RalinkCounters.OneSecTxRetryOkCount +
978 pAd->RalinkCounters.OneSecTxFailCount;
980 // dynamic adjust antenna evaluation period according to the traffic
983 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
985 AsicEvaluateRxAnt(pAd);
990 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
992 AsicEvaluateRxAnt(pAd);
997 STAMlmePeriodicExec(pAd);
999 MlmeResetRalinkCounters(pAd);
1003 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1006 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1007 // and sending CTS-to-self over and over.
1008 // Software Patch Solution:
1009 // 1. Polling debug state register 0x10F4 every one second.
1010 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1011 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1015 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1016 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1018 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1020 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1022 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1027 RT28XX_MLME_HANDLER(pAd);
1030 pAd->bUpdateBcnCntDone = FALSE;
1033 VOID STAMlmePeriodicExec(
1044 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1046 // WPA MIC error should block association attempt for 60 seconds
1047 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1048 pAd->StaCfg.bBlockAssoc = FALSE;
1053 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1054 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1055 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1056 if(pAd->StaCfg.WepStatus<2)
1058 pAd->StaCfg.WpaSupplicantUP = 0;
1062 pAd->StaCfg.WpaSupplicantUP = 1;
1066 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1068 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1070 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1072 pAd->PreMediaState = pAd->IndicateMediaState;
1076 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1077 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1078 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1079 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1080 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1081 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1083 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1089 AsicStaBbpTuning(pAd);
1091 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1092 pAd->RalinkCounters.OneSecTxRetryOkCount +
1093 pAd->RalinkCounters.OneSecTxFailCount;
1095 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1097 // update channel quality for Roaming and UI LinkQuality display
1098 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1101 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1102 // Radio is currently in noisy environment
1103 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1104 AsicAdjustTxPower(pAd);
1108 // Is PSM bit consistent with user power management policy?
1109 // This is the only place that will set PSM bit ON.
1110 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1111 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1113 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1115 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1116 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1117 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1119 RTMPSetAGCInitValue(pAd, BW_20);
1120 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1124 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1126 // When APSD is enabled, the period changes as 20 sec
1127 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1128 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1132 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1133 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1135 if (pAd->CommonCfg.bWmmCapable)
1136 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1138 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1143 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1145 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1146 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1147 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1149 // Lost AP, send disconnect & link down event
1150 LinkDown(pAd, FALSE);
1153 union iwreq_data wrqu;
1154 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1155 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1158 MlmeAutoReconnectLastSSID(pAd);
1160 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1162 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1163 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1164 MlmeAutoReconnectLastSSID(pAd);
1167 // Add auto seamless roaming
1168 if (pAd->StaCfg.bFastRoaming)
1170 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1172 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));
1174 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1176 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1180 else if (ADHOC_ON(pAd))
1183 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1184 // the "TX BEACON competition" for the entire past 1 sec.
1185 // So that even when ASIC's BEACONgen engine been blocked
1186 // by peer's BEACON due to slower system clock, this STA still can send out
1187 // minimum BEACON to tell the peer I'm alive.
1188 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1189 // EnqueueBeaconFrame(pAd); // software send BEACON
1191 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1192 // restore outgoing BEACON to support B/G-mixed mode
1193 if ((pAd->CommonCfg.Channel <= 14) &&
1194 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1195 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1196 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1198 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1199 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1200 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1201 MlmeUpdateTxRates(pAd, FALSE, 0);
1202 MakeIbssBeacon(pAd); // re-build BEACON frame
1203 AsicEnableIbssSync(pAd); // copy to on-chip memory
1204 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1207 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1209 if ((pAd->StaCfg.AdhocBGJoined) &&
1210 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1212 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1213 pAd->StaCfg.AdhocBGJoined = FALSE;
1216 if ((pAd->StaCfg.Adhoc20NJoined) &&
1217 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1219 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1220 pAd->StaCfg.Adhoc20NJoined = FALSE;
1226 if ((pAd->CommonCfg.Channel > 14)
1227 && (pAd->CommonCfg.bIEEE80211H == 1)
1228 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1230 RadarDetectPeriodic(pAd);
1233 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1234 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1236 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1237 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1239 MLME_START_REQ_STRUCT StartReq;
1241 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1242 LinkDown(pAd, FALSE);
1244 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1245 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1246 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1250 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1252 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1254 if (pEntry->ValidAsCLI == FALSE)
1257 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1258 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1262 else // no INFRA nor ADHOC connection
1265 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1266 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1267 goto SKIP_AUTO_SCAN_CONN;
1269 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1271 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1272 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1273 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1275 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1277 MLME_SCAN_REQ_STRUCT ScanReq;
1279 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1281 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1282 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1283 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1284 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1285 // Reset Missed scan number
1286 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1288 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1289 MlmeAutoReconnectLastSSID(pAd);
1291 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1293 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1296 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1300 MlmeAutoReconnectLastSSID(pAd);
1306 SKIP_AUTO_SCAN_CONN:
1308 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1310 pAd->MacTab.fAnyBASession = TRUE;
1311 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1313 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1315 pAd->MacTab.fAnyBASession = FALSE;
1316 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1324 IN PVOID SystemSpecific1,
1325 IN PVOID FunctionContext,
1326 IN PVOID SystemSpecific2,
1327 IN PVOID SystemSpecific3)
1330 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1332 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1333 RTMP_IndicateMediaState(pAd);
1334 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1337 // IRQL = DISPATCH_LEVEL
1339 IN PRTMP_ADAPTER pAd)
1341 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1342 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1344 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1346 MLME_CNTL_STATE_MACHINE,
1347 OID_802_11_BSSID_LIST_SCAN,
1350 RT28XX_MLME_HANDLER(pAd);
1354 // IRQL = DISPATCH_LEVEL
1355 VOID MlmeAutoReconnectLastSSID(
1356 IN PRTMP_ADAPTER pAd)
1360 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1361 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1362 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1364 NDIS_802_11_SSID OidSsid;
1365 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1366 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1368 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1370 MLME_CNTL_STATE_MACHINE,
1372 sizeof(NDIS_802_11_SSID),
1374 RT28XX_MLME_HANDLER(pAd);
1379 ==========================================================================
1380 Validate SSID for connection try and rescan purpose
1381 Valid SSID will have visible chars only.
1382 The valid length is from 0 to 32.
1383 IRQL = DISPATCH_LEVEL
1384 ==========================================================================
1386 BOOLEAN MlmeValidateSSID(
1392 if (SsidLen > MAX_LEN_OF_SSID)
1395 // Check each character value
1396 for (index = 0; index < SsidLen; index++)
1398 if (pSsid[index] < 0x20)
1406 VOID MlmeSelectTxRateTable(
1407 IN PRTMP_ADAPTER pAd,
1408 IN PMAC_TABLE_ENTRY pEntry,
1410 IN PUCHAR pTableSize,
1411 IN PUCHAR pInitTxRateIdx)
1415 // decide the rate table for tuning
1416 if (pAd->CommonCfg.TxRateTableSize > 0)
1418 *ppTable = RateSwitchTable;
1419 *pTableSize = RateSwitchTable[0];
1420 *pInitTxRateIdx = RateSwitchTable[1];
1425 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1427 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1429 !pAd->StaCfg.AdhocBOnlyJoined &&
1430 !pAd->StaCfg.AdhocBGJoined &&
1431 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1432 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1435 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1436 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1439 *ppTable = RateSwitchTable11N1S;
1440 *pTableSize = RateSwitchTable11N1S[0];
1441 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1444 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1446 !pAd->StaCfg.AdhocBOnlyJoined &&
1447 !pAd->StaCfg.AdhocBGJoined &&
1448 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1449 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1452 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1453 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1455 (pAd->Antenna.field.TxPath == 2))
1457 if (pAd->LatchRfRegs.Channel <= 14)
1459 *ppTable = RateSwitchTable11N2S;
1460 *pTableSize = RateSwitchTable11N2S[0];
1461 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1465 *ppTable = RateSwitchTable11N2SForABand;
1466 *pTableSize = RateSwitchTable11N2SForABand[0];
1467 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1473 if (pAd->CommonCfg.PhyMode == PHY_11B)
1475 *ppTable = RateSwitchTable11B;
1476 *pTableSize = RateSwitchTable11B[0];
1477 *pInitTxRateIdx = RateSwitchTable11B[1];
1480 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1483 if ((pEntry->RateLen == 4)
1484 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1488 // USe B Table when Only b-only Station in my IBSS .
1489 *ppTable = RateSwitchTable11B;
1490 *pTableSize = RateSwitchTable11B[0];
1491 *pInitTxRateIdx = RateSwitchTable11B[1];
1494 else if (pAd->LatchRfRegs.Channel <= 14)
1496 *ppTable = RateSwitchTable11BG;
1497 *pTableSize = RateSwitchTable11BG[0];
1498 *pInitTxRateIdx = RateSwitchTable11BG[1];
1503 *ppTable = RateSwitchTable11G;
1504 *pTableSize = RateSwitchTable11G[0];
1505 *pInitTxRateIdx = RateSwitchTable11G[1];
1511 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1512 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1514 *ppTable = RateSwitchTable11BGN1S;
1515 *pTableSize = RateSwitchTable11BGN1S[0];
1516 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1521 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1522 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1524 if (pAd->LatchRfRegs.Channel <= 14)
1526 *ppTable = RateSwitchTable11BGN2S;
1527 *pTableSize = RateSwitchTable11BGN2S[0];
1528 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1533 *ppTable = RateSwitchTable11BGN2SForABand;
1534 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1535 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1541 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1543 *ppTable = RateSwitchTable11N1S;
1544 *pTableSize = RateSwitchTable11N1S[0];
1545 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1550 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1552 if (pAd->LatchRfRegs.Channel <= 14)
1554 *ppTable = RateSwitchTable11N2S;
1555 *pTableSize = RateSwitchTable11N2S[0];
1556 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1560 *ppTable = RateSwitchTable11N2SForABand;
1561 *pTableSize = RateSwitchTable11N2SForABand[0];
1562 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1568 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1569 if ((pEntry->RateLen == 4)
1571 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1572 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1576 *ppTable = RateSwitchTable11B;
1577 *pTableSize = RateSwitchTable11B[0];
1578 *pInitTxRateIdx = RateSwitchTable11B[1];
1583 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1584 if ((pEntry->RateLen > 8)
1585 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1588 *ppTable = RateSwitchTable11BG;
1589 *pTableSize = RateSwitchTable11BG[0];
1590 *pInitTxRateIdx = RateSwitchTable11BG[1];
1595 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1596 if ((pEntry->RateLen == 8)
1597 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1600 *ppTable = RateSwitchTable11G;
1601 *pTableSize = RateSwitchTable11G[0];
1602 *pInitTxRateIdx = RateSwitchTable11G[1];
1608 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1609 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1611 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1613 *ppTable = RateSwitchTable11B;
1614 *pTableSize = RateSwitchTable11B[0];
1615 *pInitTxRateIdx = RateSwitchTable11B[1];
1617 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1619 *ppTable = RateSwitchTable11G;
1620 *pTableSize = RateSwitchTable11G[0];
1621 *pInitTxRateIdx = RateSwitchTable11G[1];
1626 *ppTable = RateSwitchTable11BG;
1627 *pTableSize = RateSwitchTable11BG[0];
1628 *pInitTxRateIdx = RateSwitchTable11BG[1];
1633 if (pAd->LatchRfRegs.Channel <= 14)
1635 if (pAd->CommonCfg.TxStream == 1)
1637 *ppTable = RateSwitchTable11N1S;
1638 *pTableSize = RateSwitchTable11N1S[0];
1639 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1640 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1644 *ppTable = RateSwitchTable11N2S;
1645 *pTableSize = RateSwitchTable11N2S[0];
1646 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1647 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1652 if (pAd->CommonCfg.TxStream == 1)
1654 *ppTable = RateSwitchTable11N1S;
1655 *pTableSize = RateSwitchTable11N1S[0];
1656 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1657 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1661 *ppTable = RateSwitchTable11N2SForABand;
1662 *pTableSize = RateSwitchTable11N2SForABand[0];
1663 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1664 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1668 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1669 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1675 ==========================================================================
1677 This routine checks if there're other APs out there capable for
1678 roaming. Caller should call this routine only when Link up in INFRA mode
1679 and channel quality is below CQI_GOOD_THRESHOLD.
1681 IRQL = DISPATCH_LEVEL
1684 ==========================================================================
1686 VOID MlmeCheckForRoaming(
1687 IN PRTMP_ADAPTER pAd,
1691 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1694 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1695 // put all roaming candidates into RoamTab, and sort in RSSI order
1696 BssTableInit(pRoamTab);
1697 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1699 pBss = &pAd->ScanTab.BssEntry[i];
1701 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1702 continue; // AP disappear
1703 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1704 continue; // RSSI too weak. forget it.
1705 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1706 continue; // skip current AP
1707 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1708 continue; // only AP with stronger RSSI is eligible for roaming
1710 // AP passing all above rules is put into roaming candidate table
1711 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1712 pRoamTab->BssNr += 1;
1715 if (pRoamTab->BssNr > 0)
1717 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1718 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1720 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1721 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1722 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1723 RT28XX_MLME_HANDLER(pAd);
1726 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1730 ==========================================================================
1732 This routine checks if there're other APs out there capable for
1733 roaming. Caller should call this routine only when link up in INFRA mode
1734 and channel quality is below CQI_GOOD_THRESHOLD.
1736 IRQL = DISPATCH_LEVEL
1739 ==========================================================================
1741 VOID MlmeCheckForFastRoaming(
1742 IN PRTMP_ADAPTER pAd,
1746 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1749 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1750 // put all roaming candidates into RoamTab, and sort in RSSI order
1751 BssTableInit(pRoamTab);
1752 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1754 pBss = &pAd->ScanTab.BssEntry[i];
1756 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1757 continue; // RSSI too weak. forget it.
1758 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1759 continue; // skip current AP
1760 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1761 continue; // skip different SSID
1762 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1763 continue; // skip AP without better RSSI
1765 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));
1766 // AP passing all above rules is put into roaming candidate table
1767 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1768 pRoamTab->BssNr += 1;
1771 if (pRoamTab->BssNr > 0)
1773 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1774 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1776 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1777 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1778 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1779 RT28XX_MLME_HANDLER(pAd);
1782 // Maybe site survey required
1785 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1787 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1788 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1789 pAd->StaCfg.ScanCnt = 2;
1790 pAd->StaCfg.LastScanTime = Now;
1795 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1799 ==========================================================================
1801 This routine calculates TxPER, RxPER of the past N-sec period. And
1802 according to the calculation result, ChannelQuality is calculated here
1803 to decide if current AP is still doing the job.
1805 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1807 StaCfg.ChannelQuality - 0..100
1809 IRQL = DISPATCH_LEVEL
1811 NOTE: This routine decide channle quality based on RX CRC error ratio.
1812 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1813 is performed right before this routine, so that this routine can decide
1814 channel quality based on the most up-to-date information
1815 ==========================================================================
1817 VOID MlmeCalculateChannelQuality(
1818 IN PRTMP_ADAPTER pAd,
1821 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1825 ULONG BeaconLostTime = BEACON_LOST_TIME;
1827 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1830 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1832 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1833 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1841 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1842 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1846 // calculate RX PER - don't take RxPER into consideration if too few sample
1848 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1852 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1855 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1857 if (INFRA_ON(pAd) &&
1858 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1859 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1861 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1862 pAd->Mlme.ChannelQuality = 0;
1869 else if (MaxRssi < -90)
1872 NorRssi = (MaxRssi + 90) * 2;
1874 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1875 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1876 TX_WEIGHTING * (100 - TxPRR) +
1877 RX_WEIGHTING* (100 - RxPER)) / 100;
1878 if (pAd->Mlme.ChannelQuality >= 100)
1879 pAd->Mlme.ChannelQuality = 100;
1885 IN PRTMP_ADAPTER pAd,
1886 IN PMAC_TABLE_ENTRY pEntry,
1887 IN PRTMP_TX_RATE_SWITCH pTxRate)
1889 UCHAR MaxMode = MODE_OFDM;
1891 MaxMode = MODE_HTGREENFIELD;
1893 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1894 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1896 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1898 if (pTxRate->CurrMCS < MCS_AUTO)
1899 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1901 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1902 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1906 // If peer adhoc is b-only mode, we can't send 11g rate.
1907 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1908 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1911 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1913 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1914 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1915 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1917 // Patch speed error in status page
1918 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1922 if (pTxRate->Mode <= MaxMode)
1923 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1925 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1926 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1928 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1930 // Reexam each bandwidth's SGI support.
1931 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1933 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1934 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1935 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1936 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1939 // Turn RTS/CTS rate to 6Mbps.
1940 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1942 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1943 if (pAd->MacTab.fAnyBASession)
1945 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1949 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1952 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1954 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1955 if (pAd->MacTab.fAnyBASession)
1957 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1961 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1964 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1966 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1969 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1971 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1974 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1975 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1976 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1977 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1979 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1980 pAd->WIFItestbed.bGreenField)
1981 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1984 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1988 ==========================================================================
1990 This routine calculates the acumulated TxPER of eaxh TxRate. And
1991 according to the calculation result, change CommonCfg.TxRate which
1992 is the stable TX Rate we expect the Radio situation could sustained.
1994 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1998 IRQL = DISPATCH_LEVEL
2001 call this routine every second
2002 ==========================================================================
2004 VOID MlmeDynamicTxRateSwitching(
2005 IN PRTMP_ADAPTER pAd)
2007 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2008 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2009 ULONG TxErrorRatio = 0;
2010 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2011 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2013 UCHAR TableSize = 0;
2014 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2015 CHAR Rssi, RssiOffset = 0;
2016 TX_STA_CNT1_STRUC StaTx1;
2017 TX_STA_CNT0_STRUC TxStaCnt0;
2018 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2019 MAC_TABLE_ENTRY *pEntry;
2022 // walk through MAC table, see if need to change AP's TX rate toward each entry
2024 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2026 pEntry = &pAd->MacTab.Content[i];
2028 // check if this entry need to switch rate automatically
2029 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2032 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2035 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2038 Rssi = RTMPMaxRssi(pAd,
2039 pAd->StaCfg.RssiSample.AvgRssi0,
2040 pAd->StaCfg.RssiSample.AvgRssi1,
2041 pAd->StaCfg.RssiSample.AvgRssi2);
2044 // Update statistic counter
2045 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2046 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2047 pAd->bUpdateBcnCntDone = TRUE;
2048 TxRetransmit = StaTx1.field.TxRetransmit;
2049 TxSuccess = StaTx1.field.TxSuccess;
2050 TxFailCount = TxStaCnt0.field.TxFailCount;
2051 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2053 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2054 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2055 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2056 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2057 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2058 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2060 // if no traffic in the past 1-sec period, don't change TX rate,
2061 // but clear all bad history. because the bad history may affect the next
2062 // Chariot throughput test
2063 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2064 pAd->RalinkCounters.OneSecTxRetryOkCount +
2065 pAd->RalinkCounters.OneSecTxFailCount;
2068 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2073 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2076 if (INFRA_ON(pAd) && (i == 1))
2077 Rssi = RTMPMaxRssi(pAd,
2078 pAd->StaCfg.RssiSample.AvgRssi0,
2079 pAd->StaCfg.RssiSample.AvgRssi1,
2080 pAd->StaCfg.RssiSample.AvgRssi2);
2082 Rssi = RTMPMaxRssi(pAd,
2083 pEntry->RssiSample.AvgRssi0,
2084 pEntry->RssiSample.AvgRssi1,
2085 pEntry->RssiSample.AvgRssi2);
2088 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2089 pEntry->OneSecTxRetryOkCount +
2090 pEntry->OneSecTxFailCount;
2093 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2096 CurrRateIdx = pEntry->CurrTxRateIndex;
2098 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2100 if (CurrRateIdx >= TableSize)
2102 CurrRateIdx = TableSize - 1;
2105 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2106 // So need to sync here.
2107 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2108 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2109 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2113 // Need to sync Real Tx rate and our record.
2114 // Then return for next DRS.
2115 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2116 pEntry->CurrTxRateIndex = InitTxRateIdx;
2117 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2119 // reset all OneSecTx counters
2120 RESET_ONE_SEC_TX_CNT(pEntry);
2124 // decide the next upgrade rate and downgrade rate, if any
2125 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2127 UpRateIdx = CurrRateIdx + 1;
2128 DownRateIdx = CurrRateIdx -1;
2130 else if (CurrRateIdx == 0)
2132 UpRateIdx = CurrRateIdx + 1;
2133 DownRateIdx = CurrRateIdx;
2135 else if (CurrRateIdx == (TableSize - 1))
2137 UpRateIdx = CurrRateIdx;
2138 DownRateIdx = CurrRateIdx - 1;
2141 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2143 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2145 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2146 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2150 TrainUp = pCurrTxRate->TrainUp;
2151 TrainDown = pCurrTxRate->TrainDown;
2154 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2157 // Keep the last time TxRateChangeAction status.
2159 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2164 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2165 // (criteria copied from RT2500 for Netopia case)
2167 if (TxTotalCnt <= 15)
2171 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2172 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2173 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2174 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2176 // check the existence and index of each needed MCS
2177 while (idx < pTable[0])
2179 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2181 if (pCurrTxRate->CurrMCS == MCS_0)
2185 else if (pCurrTxRate->CurrMCS == MCS_1)
2189 else if (pCurrTxRate->CurrMCS == MCS_2)
2193 else if (pCurrTxRate->CurrMCS == MCS_3)
2197 else if (pCurrTxRate->CurrMCS == MCS_4)
2201 else if (pCurrTxRate->CurrMCS == MCS_5)
2205 else if (pCurrTxRate->CurrMCS == MCS_6)
2209 //else if (pCurrTxRate->CurrMCS == MCS_7)
2210 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2214 else if (pCurrTxRate->CurrMCS == MCS_12)
2218 else if (pCurrTxRate->CurrMCS == MCS_13)
2222 else if (pCurrTxRate->CurrMCS == MCS_14)
2226 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
2230 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2234 else if (pCurrTxRate->CurrMCS == MCS_21)
2238 else if (pCurrTxRate->CurrMCS == MCS_22)
2242 else if (pCurrTxRate->CurrMCS == MCS_23)
2249 if (pAd->LatchRfRegs.Channel <= 14)
2251 if (pAd->NicConfig2.field.ExternalLNAForG)
2262 if (pAd->NicConfig2.field.ExternalLNAForA)
2273 if ((pTable == RateSwitchTable11BGN3S) ||
2274 (pTable == RateSwitchTable11N3S) ||
2275 (pTable == RateSwitchTable))
2276 {// N mode with 3 stream // 3*3
2277 if (MCS23 && (Rssi >= -70))
2279 else if (MCS22 && (Rssi >= -72))
2281 else if (MCS21 && (Rssi >= -76))
2283 else if (MCS20 && (Rssi >= -78))
2285 else if (MCS4 && (Rssi >= -82))
2287 else if (MCS3 && (Rssi >= -84))
2289 else if (MCS2 && (Rssi >= -86))
2291 else if (MCS1 && (Rssi >= -88))
2296 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2297 {// N mode with 2 stream
2298 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2300 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2302 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2304 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2306 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2308 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2310 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2312 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2317 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2318 {// N mode with 1 stream
2319 if (MCS7 && (Rssi > (-72+RssiOffset)))
2321 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2323 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2325 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2327 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2329 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2331 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2338 if (MCS7 && (Rssi > -70))
2340 else if (MCS6 && (Rssi > -74))
2342 else if (MCS5 && (Rssi > -78))
2344 else if (MCS4 && (Rssi > -82))
2346 else if (MCS4 == 0) // for B-only mode
2348 else if (MCS3 && (Rssi > -85))
2350 else if (MCS2 && (Rssi > -87))
2352 else if (MCS1 && (Rssi > -90))
2359 pEntry->CurrTxRateIndex = TxRateIdx;
2360 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2361 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2364 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2365 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2366 pEntry->fLastSecAccordingRSSI = TRUE;
2367 // reset all OneSecTx counters
2368 RESET_ONE_SEC_TX_CNT(pEntry);
2373 if (pEntry->fLastSecAccordingRSSI == TRUE)
2375 pEntry->fLastSecAccordingRSSI = FALSE;
2376 pEntry->LastSecTxRateChangeAction = 0;
2377 // reset all OneSecTx counters
2378 RESET_ONE_SEC_TX_CNT(pEntry);
2385 BOOLEAN bTrainUpDown = FALSE;
2387 pEntry->CurrTxRateStableTime ++;
2389 // downgrade TX quality if PER >= Rate-Down threshold
2390 if (TxErrorRatio >= TrainDown)
2392 bTrainUpDown = TRUE;
2393 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2395 // upgrade TX quality if PER <= Rate-Up threshold
2396 else if (TxErrorRatio <= TrainUp)
2398 bTrainUpDown = TRUE;
2399 bUpgradeQuality = TRUE;
2400 if (pEntry->TxQuality[CurrRateIdx])
2401 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2403 if (pEntry->TxRateUpPenalty)
2404 pEntry->TxRateUpPenalty --;
2405 else if (pEntry->TxQuality[UpRateIdx])
2406 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2409 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2413 // perform DRS - consider TxRate Down first, then rate up.
2414 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2416 pEntry->CurrTxRateIndex = DownRateIdx;
2418 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2420 pEntry->CurrTxRateIndex = UpRateIdx;
2425 // if rate-up happen, clear all bad history of all TX rates
2426 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2428 pEntry->CurrTxRateStableTime = 0;
2429 pEntry->TxRateUpPenalty = 0;
2430 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2431 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2432 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2435 // For TxRate fast train up
2437 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2439 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2441 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2443 bTxRateChanged = TRUE;
2445 // if rate-down happen, only clear DownRate's bad history
2446 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2448 pEntry->CurrTxRateStableTime = 0;
2449 pEntry->TxRateUpPenalty = 0; // no penalty
2450 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2451 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2452 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2455 // For TxRate fast train down
2457 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2459 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2461 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2463 bTxRateChanged = TRUE;
2467 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2468 bTxRateChanged = FALSE;
2471 pEntry->LastTxOkCount = TxSuccess;
2473 // reset all OneSecTx counters
2474 RESET_ONE_SEC_TX_CNT(pEntry);
2476 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2477 if (bTxRateChanged && pNextTxRate)
2479 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2485 ========================================================================
2486 Routine Description:
2487 Station side, Auto TxRate faster train up timer call back function.
2490 SystemSpecific1 - Not used.
2491 FunctionContext - Pointer to our Adapter context.
2492 SystemSpecific2 - Not used.
2493 SystemSpecific3 - Not used.
2498 ========================================================================
2500 VOID StaQuickResponeForRateUpExec(
2501 IN PVOID SystemSpecific1,
2502 IN PVOID FunctionContext,
2503 IN PVOID SystemSpecific2,
2504 IN PVOID SystemSpecific3)
2506 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2507 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2509 ULONG TxErrorRatio = 0;
2511 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2514 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2516 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2518 UCHAR TableSize = 0;
2519 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2520 TX_STA_CNT1_STRUC StaTx1;
2521 TX_STA_CNT0_STRUC TxStaCnt0;
2523 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2524 MAC_TABLE_ENTRY *pEntry;
2527 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2530 // walk through MAC table, see if need to change AP's TX rate toward each entry
2532 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2534 pEntry = &pAd->MacTab.Content[i];
2536 // check if this entry need to switch rate automatically
2537 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2541 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2542 if (pAd->Antenna.field.TxPath > 1)
2543 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2545 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2548 if (INFRA_ON(pAd) && (i == 1))
2549 Rssi = RTMPMaxRssi(pAd,
2550 pAd->StaCfg.RssiSample.AvgRssi0,
2551 pAd->StaCfg.RssiSample.AvgRssi1,
2552 pAd->StaCfg.RssiSample.AvgRssi2);
2554 Rssi = RTMPMaxRssi(pAd,
2555 pEntry->RssiSample.AvgRssi0,
2556 pEntry->RssiSample.AvgRssi1,
2557 pEntry->RssiSample.AvgRssi2);
2560 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2562 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2564 // decide the next upgrade rate and downgrade rate, if any
2565 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2567 UpRateIdx = CurrRateIdx + 1;
2568 DownRateIdx = CurrRateIdx -1;
2570 else if (CurrRateIdx == 0)
2572 UpRateIdx = CurrRateIdx + 1;
2573 DownRateIdx = CurrRateIdx;
2575 else if (CurrRateIdx == (TableSize - 1))
2577 UpRateIdx = CurrRateIdx;
2578 DownRateIdx = CurrRateIdx - 1;
2581 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2583 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2585 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2586 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2590 TrainUp = pCurrTxRate->TrainUp;
2591 TrainDown = pCurrTxRate->TrainDown;
2594 if (pAd->MacTab.Size == 1)
2596 // Update statistic counter
2597 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2598 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2600 TxRetransmit = StaTx1.field.TxRetransmit;
2601 TxSuccess = StaTx1.field.TxSuccess;
2602 TxFailCount = TxStaCnt0.field.TxFailCount;
2603 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2605 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2606 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2607 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2608 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2609 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2610 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2613 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2617 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2618 pEntry->OneSecTxRetryOkCount +
2619 pEntry->OneSecTxFailCount;
2622 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2627 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2628 // (criteria copied from RT2500 for Netopia case)
2630 if (TxTotalCnt <= 12)
2632 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2633 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2635 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2637 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2638 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2640 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2642 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2645 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2651 ULONG OneSecTxNoRetryOKRationCount;
2653 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2658 // downgrade TX quality if PER >= Rate-Down threshold
2659 if (TxErrorRatio >= TrainDown)
2661 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2664 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2666 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2668 // perform DRS - consider TxRate Down first, then rate up.
2669 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2671 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2673 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2674 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2679 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2681 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2685 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2687 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2692 // if rate-up happen, clear all bad history of all TX rates
2693 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2695 pAd->DrsCounters.TxRateUpPenalty = 0;
2696 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2697 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2699 bTxRateChanged = TRUE;
2702 // if rate-down happen, only clear DownRate's bad history
2703 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2705 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2707 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2708 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2709 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2711 bTxRateChanged = TRUE;
2716 bTxRateChanged = FALSE;
2719 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2720 if (bTxRateChanged && pNextTxRate)
2722 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2728 ==========================================================================
2730 This routine is executed periodically inside MlmePeriodicExec() after
2731 association with an AP.
2732 It checks if StaCfg.Psm is consistent with user policy (recorded in
2733 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2734 there're some conditions to consider:
2735 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2736 the time when Mibss==TRUE
2737 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2738 if outgoing traffic available in TxRing or MgmtRing.
2740 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2742 IRQL = DISPATCH_LEVEL
2744 ==========================================================================
2746 VOID MlmeCheckPsmChange(
2747 IN PRTMP_ADAPTER pAd,
2753 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2754 // 2. user wants either MAX_PSP or FAST_PSP
2755 // 3. but current psm is not in PWR_SAVE
2756 // 4. CNTL state machine is not doing SCANning
2757 // 5. no TX SUCCESS event for the past 1-sec period
2758 #ifdef NDIS51_MINIPORT
2759 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2760 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2763 PowerMode = pAd->StaCfg.WindowsPowerMode;
2765 if (INFRA_ON(pAd) &&
2766 (PowerMode != Ndis802_11PowerModeCAM) &&
2767 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2769 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2771 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2775 // add by johnli, use Rx OK data count per second to calculate throughput
2776 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2777 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2778 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2779 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2780 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2781 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2785 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2786 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2787 MlmeSetPsmBit(pAd, PWR_SAVE);
2788 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2790 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2794 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2800 // IRQL = PASSIVE_LEVEL
2801 // IRQL = DISPATCH_LEVEL
2803 IN PRTMP_ADAPTER pAd,
2806 AUTO_RSP_CFG_STRUC csr4;
2808 pAd->StaCfg.Psm = psm;
2809 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2810 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2811 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2813 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2816 // IRQL = DISPATCH_LEVEL
2817 VOID MlmeSetTxPreamble(
2818 IN PRTMP_ADAPTER pAd,
2819 IN USHORT TxPreamble)
2821 AUTO_RSP_CFG_STRUC csr4;
2824 // Always use Long preamble before verifiation short preamble functionality works well.
2825 // Todo: remove the following line if short preamble functionality works
2827 //TxPreamble = Rt802_11PreambleLong;
2829 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2830 if (TxPreamble == Rt802_11PreambleLong)
2832 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2833 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2834 csr4.field.AutoResponderPreamble = 0;
2838 // NOTE: 1Mbps should always use long preamble
2839 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2840 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2841 csr4.field.AutoResponderPreamble = 1;
2844 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2848 ==========================================================================
2850 Update basic rate bitmap
2851 ==========================================================================
2854 VOID UpdateBasicRateBitmap(
2855 IN PRTMP_ADAPTER pAdapter)
2858 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2859 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2860 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2861 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2862 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2865 /* if A mode, always use fix BasicRateBitMap */
2866 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2867 if (pAdapter->CommonCfg.Channel > 14)
2868 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2871 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2873 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2877 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2883 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2885 if (bitmap & (1 << i))
2887 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2889 if (sup_p[j] == rate[i])
2894 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2896 if (ext_p[j] == rate[i])
2902 } /* End of UpdateBasicRateBitmap */
2904 // IRQL = PASSIVE_LEVEL
2905 // IRQL = DISPATCH_LEVEL
2906 // bLinkUp is to identify the inital link speed.
2907 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2908 VOID MlmeUpdateTxRates(
2909 IN PRTMP_ADAPTER pAd,
2914 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2915 UCHAR MinSupport = RATE_54;
2916 ULONG BasicRateBitmap = 0;
2917 UCHAR CurrBasicRate = RATE_1;
2918 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2919 PHTTRANSMIT_SETTING pHtPhy = NULL;
2920 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2921 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2922 BOOLEAN *auto_rate_cur_p;
2923 UCHAR HtMcs = MCS_AUTO;
2925 // find max desired rate
2926 UpdateBasicRateBitmap(pAd);
2929 auto_rate_cur_p = NULL;
2930 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2932 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2934 case 2: Rate = RATE_1; num++; break;
2935 case 4: Rate = RATE_2; num++; break;
2936 case 11: Rate = RATE_5_5; num++; break;
2937 case 22: Rate = RATE_11; num++; break;
2938 case 12: Rate = RATE_6; num++; break;
2939 case 18: Rate = RATE_9; num++; break;
2940 case 24: Rate = RATE_12; num++; break;
2941 case 36: Rate = RATE_18; num++; break;
2942 case 48: Rate = RATE_24; num++; break;
2943 case 72: Rate = RATE_36; num++; break;
2944 case 96: Rate = RATE_48; num++; break;
2945 case 108: Rate = RATE_54; num++; break;
2946 //default: Rate = RATE_1; break;
2948 if (MaxDesire < Rate) MaxDesire = Rate;
2951 //===========================================================================
2952 //===========================================================================
2954 pHtPhy = &pAd->StaCfg.HTPhyMode;
2955 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2956 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2958 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2959 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2961 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2962 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2963 (MaxDesire > RATE_11))
2965 MaxDesire = RATE_11;
2969 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2970 pMinHtPhy->word = 0;
2971 pMaxHtPhy->word = 0;
2974 // Auto rate switching is enabled only if more than one DESIRED RATES are
2975 // specified; otherwise disabled
2978 *auto_rate_cur_p = FALSE;
2982 *auto_rate_cur_p = TRUE;
2986 if (HtMcs != MCS_AUTO)
2988 *auto_rate_cur_p = FALSE;
2992 *auto_rate_cur_p = TRUE;
2996 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2998 pSupRate = &pAd->StaActive.SupRate[0];
2999 pExtRate = &pAd->StaActive.ExtRate[0];
3000 SupRateLen = pAd->StaActive.SupRateLen;
3001 ExtRateLen = pAd->StaActive.ExtRateLen;
3005 pSupRate = &pAd->CommonCfg.SupRate[0];
3006 pExtRate = &pAd->CommonCfg.ExtRate[0];
3007 SupRateLen = pAd->CommonCfg.SupRateLen;
3008 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3011 // find max supported rate
3012 for (i=0; i<SupRateLen; i++)
3014 switch (pSupRate[i] & 0x7f)
3016 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3017 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3018 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3019 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3020 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3021 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3022 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3023 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3024 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3025 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3026 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3027 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3028 default: Rate = RATE_1; break;
3030 if (MaxSupport < Rate) MaxSupport = Rate;
3032 if (MinSupport > Rate) MinSupport = Rate;
3035 for (i=0; i<ExtRateLen; i++)
3037 switch (pExtRate[i] & 0x7f)
3039 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3040 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3041 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3042 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3043 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3044 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3045 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3046 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3047 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3048 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3049 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3050 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3051 default: Rate = RATE_1; break;
3053 if (MaxSupport < Rate) MaxSupport = Rate;
3055 if (MinSupport > Rate) MinSupport = Rate;
3058 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3060 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3061 // the DURATION field of outgoing uniicast DATA/MGMT frame
3062 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3064 if (BasicRateBitmap & (0x01 << i))
3065 CurrBasicRate = (UCHAR)i;
3066 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3069 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3070 // max tx rate = min {max desire rate, max supported rate}
3071 if (MaxSupport < MaxDesire)
3072 pAd->CommonCfg.MaxTxRate = MaxSupport;
3074 pAd->CommonCfg.MaxTxRate = MaxDesire;
3076 pAd->CommonCfg.MinTxRate = MinSupport;
3077 if (*auto_rate_cur_p)
3081 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3083 if (bLinkUp == TRUE)
3084 pAd->CommonCfg.TxRate = RATE_24;
3086 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3089 pAd->CommonCfg.TxRate = RATE_11;
3091 pAd->CommonCfg.TxRate = RATE_24;
3093 // should never exceed MaxTxRate (consider 11B-only mode)
3094 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3095 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3097 pAd->CommonCfg.TxRateIndex = 0;
3101 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3102 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3103 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3105 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3106 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3107 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3108 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3111 if (pAd->CommonCfg.TxRate <= RATE_11)
3113 pMaxHtPhy->field.MODE = MODE_CCK;
3114 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3115 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3119 pMaxHtPhy->field.MODE = MODE_OFDM;
3120 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3121 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3122 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3124 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3127 pHtPhy->word = (pMaxHtPhy->word);
3128 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3130 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3131 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3132 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3136 switch (pAd->CommonCfg.PhyMode)
3138 case PHY_11BG_MIXED:
3140 case PHY_11BGN_MIXED:
3141 pAd->CommonCfg.MlmeRate = RATE_1;
3142 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3143 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3144 pAd->CommonCfg.RtsRate = RATE_11;
3148 case PHY_11AGN_MIXED:
3149 case PHY_11GN_MIXED:
3151 case PHY_11AN_MIXED:
3153 pAd->CommonCfg.MlmeRate = RATE_6;
3154 pAd->CommonCfg.RtsRate = RATE_6;
3155 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3156 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3158 case PHY_11ABG_MIXED:
3159 case PHY_11ABGN_MIXED:
3160 if (pAd->CommonCfg.Channel <= 14)
3162 pAd->CommonCfg.MlmeRate = RATE_1;
3163 pAd->CommonCfg.RtsRate = RATE_1;
3164 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3165 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3169 pAd->CommonCfg.MlmeRate = RATE_6;
3170 pAd->CommonCfg.RtsRate = RATE_6;
3171 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3172 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3176 pAd->CommonCfg.MlmeRate = RATE_6;
3177 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3178 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3179 pAd->CommonCfg.RtsRate = RATE_1;
3183 // Keep Basic Mlme Rate.
3185 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3186 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3187 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3189 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3190 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3193 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3194 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3195 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3196 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3197 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3198 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3199 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 ));
3203 ==========================================================================
3205 This function update HT Rate setting.
3206 Input Wcid value is valid for 2 case :
3207 1. it's used for Station in infra mode that copy AP rate to Mactable.
3208 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3210 IRQL = DISPATCH_LEVEL
3212 ==========================================================================
3214 VOID MlmeUpdateHtTxRates(
3215 IN PRTMP_ADAPTER pAd,
3218 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3220 RT_HT_CAPABILITY *pRtHtCap = NULL;
3221 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3224 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3225 PHTTRANSMIT_SETTING pHtPhy = NULL;
3226 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3227 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3228 BOOLEAN *auto_rate_cur_p;
3230 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3232 auto_rate_cur_p = NULL;
3235 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3236 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3237 pHtPhy = &pAd->StaCfg.HTPhyMode;
3238 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3239 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3241 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3244 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3246 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3249 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3250 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3251 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3252 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3253 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3254 pMaxHtPhy->field.STBC = STBC_USE;
3256 pMaxHtPhy->field.STBC = STBC_NONE;
3260 if (pDesireHtPhy->bHtEnable == FALSE)
3263 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3264 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3265 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3266 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3267 pMaxHtPhy->field.STBC = STBC_USE;
3269 pMaxHtPhy->field.STBC = STBC_NONE;
3272 // Decide MAX ht rate.
3273 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3274 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3276 pMaxHtPhy->field.MODE = MODE_HTMIX;
3278 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3279 pMaxHtPhy->field.BW = BW_40;
3281 pMaxHtPhy->field.BW = BW_20;
3283 if (pMaxHtPhy->field.BW == BW_20)
3284 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3286 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3288 for (i=23; i>=0; i--) // 3*3
3291 bitmask = (1<<(i-(j*8)));
3293 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3295 pMaxHtPhy->field.MCS = i;
3303 // Copy MIN ht rate. rt2860???
3304 pMinHtPhy->field.BW = BW_20;
3305 pMinHtPhy->field.MCS = 0;
3306 pMinHtPhy->field.STBC = 0;
3307 pMinHtPhy->field.ShortGI = 0;
3308 //If STA assigns fixed rate. update to fixed here.
3309 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3311 if (pDesireHtPhy->MCSSet[4] != 0)
3313 pMaxHtPhy->field.MCS = 32;
3314 pMinHtPhy->field.MCS = 32;
3315 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3318 for (i=23; (CHAR)i >= 0; i--) // 3*3
3321 bitmask = (1<<(i-(j*8)));
3322 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3324 pMaxHtPhy->field.MCS = i;
3325 pMinHtPhy->field.MCS = i;
3334 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3335 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3336 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3337 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3338 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3340 // use default now. rt2860
3341 if (pDesireHtPhy->MCSSet[0] != 0xff)
3342 *auto_rate_cur_p = FALSE;
3344 *auto_rate_cur_p = TRUE;
3346 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3347 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3348 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3349 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3352 // IRQL = DISPATCH_LEVEL
3354 IN PRTMP_ADAPTER pAd)
3356 RT28XX_MLME_RADIO_OFF(pAd);
3359 // IRQL = DISPATCH_LEVEL
3361 IN PRTMP_ADAPTER pAd)
3363 RT28XX_MLME_RADIO_ON(pAd);
3366 // ===========================================================================================
3368 // ===========================================================================================
3371 /*! \brief initialize BSS table
3372 * \param p_tab pointer to the table
3377 IRQL = PASSIVE_LEVEL
3378 IRQL = DISPATCH_LEVEL
3387 Tab->BssOverlapNr = 0;
3388 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3390 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3391 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3396 IN PRTMP_ADAPTER pAd,
3401 Tab->numAsOriginator = 0;
3402 Tab->numAsRecipient = 0;
3403 NdisAllocateSpinLock(&pAd->BATabLock);
3404 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3406 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3407 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3409 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3411 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3415 /*! \brief search the BSS table by SSID
3416 * \param p_tab pointer to the bss table
3417 * \param ssid SSID string
3418 * \return index of the table, BSS_NOT_FOUND if not in the table
3421 * \note search by sequential search
3423 IRQL = DISPATCH_LEVEL
3426 ULONG BssTableSearch(
3433 for (i = 0; i < Tab->BssNr; i++)
3436 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3437 // We should distinguish this case.
3439 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3440 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3441 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3446 return (ULONG)BSS_NOT_FOUND;
3449 ULONG BssSsidTableSearch(
3458 for (i = 0; i < Tab->BssNr; i++)
3461 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3462 // We should distinguish this case.
3464 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3465 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3466 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3467 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3472 return (ULONG)BSS_NOT_FOUND;
3475 ULONG BssTableSearchWithSSID(
3484 for (i = 0; i < Tab->BssNr; i++)
3486 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3487 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3488 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3489 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3490 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3491 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3496 return (ULONG)BSS_NOT_FOUND;
3499 // IRQL = DISPATCH_LEVEL
3500 VOID BssTableDeleteEntry(
3501 IN OUT BSS_TABLE *Tab,
3507 for (i = 0; i < Tab->BssNr; i++)
3509 if ((Tab->BssEntry[i].Channel == Channel) &&
3510 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3512 for (j = i; j < Tab->BssNr - 1; j++)
3514 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3516 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3524 ========================================================================
3525 Routine Description:
3526 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3529 // IRQL = DISPATCH_LEVEL
3530 ========================================================================
3532 VOID BATableDeleteORIEntry(
3533 IN OUT PRTMP_ADAPTER pAd,
3534 IN BA_ORI_ENTRY *pBAORIEntry)
3537 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3539 NdisAcquireSpinLock(&pAd->BATabLock);
3540 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3542 pAd->BATable.numAsOriginator -= 1;
3543 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3544 // Erase Bitmap flag.
3546 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3547 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3548 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3549 pBAORIEntry->Token = 1;
3550 // Not clear Sequence here.
3551 NdisReleaseSpinLock(&pAd->BATabLock);
3561 IRQL = DISPATCH_LEVEL
3565 IN PRTMP_ADAPTER pAd,
3566 OUT BSS_ENTRY *pBss,
3571 IN USHORT BeaconPeriod,
3572 IN PCF_PARM pCfParm,
3574 IN USHORT CapabilityInfo,
3576 IN UCHAR SupRateLen,
3578 IN UCHAR ExtRateLen,
3579 IN HT_CAPABILITY_IE *pHtCapability,
3580 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3581 IN UCHAR HtCapabilityLen,
3582 IN UCHAR AddHtInfoLen,
3583 IN UCHAR NewExtChanOffset,
3586 IN LARGE_INTEGER TimeStamp,
3588 IN PEDCA_PARM pEdcaParm,
3589 IN PQOS_CAPABILITY_PARM pQosCapability,
3590 IN PQBSS_LOAD_PARM pQbssLoad,
3591 IN USHORT LengthVIE,
3592 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3594 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3595 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3599 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3600 // Or send beacon /probe response with SSID len matching real SSID length,
3601 // but SSID is all zero. such as "00-00-00-00" with length 4.
3602 // We have to prevent this case overwrite correct table
3603 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3605 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3606 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3607 pBss->SsidLen = SsidLen;
3613 pBss->BssType = BssType;
3614 pBss->BeaconPeriod = BeaconPeriod;
3615 if (BssType == BSS_INFRA)
3617 if (pCfParm->bValid)
3619 pBss->CfpCount = pCfParm->CfpCount;
3620 pBss->CfpPeriod = pCfParm->CfpPeriod;
3621 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3622 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3627 pBss->AtimWin = AtimWin;
3630 pBss->CapabilityInfo = CapabilityInfo;
3631 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3632 // Combine with AuthMode, they will decide the connection methods.
3633 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3634 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3635 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3636 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3638 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3639 pBss->SupRateLen = SupRateLen;
3640 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3641 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3642 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3643 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3644 pBss->NewExtChanOffset = NewExtChanOffset;
3645 pBss->ExtRateLen = ExtRateLen;
3646 pBss->Channel = Channel;
3647 pBss->CentralChannel = Channel;
3649 // Update CkipFlag. if not exists, the value is 0x0
3650 pBss->CkipFlag = CkipFlag;
3652 // New for microsoft Fixed IEs
3653 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3654 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3655 pBss->FixIEs.Capabilities = CapabilityInfo;
3657 // New for microsoft Variable IEs
3660 pBss->VarIELen = LengthVIE;
3661 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3668 pBss->AddHtInfoLen = 0;
3669 pBss->HtCapabilityLen = 0;
3671 if (HtCapabilityLen> 0)
3673 pBss->HtCapabilityLen = HtCapabilityLen;
3674 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3675 if (AddHtInfoLen > 0)
3677 pBss->AddHtInfoLen = AddHtInfoLen;
3678 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3680 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3682 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3684 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3686 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3691 BssCipherParse(pBss);
3695 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3697 pBss->EdcaParm.bValid = FALSE;
3699 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3701 pBss->QosCapability.bValid = FALSE;
3703 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3705 pBss->QbssLoad.bValid = FALSE;
3712 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3713 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3715 pEid = (PEID_STRUCT) pVIE;
3717 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3722 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3724 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3726 pBss->WpaIE.IELen = 0;
3729 pBss->WpaIE.IELen = pEid->Len + 2;
3730 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3734 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3736 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3738 pBss->RsnIE.IELen = 0;
3741 pBss->RsnIE.IELen = pEid->Len + 2;
3742 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3746 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3747 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3753 * \brief insert an entry into the bss table
3754 * \param p_tab The BSS table
3755 * \param Bssid BSSID
3757 * \param ssid_len Length of SSID
3759 * \param beacon_period
3766 * \param channel_idx
3770 * \note If SSID is identical, the old entry will be replaced by the new one
3772 IRQL = DISPATCH_LEVEL
3775 ULONG BssTableSetEntry(
3776 IN PRTMP_ADAPTER pAd,
3782 IN USHORT BeaconPeriod,
3785 IN USHORT CapabilityInfo,
3787 IN UCHAR SupRateLen,
3789 IN UCHAR ExtRateLen,
3790 IN HT_CAPABILITY_IE *pHtCapability,
3791 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3792 IN UCHAR HtCapabilityLen,
3793 IN UCHAR AddHtInfoLen,
3794 IN UCHAR NewExtChanOffset,
3797 IN LARGE_INTEGER TimeStamp,
3799 IN PEDCA_PARM pEdcaParm,
3800 IN PQOS_CAPABILITY_PARM pQosCapability,
3801 IN PQBSS_LOAD_PARM pQbssLoad,
3802 IN USHORT LengthVIE,
3803 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3807 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3808 if (Idx == BSS_NOT_FOUND)
3810 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3813 // It may happen when BSS Table was full.
3814 // The desired AP will not be added into BSS Table
3815 // In this case, if we found the desired AP then overwrite BSS Table.
3817 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3819 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3820 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3822 Idx = Tab->BssOverlapNr;
3823 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3824 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3825 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3826 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3832 return BSS_NOT_FOUND;
3836 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3837 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3838 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3844 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3845 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3846 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3849 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3850 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3851 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3860 // IRQL = DISPATCH_LEVEL
3861 VOID BssTableSsidSort(
3862 IN PRTMP_ADAPTER pAd,
3863 OUT BSS_TABLE *OutTab,
3868 BssTableInit(OutTab);
3870 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3872 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3873 BOOLEAN bIsHiddenApIncluded = FALSE;
3875 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3876 (pAd->MlmeAux.Channel > 14) &&
3877 RadarChannelCheck(pAd, pInBss->Channel))
3881 bIsHiddenApIncluded = TRUE;
3884 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3885 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3887 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3889 // 2.4G/5G N only mode
3890 if ((pInBss->HtCapabilityLen == 0) &&
3891 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3893 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3898 // Check the Authmode first
3899 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3901 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3902 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3906 // Check cipher suite, AP must have more secured cipher than station setting
3907 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3909 // If it's not mixed mode, we should only let BSS pass with the same encryption
3910 if (pInBss->WPA.bMixMode == FALSE)
3911 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3914 // check group cipher
3917 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3918 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3920 pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3923 // check pairwise cipher, skip if none matched
3924 // If profile set to AES, let it pass without question.
3925 // If profile set to TKIP, we must find one mateched
3926 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3927 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3928 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3931 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3933 // If it's not mixed mode, we should only let BSS pass with the same encryption
3934 if (pInBss->WPA2.bMixMode == FALSE)
3935 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3938 // check group cipher
3941 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3942 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3944 pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3947 // check pairwise cipher, skip if none matched
3948 // If profile set to AES, let it pass without question.
3949 // If profile set to TKIP, we must find one mateched
3950 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3951 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3952 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3956 // Bss Type matched, SSID matched.
3957 // We will check wepstatus for qualification Bss
3958 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3960 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3962 // For the SESv2 case, we will not qualify WepStatus.
3968 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3969 // It definitely will fail. So, skip it.
3970 // CCX also require not even try to connect it!!
3974 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3975 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3976 if ((pInBss->CentralChannel != pInBss->Channel) &&
3977 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3979 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3981 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3983 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3987 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3994 // copy matching BSS from InTab to OutTab
3995 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3999 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4001 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4003 // 2.4G/5G N only mode
4004 if ((pInBss->HtCapabilityLen == 0) &&
4005 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4007 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4012 // Check the Authmode first
4013 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4015 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4016 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4020 // Check cipher suite, AP must have more secured cipher than station setting
4021 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4023 // If it's not mixed mode, we should only let BSS pass with the same encryption
4024 if (pInBss->WPA.bMixMode == FALSE)
4025 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4028 // check group cipher
4029 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4032 // check pairwise cipher, skip if none matched
4033 // If profile set to AES, let it pass without question.
4034 // If profile set to TKIP, we must find one mateched
4035 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4036 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4037 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4040 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4042 // If it's not mixed mode, we should only let BSS pass with the same encryption
4043 if (pInBss->WPA2.bMixMode == FALSE)
4044 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4047 // check group cipher
4048 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4051 // check pairwise cipher, skip if none matched
4052 // If profile set to AES, let it pass without question.
4053 // If profile set to TKIP, we must find one mateched
4054 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4055 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4056 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4060 // Bss Type matched, SSID matched.
4061 // We will check wepstatus for qualification Bss
4062 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4065 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4066 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4067 if ((pInBss->CentralChannel != pInBss->Channel) &&
4068 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4070 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4072 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4074 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4078 // copy matching BSS from InTab to OutTab
4079 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4084 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4088 BssTableSortByRssi(OutTab);
4092 // IRQL = DISPATCH_LEVEL
4093 VOID BssTableSortByRssi(
4094 IN OUT BSS_TABLE *OutTab)
4099 for (i = 0; i < OutTab->BssNr - 1; i++)
4101 for (j = i+1; j < OutTab->BssNr; j++)
4103 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4105 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4106 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4107 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4113 VOID BssCipherParse(
4114 IN OUT PBSS_ENTRY pBss)
4118 PRSN_IE_HEADER_STRUCT pRsnHeader;
4119 PCIPHER_SUITE_STRUCT pCipher;
4120 PAKM_SUITE_STRUCT pAKM;
4123 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4126 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4130 pBss->WepStatus = Ndis802_11WEPEnabled;
4134 pBss->WepStatus = Ndis802_11WEPDisabled;
4136 // Set default to disable & open authentication before parsing variable IE
4137 pBss->AuthMode = Ndis802_11AuthModeOpen;
4138 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4141 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4142 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4143 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4144 pBss->WPA.RsnCapability = 0;
4145 pBss->WPA.bMixMode = FALSE;
4147 // Init WPA2 setting
4148 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4149 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4150 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4151 pBss->WPA2.RsnCapability = 0;
4152 pBss->WPA2.bMixMode = FALSE;
4155 Length = (INT) pBss->VarIELen;
4159 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4160 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4161 pEid = (PEID_STRUCT) pTmp;
4165 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4166 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4172 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4173 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4174 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4175 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4178 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4179 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4180 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4183 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4184 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4185 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4191 // if Cisco IE_WPA, break
4194 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4199 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4201 // if unsupported vendor specific IE
4204 // Skip OUI, version, and multicast suite
4205 // This part should be improved in the future when AP supported multiple cipher suite.
4206 // For now, it's OK since almost all APs have fixed cipher suite supported.
4207 // pTmp = (PUCHAR) pEid->Octet;
4210 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4218 // Parse group cipher
4223 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4226 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4229 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4230 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4234 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4237 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4242 // number of unicast suite
4245 // skip all unicast cipher suites
4246 //Count = *(PUSHORT) pTmp;
4247 Count = (pTmp[1]<<8) + pTmp[0];
4248 pTmp += sizeof(USHORT);
4250 // Parsing all unicast cipher suite
4255 TmpCipher = Ndis802_11WEPDisabled;
4259 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4260 TmpCipher = Ndis802_11Encryption1Enabled;
4263 TmpCipher = Ndis802_11Encryption2Enabled;
4266 TmpCipher = Ndis802_11Encryption3Enabled;
4271 if (TmpCipher > pBss->WPA.PairCipher)
4273 // Move the lower cipher suite to PairCipherAux
4274 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4275 pBss->WPA.PairCipher = TmpCipher;
4279 pBss->WPA.PairCipherAux = TmpCipher;
4285 // 4. get AKM suite counts
4286 //Count = *(PUSHORT) pTmp;
4287 Count = (pTmp[1]<<8) + pTmp[0];
4288 pTmp += sizeof(USHORT);
4294 // Set AP support WPA mode
4295 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4296 pBss->AuthMode = Ndis802_11AuthModeWPA;
4298 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4301 // Set AP support WPA mode
4302 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4303 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4305 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4312 // Fixed for WPA-None
4313 if (pBss->BssType == BSS_ADHOC)
4315 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4316 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4317 pBss->WepStatus = pBss->WPA.GroupCipher;
4318 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4319 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4322 pBss->WepStatus = pBss->WPA.PairCipher;
4324 // Check the Pair & Group, if different, turn on mixed mode flag
4325 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4326 pBss->WPA.bMixMode = TRUE;
4331 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4333 // 0. Version must be 1
4334 if (le2cpu16(pRsnHeader->Version) != 1)
4336 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4338 // 1. Check group cipher
4339 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4340 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4343 // Parse group cipher
4344 switch (pCipher->Type)
4348 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4351 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4354 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4355 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4359 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4362 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4367 // set to correct offset for next parsing
4368 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4370 // 2. Get pairwise cipher counts
4371 //Count = *(PUSHORT) pTmp;
4372 Count = (pTmp[1]<<8) + pTmp[0];
4373 pTmp += sizeof(USHORT);
4375 // 3. Get pairwise cipher
4376 // Parsing all unicast cipher suite
4380 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4381 TmpCipher = Ndis802_11WEPDisabled;
4382 switch (pCipher->Type)
4385 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4386 TmpCipher = Ndis802_11Encryption1Enabled;
4389 TmpCipher = Ndis802_11Encryption2Enabled;
4392 TmpCipher = Ndis802_11Encryption3Enabled;
4397 if (TmpCipher > pBss->WPA2.PairCipher)
4399 // Move the lower cipher suite to PairCipherAux
4400 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4401 pBss->WPA2.PairCipher = TmpCipher;
4405 pBss->WPA2.PairCipherAux = TmpCipher;
4407 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4411 // 4. get AKM suite counts
4412 //Count = *(PUSHORT) pTmp;
4413 Count = (pTmp[1]<<8) + pTmp[0];
4414 pTmp += sizeof(USHORT);
4416 // 5. Get AKM ciphers
4417 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4418 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4424 // Set AP support WPA mode
4425 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4426 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4428 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4431 // Set AP support WPA mode
4432 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4433 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4435 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4440 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4442 // Fixed for WPA-None
4443 if (pBss->BssType == BSS_ADHOC)
4445 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4446 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4447 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4448 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4449 pBss->WepStatus = pBss->WPA.GroupCipher;
4450 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4451 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4453 pBss->WepStatus = pBss->WPA2.PairCipher;
4455 // 6. Get RSN capability
4456 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4457 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4458 pTmp += sizeof(USHORT);
4460 // Check the Pair & Group, if different, turn on mixed mode flag
4461 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4462 pBss->WPA2.bMixMode = TRUE;
4468 Length -= (pEid->Len + 2);
4472 // ===========================================================================================
4474 // ===========================================================================================
4476 /*! \brief generates a random mac address value for IBSS BSSID
4477 * \param Addr the bssid location
4482 VOID MacAddrRandomBssid(
4483 IN PRTMP_ADAPTER pAd,
4488 for (i = 0; i < MAC_ADDR_LEN; i++)
4490 pAddr[i] = RandomByte(pAd);
4493 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4496 /*! \brief init the management mac frame header
4497 * \param p_hdr mac header
4498 * \param subtype subtype of the frame
4499 * \param p_ds destination address, don't care if it is a broadcast address
4501 * \pre the station has the following information in the pAd->StaCfg
4505 * \note this function initializes the following field
4507 IRQL = PASSIVE_LEVEL
4508 IRQL = DISPATCH_LEVEL
4511 VOID MgtMacHeaderInit(
4512 IN PRTMP_ADAPTER pAd,
4513 IN OUT PHEADER_802_11 pHdr80211,
4519 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4521 pHdr80211->FC.Type = BTYPE_MGMT;
4522 pHdr80211->FC.SubType = SubType;
4523 pHdr80211->FC.ToDs = ToDs;
4524 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4526 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4528 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4531 // ===========================================================================================
4533 // ===========================================================================================
4535 /*!***************************************************************************
4536 * This routine build an outgoing frame, and fill all information specified
4537 * in argument list to the frame body. The actual frame size is the summation
4540 * Buffer - pointer to a pre-allocated memory segment
4541 * args - a list of <int arg_size, arg> pairs.
4542 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4543 * function will FAIL!!!
4545 * Size of the buffer
4547 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4549 IRQL = PASSIVE_LEVEL
4550 IRQL = DISPATCH_LEVEL
4552 ****************************************************************************/
4553 ULONG MakeOutgoingFrame(
4555 OUT ULONG *FrameLen, ...)
4562 // calculates the total length
4564 va_start(Args, FrameLen);
4567 leng = va_arg(Args, int);
4568 if (leng == END_OF_ARGS)
4572 p = va_arg(Args, PVOID);
4573 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4574 TotLeng = TotLeng + leng;
4577 va_end(Args); /* clean up */
4578 *FrameLen = TotLeng;
4582 // ===========================================================================================
4584 // ===========================================================================================
4586 /*! \brief Initialize The MLME Queue, used by MLME Functions
4587 * \param *Queue The MLME Queue
4588 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4591 * \note Because this is done only once (at the init stage), no need to be locked
4593 IRQL = PASSIVE_LEVEL
4596 NDIS_STATUS MlmeQueueInit(
4597 IN MLME_QUEUE *Queue)
4601 NdisAllocateSpinLock(&Queue->Lock);
4607 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4609 Queue->Entry[i].Occupied = FALSE;
4610 Queue->Entry[i].MsgLen = 0;
4611 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4614 return NDIS_STATUS_SUCCESS;
4617 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4618 * \param *Queue The MLME Queue
4619 * \param Machine The State Machine Id
4620 * \param MsgType The Message Type
4621 * \param MsgLen The Message length
4622 * \param *Msg The message pointer
4623 * \return TRUE if enqueue is successful, FALSE if the queue is full
4626 * \note The message has to be initialized
4628 IRQL = PASSIVE_LEVEL
4629 IRQL = DISPATCH_LEVEL
4632 BOOLEAN MlmeEnqueue(
4633 IN PRTMP_ADAPTER pAd,
4640 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4642 // Do nothing if the driver is starting halt state.
4643 // This might happen when timer already been fired before cancel timer with mlmehalt
4644 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4647 // First check the size, it MUST not exceed the mlme queue size
4648 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4650 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4654 if (MlmeQueueFull(Queue))
4659 NdisAcquireSpinLock(&(Queue->Lock));
4663 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4668 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4669 Queue->Entry[Tail].Occupied = TRUE;
4670 Queue->Entry[Tail].Machine = Machine;
4671 Queue->Entry[Tail].MsgType = MsgType;
4672 Queue->Entry[Tail].MsgLen = MsgLen;
4676 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4679 NdisReleaseSpinLock(&(Queue->Lock));
4683 /*! \brief This function is used when Recv gets a MLME message
4684 * \param *Queue The MLME Queue
4685 * \param TimeStampHigh The upper 32 bit of timestamp
4686 * \param TimeStampLow The lower 32 bit of timestamp
4687 * \param Rssi The receiving RSSI strength
4688 * \param MsgLen The length of the message
4689 * \param *Msg The message pointer
4690 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4694 IRQL = DISPATCH_LEVEL
4697 BOOLEAN MlmeEnqueueForRecv(
4698 IN PRTMP_ADAPTER pAd,
4700 IN ULONG TimeStampHigh,
4701 IN ULONG TimeStampLow,
4710 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4712 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4714 // Do nothing if the driver is starting halt state.
4715 // This might happen when timer already been fired before cancel timer with mlmehalt
4716 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4718 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4722 // First check the size, it MUST not exceed the mlme queue size
4723 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4725 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4729 if (MlmeQueueFull(Queue))
4735 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4737 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4742 // OK, we got all the informations, it is time to put things into queue
4743 NdisAcquireSpinLock(&(Queue->Lock));
4747 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4751 Queue->Entry[Tail].Occupied = TRUE;
4752 Queue->Entry[Tail].Machine = Machine;
4753 Queue->Entry[Tail].MsgType = MsgType;
4754 Queue->Entry[Tail].MsgLen = MsgLen;
4755 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4756 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4757 Queue->Entry[Tail].Rssi0 = Rssi0;
4758 Queue->Entry[Tail].Rssi1 = Rssi1;
4759 Queue->Entry[Tail].Rssi2 = Rssi2;
4760 Queue->Entry[Tail].Signal = Signal;
4761 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4763 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4767 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4770 NdisReleaseSpinLock(&(Queue->Lock));
4772 RT28XX_MLME_HANDLER(pAd);
4778 /*! \brief Dequeue a message from the MLME Queue
4779 * \param *Queue The MLME Queue
4780 * \param *Elem The message dequeued from MLME Queue
4781 * \return TRUE if the Elem contains something, FALSE otherwise
4785 IRQL = DISPATCH_LEVEL
4788 BOOLEAN MlmeDequeue(
4789 IN MLME_QUEUE *Queue,
4790 OUT MLME_QUEUE_ELEM **Elem)
4792 NdisAcquireSpinLock(&(Queue->Lock));
4793 *Elem = &(Queue->Entry[Queue->Head]);
4796 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4800 NdisReleaseSpinLock(&(Queue->Lock));
4804 // IRQL = DISPATCH_LEVEL
4805 VOID MlmeRestartStateMachine(
4806 IN PRTMP_ADAPTER pAd)
4809 MLME_QUEUE_ELEM *Elem = NULL;
4813 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4816 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4817 if(pAd->Mlme.bRunning)
4819 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4824 pAd->Mlme.bRunning = TRUE;
4826 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4828 // Remove all Mlme queues elements
4829 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4831 //From message type, determine which state machine I should drive
4832 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4834 // free MLME element
4835 Elem->Occupied = FALSE;
4840 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4846 // Cancel all timer events
4847 // Be careful to cancel new added timer
4848 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4849 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4850 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4851 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4852 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4853 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4856 // Change back to original channel in case of doing scan
4857 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4858 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4860 // Resume MSDU which is turned off durning scan
4861 RTMPResumeMsduTransmission(pAd);
4864 // Set all state machines back IDLE
4865 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4866 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4867 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4868 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4869 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4870 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4874 // Remove running state
4875 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4876 pAd->Mlme.bRunning = FALSE;
4877 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4881 /*! \brief test if the MLME Queue is empty
4882 * \param *Queue The MLME Queue
4883 * \return TRUE if the Queue is empty, FALSE otherwise
4887 IRQL = DISPATCH_LEVEL
4890 BOOLEAN MlmeQueueEmpty(
4891 IN MLME_QUEUE *Queue)
4895 NdisAcquireSpinLock(&(Queue->Lock));
4896 Ans = (Queue->Num == 0);
4897 NdisReleaseSpinLock(&(Queue->Lock));
4902 /*! \brief test if the MLME Queue is full
4903 * \param *Queue The MLME Queue
4904 * \return TRUE if the Queue is empty, FALSE otherwise
4908 IRQL = PASSIVE_LEVEL
4909 IRQL = DISPATCH_LEVEL
4912 BOOLEAN MlmeQueueFull(
4913 IN MLME_QUEUE *Queue)
4917 NdisAcquireSpinLock(&(Queue->Lock));
4918 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4919 NdisReleaseSpinLock(&(Queue->Lock));
4924 /*! \brief The destructor of MLME Queue
4929 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4931 IRQL = PASSIVE_LEVEL
4934 VOID MlmeQueueDestroy(
4935 IN MLME_QUEUE *pQueue)
4937 NdisAcquireSpinLock(&(pQueue->Lock));
4941 NdisReleaseSpinLock(&(pQueue->Lock));
4942 NdisFreeSpinLock(&(pQueue->Lock));
4945 /*! \brief To substitute the message type if the message is coming from external
4946 * \param pFrame The frame received
4947 * \param *Machine The state machine
4948 * \param *MsgType the message type for the state machine
4949 * \return TRUE if the substitution is successful, FALSE otherwise
4953 IRQL = DISPATCH_LEVEL
4956 BOOLEAN MsgTypeSubst(
4957 IN PRTMP_ADAPTER pAd,
4958 IN PFRAME_802_11 pFrame,
4966 // Pointer to start of data frames including SNAP header
4967 pData = (PUCHAR) pFrame + LENGTH_802_11;
4969 // The only data type will pass to this function is EAPOL frame
4970 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4972 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4974 // Cisco Aironet SNAP header
4975 *Machine = AIRONET_STATE_MACHINE;
4976 *MsgType = MT2_AIRONET_MSG;
4980 *Machine = WPA_PSK_STATE_MACHINE;
4981 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4982 return(WpaMsgTypeSubst(EAPType, MsgType));
4986 switch (pFrame->Hdr.FC.SubType)
4988 case SUBTYPE_ASSOC_REQ:
4989 *Machine = ASSOC_STATE_MACHINE;
4990 *MsgType = MT2_PEER_ASSOC_REQ;
4992 case SUBTYPE_ASSOC_RSP:
4993 *Machine = ASSOC_STATE_MACHINE;
4994 *MsgType = MT2_PEER_ASSOC_RSP;
4996 case SUBTYPE_REASSOC_REQ:
4997 *Machine = ASSOC_STATE_MACHINE;
4998 *MsgType = MT2_PEER_REASSOC_REQ;
5000 case SUBTYPE_REASSOC_RSP:
5001 *Machine = ASSOC_STATE_MACHINE;
5002 *MsgType = MT2_PEER_REASSOC_RSP;
5004 case SUBTYPE_PROBE_REQ:
5005 *Machine = SYNC_STATE_MACHINE;
5006 *MsgType = MT2_PEER_PROBE_REQ;
5008 case SUBTYPE_PROBE_RSP:
5009 *Machine = SYNC_STATE_MACHINE;
5010 *MsgType = MT2_PEER_PROBE_RSP;
5012 case SUBTYPE_BEACON:
5013 *Machine = SYNC_STATE_MACHINE;
5014 *MsgType = MT2_PEER_BEACON;
5017 *Machine = SYNC_STATE_MACHINE;
5018 *MsgType = MT2_PEER_ATIM;
5020 case SUBTYPE_DISASSOC:
5021 *Machine = ASSOC_STATE_MACHINE;
5022 *MsgType = MT2_PEER_DISASSOC_REQ;
5025 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5026 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5027 if (Seq == 1 || Seq == 3)
5029 *Machine = AUTH_RSP_STATE_MACHINE;
5030 *MsgType = MT2_PEER_AUTH_ODD;
5032 else if (Seq == 2 || Seq == 4)
5034 *Machine = AUTH_STATE_MACHINE;
5035 *MsgType = MT2_PEER_AUTH_EVEN;
5042 case SUBTYPE_DEAUTH:
5043 *Machine = AUTH_RSP_STATE_MACHINE;
5044 *MsgType = MT2_PEER_DEAUTH;
5046 case SUBTYPE_ACTION:
5047 *Machine = ACTION_STATE_MACHINE;
5048 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5049 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5051 *MsgType = MT2_ACT_INVALID;
5055 *MsgType = (pFrame->Octet[0]&0x7F);
5066 // ===========================================================================================
5068 // ===========================================================================================
5070 /*! \brief Initialize the state machine.
5071 * \param *S pointer to the state machine
5072 * \param Trans State machine transition function
5073 * \param StNr number of states
5074 * \param MsgNr number of messages
5075 * \param DefFunc default function, when there is invalid state/message combination
5076 * \param InitState initial state of the state machine
5077 * \param Base StateMachine base, internal use only
5078 * \pre p_sm should be a legal pointer
5081 IRQL = PASSIVE_LEVEL
5084 VOID StateMachineInit(
5085 IN STATE_MACHINE *S,
5086 IN STATE_MACHINE_FUNC Trans[],
5089 IN STATE_MACHINE_FUNC DefFunc,
5095 // set number of states and messages
5100 S->TransFunc = Trans;
5102 // init all state transition to default function
5103 for (i = 0; i < StNr; i++)
5105 for (j = 0; j < MsgNr; j++)
5107 S->TransFunc[i * MsgNr + j] = DefFunc;
5111 // set the starting state
5112 S->CurrState = InitState;
5115 /*! \brief This function fills in the function pointer into the cell in the state machine
5116 * \param *S pointer to the state machine
5118 * \param Msg incoming message
5119 * \param f the function to be executed when (state, message) combination occurs at the state machine
5120 * \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
5123 IRQL = PASSIVE_LEVEL
5126 VOID StateMachineSetAction(
5127 IN STATE_MACHINE *S,
5130 IN STATE_MACHINE_FUNC Func)
5134 MsgIdx = Msg - S->Base;
5136 if (St < S->NrState && MsgIdx < S->NrMsg)
5138 // boundary checking before setting the action
5139 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5143 /*! \brief This function does the state transition
5144 * \param *Adapter the NIC adapter pointer
5145 * \param *S the state machine
5146 * \param *Elem the message to be executed
5149 IRQL = DISPATCH_LEVEL
5152 VOID StateMachinePerformAction(
5153 IN PRTMP_ADAPTER pAd,
5154 IN STATE_MACHINE *S,
5155 IN MLME_QUEUE_ELEM *Elem)
5157 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5161 ==========================================================================
5163 The drop function, when machine executes this, the message is simply
5164 ignored. This function does nothing, the message is freed in
5165 StateMachinePerformAction()
5166 ==========================================================================
5169 IN PRTMP_ADAPTER pAd,
5170 IN MLME_QUEUE_ELEM *Elem)
5174 // ===========================================================================================
5176 // ===========================================================================================
5179 ==========================================================================
5182 IRQL = PASSIVE_LEVEL
5184 ==========================================================================
5187 IN PRTMP_ADAPTER pAd,
5191 pAd->Mlme.ShiftReg = 1;
5193 pAd->Mlme.ShiftReg = Seed;
5197 ==========================================================================
5199 ==========================================================================
5202 IN PRTMP_ADAPTER pAd)
5209 if (pAd->Mlme.ShiftReg == 0)
5210 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5212 for (i = 0; i < 8; i++)
5214 if (pAd->Mlme.ShiftReg & 0x00000001)
5216 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5221 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5224 R = (R << 1) | Result;
5230 VOID AsicUpdateAutoFallBackTable(
5231 IN PRTMP_ADAPTER pAd,
5232 IN PUCHAR pRateTable)
5235 HT_FBK_CFG0_STRUC HtCfg0;
5236 HT_FBK_CFG1_STRUC HtCfg1;
5237 LG_FBK_CFG0_STRUC LgCfg0;
5238 LG_FBK_CFG1_STRUC LgCfg1;
5239 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5241 // set to initial value
5242 HtCfg0.word = 0x65432100;
5243 HtCfg1.word = 0xedcba988;
5244 LgCfg0.word = 0xedcba988;
5245 LgCfg1.word = 0x00002100;
5247 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5248 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5250 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5251 switch (pCurrTxRate->Mode)
5257 switch(pCurrTxRate->CurrMCS)
5260 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5263 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5266 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5269 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5272 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5275 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5278 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5281 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5289 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5291 switch(pCurrTxRate->CurrMCS)
5294 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5297 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5300 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5303 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5306 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5309 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5312 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5315 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5318 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5321 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5324 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5327 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5330 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5333 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5336 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5339 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5342 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5349 pNextTxRate = pCurrTxRate;
5352 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5353 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5354 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5355 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5359 ========================================================================
5361 Routine Description:
5362 Set MAC register value according operation mode.
5363 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5364 If MM or GF mask is not set, those passing argument doesn't not take effect.
5366 Operation mode meaning:
5367 = 0 : Pure HT, no preotection.
5368 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5369 = 0x10: No Transmission in 40M is protected.
5370 = 0x11: Transmission in both 40M and 20M shall be protected
5372 we should choose not to use GF. But still set correct ASIC registers.
5373 ========================================================================
5375 VOID AsicUpdateProtect(
5376 IN PRTMP_ADAPTER pAd,
5377 IN USHORT OperationMode,
5379 IN BOOLEAN bDisableBGProtect,
5380 IN BOOLEAN bNonGFExist)
5382 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5388 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5393 if (pAd->BATable.numAsOriginator)
5396 // enable the RTS/CTS to avoid channel collision
5398 SetMask = ALLN_SETPROTECT;
5402 // Config ASIC RTS threshold register
5403 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5404 MacReg &= 0xFF0000FF;
5406 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5408 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5409 (pAd->CommonCfg.bAggregationCapable == TRUE))
5410 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5412 MacReg |= (0x1000 << 8);
5416 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5419 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5421 // Initial common protection settings
5422 RTMPZeroMemory(Protect, sizeof(Protect));
5425 ProtCfg.field.TxopAllowGF40 = 1;
5426 ProtCfg.field.TxopAllowGF20 = 1;
5427 ProtCfg.field.TxopAllowMM40 = 1;
5428 ProtCfg.field.TxopAllowMM20 = 1;
5429 ProtCfg.field.TxopAllowOfdm = 1;
5430 ProtCfg.field.TxopAllowCck = 1;
5431 ProtCfg.field.RTSThEn = 1;
5432 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5434 // update PHY mode and rate
5435 if (pAd->CommonCfg.Channel > 14)
5436 ProtCfg.field.ProtectRate = 0x4000;
5437 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5439 // Handle legacy(B/G) protection
5440 if (bDisableBGProtect)
5442 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5443 ProtCfg.field.ProtectCtrl = 0;
5444 Protect[0] = ProtCfg.word;
5445 Protect[1] = ProtCfg.word;
5449 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5450 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5451 Protect[0] = ProtCfg.word;
5452 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5453 Protect[1] = ProtCfg.word;
5456 // Decide HT frame protection.
5457 if ((SetMask & ALLN_SETPROTECT) != 0)
5459 switch(OperationMode)
5463 // 1.All STAs in the BSS are 20/40 MHz HT
5464 // 2. in ai 20/40MHz BSS
5465 // 3. all STAs are 20MHz in a 20MHz BSS
5466 // Pure HT. no protection.
5470 // PROT_TXOP(25:20) -- 010111
5471 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5472 // PROT_CTRL(17:16) -- 00 (None)
5473 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5474 Protect[2] = 0x01744004;
5478 // PROT_TXOP(25:20) -- 111111
5479 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5480 // PROT_CTRL(17:16) -- 00 (None)
5481 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5482 Protect[3] = 0x03f44084;
5486 // PROT_TXOP(25:20) -- 010111
5487 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5488 // PROT_CTRL(17:16) -- 00 (None)
5489 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5490 Protect[4] = 0x01744004;
5494 // PROT_TXOP(25:20) -- 111111
5495 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5496 // PROT_CTRL(17:16) -- 00 (None)
5497 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5498 Protect[5] = 0x03f44084;
5502 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5503 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5504 Protect[4] = 0x01754004;
5505 Protect[5] = 0x03f54084;
5507 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5511 // This is "HT non-member protection mode."
5512 // If there may be non-HT STAs my BSS
5513 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5514 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5515 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5517 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5518 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5520 //Assign Protection method for 20&40 MHz packets
5521 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5522 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5523 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5524 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5525 Protect[2] = ProtCfg.word;
5526 Protect[3] = ProtCfg4.word;
5527 Protect[4] = ProtCfg.word;
5528 Protect[5] = ProtCfg4.word;
5529 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5533 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5534 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5535 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5537 //Assign Protection method for 40MHz packets
5538 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5539 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5540 Protect[2] = ProtCfg.word;
5541 Protect[3] = ProtCfg4.word;
5544 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5545 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5547 Protect[4] = ProtCfg.word;
5548 Protect[5] = ProtCfg4.word;
5550 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5554 // HT mixed mode. PROTECT ALL!
5556 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5557 ProtCfg4.word = 0x03f44084;
5558 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5559 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5561 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5562 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5564 //Assign Protection method for 20&40 MHz packets
5565 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5566 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5567 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5568 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5569 Protect[2] = ProtCfg.word;
5570 Protect[3] = ProtCfg4.word;
5571 Protect[4] = ProtCfg.word;
5572 Protect[5] = ProtCfg4.word;
5573 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5577 // Special on for Atheros problem n chip.
5578 Protect[2] = 0x01754004;
5579 Protect[3] = 0x03f54084;
5580 Protect[4] = 0x01754004;
5581 Protect[5] = 0x03f54084;
5582 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5587 offset = CCK_PROT_CFG;
5588 for (i = 0;i < 6;i++)
5590 if ((SetMask & (1<< i)))
5592 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5598 // add by johnli, RF power sequence setup
5600 ==========================================================================
5603 Load RF normal operation-mode setup
5605 ==========================================================================
5607 VOID RT30xxLoadRFNormalModeSetup(
5608 IN PRTMP_ADAPTER pAd)
5612 // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5613 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5614 RFValue = (RFValue & (~0x0C)) | 0x31;
5615 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5617 // TX_LO2_en, RF R15 register Bit 3 to 0
5618 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5620 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5622 // TX_LO1_en, RF R17 register Bit 3 to 0
5623 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5625 // to fix rx long range issue
5626 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5630 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5632 // RX_LO1_en, RF R20 register Bit 3 to 0
5633 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5635 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5637 // RX_LO2_en, RF R21 register Bit 3 to 0
5638 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5640 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5642 // LDORF_VC, RF R27 register Bit 2 to 0
5643 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5644 if ((pAd->MACVersion & 0xffff) < 0x0211)
5645 RFValue = (RFValue & (~0x77)) | 0x3;
5647 RFValue = (RFValue & (~0x77));
5648 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5653 ==========================================================================
5656 Load RF sleep-mode setup
5658 ==========================================================================
5660 VOID RT30xxLoadRFSleepModeSetup(
5661 IN PRTMP_ADAPTER pAd)
5666 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5667 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5669 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5671 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5672 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5674 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5676 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5677 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5679 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5681 // RX_CTB_en, RF R21 register Bit 7 to 0
5682 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5684 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5686 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5687 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5689 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5691 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5692 MACValue |= 0x1D000000;
5693 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5697 ==========================================================================
5700 Reverse RF sleep-mode setup
5702 ==========================================================================
5704 VOID RT30xxReverseRFSleepModeSetup(
5705 IN PRTMP_ADAPTER pAd)
5710 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5711 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5713 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5715 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5716 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5718 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5720 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5721 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5723 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5725 // RX_CTB_en, RF R21 register Bit 7 to 1
5726 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5728 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5730 // LDORF_VC, RF R27 register Bit 2 to 0
5731 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5732 if ((pAd->MACVersion & 0xffff) < 0x0211)
5733 RFValue = (RFValue & (~0x77)) | 0x3;
5735 RFValue = (RFValue & (~0x77));
5736 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5738 // RT3071 version E has fixed this issue
5739 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5741 // patch tx EVM issue temporarily
5742 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5743 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5744 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5748 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5749 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5750 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5757 ==========================================================================
5760 IRQL = PASSIVE_LEVEL
5761 IRQL = DISPATCH_LEVEL
5763 ==========================================================================
5765 VOID AsicSwitchChannel(
5766 IN PRTMP_ADAPTER pAd,
5770 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5771 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5773 UINT32 Value = 0; //BbpReg, Value;
5774 RTMP_RF_REGS *RFRegTable;
5776 // Search Tx power value
5778 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5779 // in ChannelList, so use TxPower array instead.
5781 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5783 if (Channel == pAd->TxPower[index].Channel)
5785 TxPwer = pAd->TxPower[index].Power;
5786 TxPwer2 = pAd->TxPower[index].Power2;
5792 for (index = 0; index < pAd->ChannelListNum; index++)
5794 if (Channel == pAd->ChannelList[index].Channel)
5796 TxPwer = pAd->ChannelList[index].Power;
5797 TxPwer2 = pAd->ChannelList[index].Power2;
5803 if (index == MAX_NUM_OF_CHANNELS)
5804 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5807 // The RF programming sequence is difference between 3xxx and 2xxx
5809 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5810 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5813 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5816 /* modify by WY for Read RF Reg. error */
5819 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5821 if (Channel == FreqItems3020[index].Channel)
5823 // Programming channel parameters
5824 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5825 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5828 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5829 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5830 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5833 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5834 RFValue = (RFValue & 0xE0) | TxPwer;
5835 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5838 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5839 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5840 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5843 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5844 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5845 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5848 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5849 RFValue = (RFValue & 0xE0) | TxPwer;
5850 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5853 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5854 RFValue = (RFValue & 0xE0) | TxPwer2;
5855 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5857 // Tx/Rx Stream setting
5858 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5859 //if (IS_RT3090(pAd))
5860 // RFValue |= 0x01; // Enable RF block.
5861 RFValue &= 0x03; //clear bit[7~2]
5862 if (pAd->Antenna.field.TxPath == 1)
5864 else if (pAd->Antenna.field.TxPath == 2)
5866 if (pAd->Antenna.field.RxPath == 1)
5868 else if (pAd->Antenna.field.RxPath == 2)
5870 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5873 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5874 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5875 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5879 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5881 RFValue = pAd->Mlme.CaliBW40RfR24;
5882 //DISABLE_11N_CHECK(pAd);
5886 RFValue = pAd->Mlme.CaliBW20RfR24;
5889 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5892 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5893 RFValue = RFValue | 0x1;
5894 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5896 // latch channel for future usage.
5897 pAd->LatchRfRegs.Channel = Channel;
5900 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5901 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5904 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5905 RFValue = RFValue | 0x1;
5906 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5908 // latch channel for future usage.
5909 pAd->LatchRfRegs.Channel = Channel;
5911 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5916 pAd->Antenna.field.TxPath,
5917 FreqItems3020[index].N,
5918 FreqItems3020[index].K,
5919 FreqItems3020[index].R));
5926 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5931 pAd->Antenna.field.TxPath,
5932 FreqItems3020[index].N,
5933 FreqItems3020[index].K,
5934 FreqItems3020[index].R));
5939 RFRegTable = RF2850RegTable;
5941 switch (pAd->RfIcType)
5948 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5950 if (Channel == RFRegTable[index].Channel)
5952 R2 = RFRegTable[index].R2;
5953 if (pAd->Antenna.field.TxPath == 1)
5955 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5958 if (pAd->Antenna.field.RxPath == 2)
5960 R2 |= 0x40; // write 1 to off Rxpath.
5962 else if (pAd->Antenna.field.RxPath == 1)
5964 R2 |= 0x20040; // write 1 to off RxPath
5969 // initialize R3, R4
5970 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5971 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5973 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5975 if ((TxPwer >= -7) && (TxPwer < 0))
5977 TxPwer = (7+TxPwer);
5978 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5979 R3 |= (TxPwer << 10);
5980 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5984 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5985 R3 |= (TxPwer << 10) | (1 << 9);
5989 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5991 TxPwer2 = (7+TxPwer2);
5992 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5993 R4 |= (TxPwer2 << 7);
5994 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5998 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5999 R4 |= (TxPwer2 << 7) | (1 << 6);
6004 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6005 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6008 // Based on BBP current mode before changing RF channel.
6009 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6015 pAd->LatchRfRegs.Channel = Channel;
6016 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6017 pAd->LatchRfRegs.R2 = R2;
6018 pAd->LatchRfRegs.R3 = R3;
6019 pAd->LatchRfRegs.R4 = R4;
6021 // Set RF value 1's set R3[bit2] = [0]
6022 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6023 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6024 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6025 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6029 // Set RF value 2's set R3[bit2] = [1]
6030 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6031 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6032 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6033 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6037 // Set RF value 3's set R3[bit2] = [0]
6038 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6039 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6040 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6041 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6053 // Change BBP setting during siwtch from a->g, g->a
6056 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6058 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6059 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6060 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6061 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.
6062 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6064 // Rx High power VGA offset for LNA select
6065 if (pAd->NicConfig2.field.ExternalLNAForG)
6067 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6068 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6072 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6073 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6076 // 5G band selection PIN, bit1 and bit2 are complement
6077 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6080 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6082 // Turn off unused PA or LNA when only 1T or 1R
6083 if (pAd->Antenna.field.TxPath == 1)
6085 TxPinCfg &= 0xFFFFFFF3;
6087 if (pAd->Antenna.field.RxPath == 1)
6089 TxPinCfg &= 0xFFFFF3FF;
6092 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6096 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6098 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6099 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6100 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6101 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.
6102 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6104 // Rx High power VGA offset for LNA select
6105 if (pAd->NicConfig2.field.ExternalLNAForA)
6107 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6111 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6114 // 5G band selection PIN, bit1 and bit2 are complement
6115 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6118 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6120 // Turn off unused PA or LNA when only 1T or 1R
6121 if (pAd->Antenna.field.TxPath == 1)
6123 TxPinCfg &= 0xFFFFFFF3;
6125 if (pAd->Antenna.field.RxPath == 1)
6127 TxPinCfg &= 0xFFFFF3FF;
6130 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6133 // R66 should be set according to Channel and use 20MHz when scanning
6134 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6136 RTMPSetAGCInitValue(pAd, BW_20);
6138 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6141 // On 11A, We should delay and wait RF/BBP to be stable
6142 // and the appropriate time should be 1000 micro seconds
6143 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6145 RTMPusecDelay(1000);
6147 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",
6150 (R3 & 0x00003e00) >> 9,
6151 (R4 & 0x000007c0) >> 6,
6152 pAd->Antenna.field.TxPath,
6153 pAd->LatchRfRegs.R1,
6154 pAd->LatchRfRegs.R2,
6155 pAd->LatchRfRegs.R3,
6156 pAd->LatchRfRegs.R4));
6160 ==========================================================================
6162 This function is required for 2421 only, and should not be used during
6163 site survey. It's only required after NIC decided to stay at a channel
6164 for a longer period.
6165 When this function is called, it's always after AsicSwitchChannel().
6167 IRQL = PASSIVE_LEVEL
6168 IRQL = DISPATCH_LEVEL
6170 ==========================================================================
6172 VOID AsicLockChannel(
6173 IN PRTMP_ADAPTER pAd,
6179 ==========================================================================
6182 IRQL = PASSIVE_LEVEL
6183 IRQL = DISPATCH_LEVEL
6185 ==========================================================================
6187 VOID AsicAntennaSelect(
6188 IN PRTMP_ADAPTER pAd,
6192 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6194 // patch for AsicSetRxAnt failed
6195 pAd->RxAnt.EvaluatePeriod = 0;
6197 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6198 // valid indication of the distance between this AP and its clients.
6199 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6203 // if no traffic then reset average rssi to trigger evaluation
6204 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6206 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6207 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6208 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6211 pAd->StaCfg.NumOfAvgRssiSample = 0;
6212 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6214 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6216 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6217 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6219 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6220 AsicEvaluateRxAnt(pAd);
6225 // if not connected, always switch antenna to try to connect
6228 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6229 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6230 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6232 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6234 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6241 ========================================================================
6243 Routine Description:
6244 Antenna miscellaneous setting.
6247 pAd Pointer to our adapter
6248 BandState Indicate current Band State.
6253 IRQL <= DISPATCH_LEVEL
6256 1.) Frame End type control
6257 only valid for G only (RF_2527 & RF_2529)
6258 0: means DPDT, set BBP R4 bit 5 to 1
6259 1: means SPDT, set BBP R4 bit 5 to 0
6262 ========================================================================
6264 VOID AsicAntennaSetting(
6265 IN PRTMP_ADAPTER pAd,
6266 IN ABGBAND_STATE BandState)
6270 VOID AsicRfTuningExec(
6271 IN PVOID SystemSpecific1,
6272 IN PVOID FunctionContext,
6273 IN PVOID SystemSpecific2,
6274 IN PVOID SystemSpecific3)
6279 ==========================================================================
6281 Gives CCK TX rate 2 more dB TX power.
6282 This routine works only in LINK UP in INFRASTRUCTURE mode.
6284 calculate desired Tx power in RF R3.Tx0~5, should consider -
6285 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6286 1. TxPowerPercentage
6287 2. auto calibration based on TSSI feedback
6288 3. extra 2 db for CCK
6289 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6291 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6292 it should be called AFTER MlmeDynamicTxRatSwitching()
6293 ==========================================================================
6295 VOID AsicAdjustTxPower(
6296 IN PRTMP_ADAPTER pAd)
6300 BOOLEAN bAutoTxAgc = FALSE;
6301 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6302 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6303 PCHAR pTxAgcCompensate;
6308 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6309 || (pAd->bPCIclkOff == TRUE)
6310 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6311 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6315 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6317 if (pAd->CommonCfg.CentralChannel > 14)
6319 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6320 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6321 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6322 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6323 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6327 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6328 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6329 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6330 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6331 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6336 if (pAd->CommonCfg.Channel > 14)
6338 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6339 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6340 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6341 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6342 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6346 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6347 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6348 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6349 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6350 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6354 // TX power compensation for temperature variation based on TSSI. try every 4 second
6355 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6357 if (pAd->CommonCfg.Channel <= 14)
6360 bAutoTxAgc = pAd->bAutoTxAgcG;
6361 TssiRef = pAd->TssiRefG;
6362 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6363 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6364 TxAgcStep = pAd->TxAgcStepG;
6365 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6370 bAutoTxAgc = pAd->bAutoTxAgcA;
6371 TssiRef = pAd->TssiRefA;
6372 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6373 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6374 TxAgcStep = pAd->TxAgcStepA;
6375 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6380 /* BbpR1 is unsigned char */
6381 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6383 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6384 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6385 /* step value is defined in pAd->TxAgcStepG for tx power value */
6387 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6388 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6389 above value are examined in mass factory production */
6390 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6392 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6393 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6394 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6396 if (BbpR49 > pTssiMinusBoundary[1])
6398 // Reading is larger than the reference value
6399 // check for how large we need to decrease the Tx power
6400 for (idx = 1; idx < 5; idx++)
6402 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6405 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6406 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6408 DeltaPwr += (*pTxAgcCompensate);
6409 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6410 BbpR49, TssiRef, TxAgcStep, idx-1));
6412 else if (BbpR49 < pTssiPlusBoundary[1])
6414 // Reading is smaller than the reference value
6415 // check for how large we need to increase the Tx power
6416 for (idx = 1; idx < 5; idx++)
6418 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6421 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6422 *pTxAgcCompensate = TxAgcStep * (idx-1);
6423 DeltaPwr += (*pTxAgcCompensate);
6424 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6425 BbpR49, TssiRef, TxAgcStep, idx-1));
6429 *pTxAgcCompensate = 0;
6430 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6431 BbpR49, TssiRef, TxAgcStep, 0));
6437 if (pAd->CommonCfg.Channel <= 14)
6439 bAutoTxAgc = pAd->bAutoTxAgcG;
6440 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6444 bAutoTxAgc = pAd->bAutoTxAgcA;
6445 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6449 DeltaPwr += (*pTxAgcCompensate);
6452 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6455 /* calculate delta power based on the percentage specified from UI */
6456 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6457 // We lower TX power here according to the percentage specified from UI
6458 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6460 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6462 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6466 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6470 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6474 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6479 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6484 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6486 /* reset different new tx power for different TX rate */
6489 if (TxPwr[i] != 0xffffffff)
6493 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6495 if ((Value + DeltaPwr) < 0)
6497 Value = 0; /* min */
6499 else if ((Value + DeltaPwr) > 0xF)
6501 Value = 0xF; /* max */
6505 Value += DeltaPwr; /* temperature compensation */
6508 /* fill new value to CSR offset */
6509 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6512 /* write tx power value to CSR */
6513 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6514 TX power for OFDM 6M/9M
6515 TX power for CCK5.5M/11M
6516 TX power for CCK1M/2M */
6517 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6518 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6525 ==========================================================================
6527 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6528 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6529 the wakeup timer timeout. Driver has to issue a separate command to wake
6532 IRQL = DISPATCH_LEVEL
6534 ==========================================================================
6536 VOID AsicSleepThenAutoWakeup(
6537 IN PRTMP_ADAPTER pAd,
6538 IN USHORT TbttNumToNextWakeUp)
6540 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6544 ==========================================================================
6546 AsicForceWakeup() is used whenever manual wakeup is required
6547 AsicForceSleep() should only be used when not in INFRA BSS. When
6548 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6549 ==========================================================================
6551 VOID AsicForceSleep(
6552 IN PRTMP_ADAPTER pAd)
6558 ==========================================================================
6560 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6563 IRQL = PASSIVE_LEVEL
6564 IRQL = DISPATCH_LEVEL
6565 ==========================================================================
6567 VOID AsicForceWakeup(
6568 IN PRTMP_ADAPTER pAd,
6576 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6578 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6581 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6586 ==========================================================================
6590 IRQL = DISPATCH_LEVEL
6592 ==========================================================================
6595 IN PRTMP_ADAPTER pAd,
6599 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6600 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6602 Addr4 = (ULONG)(pBssid[0]) |
6603 (ULONG)(pBssid[1] << 8) |
6604 (ULONG)(pBssid[2] << 16) |
6605 (ULONG)(pBssid[3] << 24);
6606 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6609 // always one BSSID in STA mode
6610 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6612 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6615 VOID AsicSetMcastWC(
6616 IN PRTMP_ADAPTER pAd)
6618 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6621 pEntry->Sst = SST_ASSOC;
6622 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6623 pEntry->PsMode = PWR_ACTIVE;
6624 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6625 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6629 ==========================================================================
6632 IRQL = DISPATCH_LEVEL
6634 ==========================================================================
6636 VOID AsicDelWcidTab(
6637 IN PRTMP_ADAPTER pAd,
6640 ULONG Addr0 = 0x0, Addr1 = 0x0;
6643 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6644 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6645 RTMP_IO_WRITE32(pAd, offset, Addr0);
6647 RTMP_IO_WRITE32(pAd, offset, Addr1);
6651 ==========================================================================
6654 IRQL = DISPATCH_LEVEL
6656 ==========================================================================
6659 IN PRTMP_ADAPTER pAd)
6661 TX_LINK_CFG_STRUC TxLinkCfg;
6664 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6665 TxLinkCfg.field.TxRDGEn = 1;
6666 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6668 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6671 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6673 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6677 ==========================================================================
6680 IRQL = DISPATCH_LEVEL
6682 ==========================================================================
6684 VOID AsicDisableRDG(
6685 IN PRTMP_ADAPTER pAd)
6687 TX_LINK_CFG_STRUC TxLinkCfg;
6691 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6692 TxLinkCfg.field.TxRDGEn = 0;
6693 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6695 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6698 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6699 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6702 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6703 if (pAd->CommonCfg.bEnableTxBurst)
6706 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6710 ==========================================================================
6713 IRQL = PASSIVE_LEVEL
6714 IRQL = DISPATCH_LEVEL
6716 ==========================================================================
6718 VOID AsicDisableSync(
6719 IN PRTMP_ADAPTER pAd)
6721 BCN_TIME_CFG_STRUC csr;
6723 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6725 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6726 // that NIC will never wakes up because TSF stops and no more
6728 pAd->TbttTickCount = 0;
6729 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6730 csr.field.bBeaconGen = 0;
6731 csr.field.bTBTTEnable = 0;
6732 csr.field.TsfSyncMode = 0;
6733 csr.field.bTsfTicking = 0;
6734 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6739 ==========================================================================
6742 IRQL = DISPATCH_LEVEL
6744 ==========================================================================
6746 VOID AsicEnableBssSync(
6747 IN PRTMP_ADAPTER pAd)
6749 BCN_TIME_CFG_STRUC csr;
6751 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6753 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6756 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6757 csr.field.bTsfTicking = 1;
6758 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6759 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6760 csr.field.bTBTTEnable = 1;
6763 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6767 ==========================================================================
6770 BEACON frame in shared memory should be built ok before this routine
6771 can be called. Otherwise, a garbage frame maybe transmitted out every
6774 IRQL = DISPATCH_LEVEL
6776 ==========================================================================
6778 VOID AsicEnableIbssSync(
6779 IN PRTMP_ADAPTER pAd)
6781 BCN_TIME_CFG_STRUC csr9;
6785 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6787 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6788 csr9.field.bBeaconGen = 0;
6789 csr9.field.bTBTTEnable = 0;
6790 csr9.field.bTsfTicking = 0;
6791 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6794 // move BEACON TXD and frame content to on-chip memory
6795 ptr = (PUCHAR)&pAd->BeaconTxWI;
6796 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6798 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6799 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6803 // start right after the 16-byte TXWI field
6804 ptr = pAd->BeaconBuf;
6805 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6807 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6808 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6813 // move BEACON TXD and frame content to on-chip memory
6814 ptr = (PUCHAR)&pAd->BeaconTxWI;
6815 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6817 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6821 // start right after the 16-byte TXWI field
6822 ptr = pAd->BeaconBuf;
6823 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6825 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6830 // start sending BEACON
6831 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6832 csr9.field.bTsfTicking = 1;
6833 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6834 csr9.field.bTBTTEnable = 1;
6835 csr9.field.bBeaconGen = 1;
6836 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6840 ==========================================================================
6843 IRQL = PASSIVE_LEVEL
6844 IRQL = DISPATCH_LEVEL
6846 ==========================================================================
6848 VOID AsicSetEdcaParm(
6849 IN PRTMP_ADAPTER pAd,
6850 IN PEDCA_PARM pEdcaParm)
6852 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6853 AC_TXOP_CSR0_STRUC csr0;
6854 AC_TXOP_CSR1_STRUC csr1;
6855 AIFSN_CSR_STRUC AifsnCsr;
6856 CWMIN_CSR_STRUC CwminCsr;
6857 CWMAX_CSR_STRUC CwmaxCsr;
6864 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6866 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6867 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6868 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6870 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6871 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6874 //========================================================
6875 // MAC Register has a copy .
6876 //========================================================
6877 if( pAd->CommonCfg.bEnableTxBurst )
6879 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6880 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6883 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6884 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6885 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6886 Ac0Cfg.field.Aifsn = 2;
6887 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6889 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6890 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6891 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6892 Ac1Cfg.field.Aifsn = 2;
6893 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6895 if (pAd->CommonCfg.PhyMode == PHY_11B)
6897 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6898 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6902 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6903 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6905 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6906 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6907 Ac2Cfg.field.Aifsn = 2;
6908 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6909 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6910 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6911 Ac3Cfg.field.Aifsn = 2;
6912 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6914 //========================================================
6915 // DMA Register has a copy too.
6916 //========================================================
6917 csr0.field.Ac0Txop = 0; // QID_AC_BE
6918 csr0.field.Ac1Txop = 0; // QID_AC_BK
6919 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6920 if (pAd->CommonCfg.PhyMode == PHY_11B)
6922 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6923 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6927 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6928 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6930 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6933 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6934 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6935 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6936 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6937 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6940 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6941 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6942 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6943 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6944 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6946 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6948 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6952 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6953 //========================================================
6954 // MAC Register has a copy.
6955 //========================================================
6957 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6958 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6960 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6962 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6963 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6964 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6965 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6967 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6968 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6969 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6970 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6972 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6973 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6974 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6975 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6978 // Tuning for Wi-Fi WMM S06
6979 if (pAd->CommonCfg.bWiFiTest &&
6980 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6981 Ac2Cfg.field.Aifsn -= 1;
6983 // Tuning for TGn Wi-Fi 5.2.32
6984 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6985 if (STA_TGN_WIFI_ON(pAd) &&
6986 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6988 Ac0Cfg.field.Aifsn = 3;
6989 Ac2Cfg.field.AcTxop = 5;
6993 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6995 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6996 Ac2Cfg.field.Aifsn = 5;
7001 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7002 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7003 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7004 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7007 if (pAd->CommonCfg.bWiFiTest)
7009 if (Ac3Cfg.field.AcTxop == 102)
7011 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7012 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7013 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7014 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7015 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7018 //#endif // WIFI_TEST //
7020 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7021 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7022 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7023 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7026 //========================================================
7027 // DMA Register has a copy too.
7028 //========================================================
7029 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7030 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7031 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7033 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7034 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7035 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7038 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7039 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7040 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7042 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7044 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7047 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7048 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7049 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7050 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7051 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7054 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7055 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7056 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7059 // Tuning for Wi-Fi WMM S06
7060 if (pAd->CommonCfg.bWiFiTest &&
7061 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7062 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7064 // Tuning for TGn Wi-Fi 5.2.32
7065 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7066 if (STA_TGN_WIFI_ON(pAd) &&
7067 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7069 AifsnCsr.field.Aifsn0 = 3;
7070 AifsnCsr.field.Aifsn2 = 7;
7074 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7078 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7080 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7081 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7084 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7086 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7089 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7090 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7091 pEdcaParm->Aifsn[0],
7092 pEdcaParm->Cwmin[0],
7093 pEdcaParm->Cwmax[0],
7094 pEdcaParm->Txop[0]<<5,
7095 pEdcaParm->bACM[0]));
7096 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7097 pEdcaParm->Aifsn[1],
7098 pEdcaParm->Cwmin[1],
7099 pEdcaParm->Cwmax[1],
7100 pEdcaParm->Txop[1]<<5,
7101 pEdcaParm->bACM[1]));
7102 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7103 pEdcaParm->Aifsn[2],
7104 pEdcaParm->Cwmin[2],
7105 pEdcaParm->Cwmax[2],
7106 pEdcaParm->Txop[2]<<5,
7107 pEdcaParm->bACM[2]));
7108 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7109 pEdcaParm->Aifsn[3],
7110 pEdcaParm->Cwmin[3],
7111 pEdcaParm->Cwmax[3],
7112 pEdcaParm->Txop[3]<<5,
7113 pEdcaParm->bACM[3]));
7119 ==========================================================================
7122 IRQL = PASSIVE_LEVEL
7123 IRQL = DISPATCH_LEVEL
7125 ==========================================================================
7127 VOID AsicSetSlotTime(
7128 IN PRTMP_ADAPTER pAd,
7129 IN BOOLEAN bUseShortSlotTime)
7132 UINT32 RegValue = 0;
7134 if (pAd->CommonCfg.Channel > 14)
7135 bUseShortSlotTime = TRUE;
7137 if (bUseShortSlotTime)
7138 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7140 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7142 SlotTime = (bUseShortSlotTime)? 9 : 20;
7146 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7147 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7148 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7151 // In this case, we will think it is doing Wi-Fi test
7152 // And we will not set to short slot when bEnableTxBurst is TRUE.
7154 else if (pAd->CommonCfg.bEnableTxBurst)
7157 if (pAd->CommonCfg.bEnableTxBurst)
7163 // For some reasons, always set it to short slot time.
7165 // ToDo: Should consider capability with 11B
7167 if (pAd->StaCfg.BssType == BSS_ADHOC)
7170 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7171 RegValue = RegValue & 0xFFFFFF00;
7173 RegValue |= SlotTime;
7175 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7179 ========================================================================
7181 Add Shared key information into ASIC.
7182 Update shared key, TxMic and RxMic to Asic Shared key table
7183 Update its cipherAlg to Asic Shared key Mode.
7186 ========================================================================
7188 VOID AsicAddSharedKeyEntry(
7189 IN PRTMP_ADAPTER pAd,
7197 ULONG offset; //, csr0;
7198 SHAREDKEY_MODE_STRUC csr1;
7203 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7204 //============================================================================================
7206 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7207 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7208 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]));
7211 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7212 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7216 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7217 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7219 //============================================================================================
7221 // fill key material - key + TX MIC + RX MIC
7224 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7226 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7228 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7232 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7234 offset += MAX_LEN_OF_SHARE_KEY;
7240 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7244 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7254 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7258 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7264 // Update cipher algorithm. WSTA always use BSS0
7266 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7267 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7268 if ((BssIndex%2) == 0)
7271 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7272 else if (KeyIdx == 1)
7273 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7274 else if (KeyIdx == 2)
7275 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7277 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7282 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7283 else if (KeyIdx == 1)
7284 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7285 else if (KeyIdx == 2)
7286 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7288 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7290 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7291 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7295 // IRQL = DISPATCH_LEVEL
7296 VOID AsicRemoveSharedKeyEntry(
7297 IN PRTMP_ADAPTER pAd,
7302 SHAREDKEY_MODE_STRUC csr1;
7304 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7306 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7307 if ((BssIndex%2) == 0)
7310 csr1.field.Bss0Key0CipherAlg = 0;
7311 else if (KeyIdx == 1)
7312 csr1.field.Bss0Key1CipherAlg = 0;
7313 else if (KeyIdx == 2)
7314 csr1.field.Bss0Key2CipherAlg = 0;
7316 csr1.field.Bss0Key3CipherAlg = 0;
7321 csr1.field.Bss1Key0CipherAlg = 0;
7322 else if (KeyIdx == 1)
7323 csr1.field.Bss1Key1CipherAlg = 0;
7324 else if (KeyIdx == 2)
7325 csr1.field.Bss1Key2CipherAlg = 0;
7327 csr1.field.Bss1Key3CipherAlg = 0;
7329 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7330 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7331 ASSERT(BssIndex < 4);
7337 VOID AsicUpdateWCIDAttribute(
7338 IN PRTMP_ADAPTER pAd,
7342 IN BOOLEAN bUsePairewiseKeyTable)
7344 ULONG WCIDAttri = 0, offset;
7347 // Update WCID attribute.
7348 // Only TxKey could update WCID attribute.
7350 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7351 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7352 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7355 VOID AsicUpdateWCIDIVEIV(
7356 IN PRTMP_ADAPTER pAd,
7363 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7365 RTMP_IO_WRITE32(pAd, offset, uIV);
7366 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7369 VOID AsicUpdateRxWCIDTable(
7370 IN PRTMP_ADAPTER pAd,
7377 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7378 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7379 RTMP_IO_WRITE32(pAd, offset, Addr);
7380 Addr = pAddr[4] + (pAddr[5] << 8);
7381 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7386 ========================================================================
7388 Routine Description:
7389 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7392 pAd Pointer to our adapter
7393 WCID WCID Entry number.
7394 BssIndex BSSID index, station or none multiple BSSID support
7395 this value should be 0.
7396 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7397 pCipherKey Pointer to Cipher Key.
7398 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7399 otherwise PairewiseKey table
7400 bTxKey This is the transmit key if enabled.
7406 This routine will set the relative key stuff to Asic including WCID attribute,
7407 Cipher Key, Cipher algorithm and IV/EIV.
7409 IV/EIV will be update if this CipherKey is the transmission key because
7410 ASIC will base on IV's KeyID value to select Cipher Key.
7412 If bTxKey sets to FALSE, this is not the TX key, but it could be
7415 For AP mode bTxKey must be always set to TRUE.
7416 ========================================================================
7418 VOID AsicAddKeyEntry(
7419 IN PRTMP_ADAPTER pAd,
7423 IN PCIPHER_KEY pCipherKey,
7424 IN BOOLEAN bUsePairewiseKeyTable,
7429 PUCHAR pKey = pCipherKey->Key;
7430 PUCHAR pTxMic = pCipherKey->TxMic;
7431 PUCHAR pRxMic = pCipherKey->RxMic;
7432 PUCHAR pTxtsc = pCipherKey->TxTsc;
7433 UCHAR CipherAlg = pCipherKey->CipherAlg;
7434 SHAREDKEY_MODE_STRUC csr1;
7439 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7441 // 1.) decide key table offset
7443 if (bUsePairewiseKeyTable)
7444 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7446 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7449 // 2.) Set Key to Asic
7451 //for (i = 0; i < KeyLen; i++)
7453 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7455 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7459 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7461 offset += MAX_LEN_OF_PEER_KEY;
7464 // 3.) Set MIC key if available
7469 for (i = 0; i < 8; i++)
7471 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7475 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7478 offset += LEN_TKIP_TXMICK;
7483 for (i = 0; i < 8; i++)
7485 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7489 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7495 // 4.) Modify IV/EIV if needs
7496 // This will force Asic to use this key ID by setting IV.
7501 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7505 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7506 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7507 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7509 IV4 = (KeyIdx << 6);
7510 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7511 IV4 |= 0x20; // turn on extension bit means EIV existence
7513 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7519 for (i = 0; i < 4; i++)
7521 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7531 IV4 = (KeyIdx << 6);
7532 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7533 IV4 |= 0x20; // turn on extension bit means EIV existence
7535 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7536 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7542 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7544 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7547 if (!bUsePairewiseKeyTable)
7550 // Only update the shared key security mode
7552 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7553 if ((BssIndex % 2) == 0)
7556 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7557 else if (KeyIdx == 1)
7558 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7559 else if (KeyIdx == 2)
7560 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7562 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7567 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7568 else if (KeyIdx == 1)
7569 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7570 else if (KeyIdx == 2)
7571 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7573 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7575 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7578 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7583 ========================================================================
7585 Add Pair-wise key material into ASIC.
7586 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7589 ========================================================================
7591 VOID AsicAddPairwiseKeyEntry(
7592 IN PRTMP_ADAPTER pAd,
7595 IN CIPHER_KEY *pCipherKey)
7599 PUCHAR pKey = pCipherKey->Key;
7600 PUCHAR pTxMic = pCipherKey->TxMic;
7601 PUCHAR pRxMic = pCipherKey->RxMic;
7603 UCHAR CipherAlg = pCipherKey->CipherAlg;
7607 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7609 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7611 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7615 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7617 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7620 RTMP_IO_READ32(pAd, offset + i, &Value);
7623 offset += MAX_LEN_OF_PEER_KEY;
7631 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7635 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7644 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7648 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7652 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7653 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7654 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]));
7657 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7658 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7662 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7663 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7667 ========================================================================
7669 Remove Pair-wise key material from ASIC.
7672 ========================================================================
7674 VOID AsicRemovePairwiseKeyEntry(
7675 IN PRTMP_ADAPTER pAd,
7682 // re-set the entry's WCID attribute as OPEN-NONE.
7683 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7684 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7685 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7688 BOOLEAN AsicSendCommandToMcu(
7689 IN PRTMP_ADAPTER pAd,
7695 HOST_CMD_CSR_STRUC H2MCmd;
7696 H2M_MAILBOX_STRUC H2MMailbox;
7701 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7702 if (H2MMailbox.field.Owner == 0)
7715 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7717 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7719 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7720 // Reset DMA/CPU ring index
7721 RTMPRingCleanUp(pAd, QID_AC_BK);
7722 RTMPRingCleanUp(pAd, QID_AC_BE);
7723 RTMPRingCleanUp(pAd, QID_AC_VI);
7724 RTMPRingCleanUp(pAd, QID_AC_VO);
7725 RTMPRingCleanUp(pAd, QID_HCCA);
7726 RTMPRingCleanUp(pAd, QID_MGMT);
7727 RTMPRingCleanUp(pAd, QID_RX);
7730 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7732 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7734 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7742 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7743 H2MMailbox.field.CmdToken = Token;
7744 H2MMailbox.field.HighByte = Arg1;
7745 H2MMailbox.field.LowByte = Arg0;
7746 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7749 H2MCmd.field.HostCommand = Command;
7750 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7752 if (Command != 0x80)
7760 BOOLEAN AsicCheckCommanOk(
7761 IN PRTMP_ADAPTER pAd,
7764 UINT32 CmdStatus = 0, CID = 0, i;
7765 UINT32 ThisCIDMask = 0;
7770 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7771 // Find where the command is. Because this is randomly specified by firmware.
7772 if ((CID & CID0MASK) == Command)
7774 ThisCIDMask = CID0MASK;
7777 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7779 ThisCIDMask = CID1MASK;
7782 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7784 ThisCIDMask = CID2MASK;
7787 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7789 ThisCIDMask = CID3MASK;
7797 // Get CommandStatus Value
7798 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7800 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7803 // If Status is 1, the comamnd is success.
7804 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7805 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7807 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7808 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7809 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7812 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7816 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7818 // Clear Command and Status.
7819 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7820 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7827 ========================================================================
7829 Routine Description:
7830 Verify the support rate for different PHY type
7833 pAd Pointer to our adapter
7838 IRQL = PASSIVE_LEVEL
7840 ========================================================================
7842 VOID RTMPCheckRates(
7843 IN PRTMP_ADAPTER pAd,
7844 IN OUT UCHAR SupRate[],
7845 IN OUT UCHAR *SupRateLen)
7847 UCHAR RateIdx, i, j;
7848 UCHAR NewRate[12], NewRateLen;
7852 if (pAd->CommonCfg.PhyMode == PHY_11B)
7857 // Check for support rates exclude basic rate bit
7858 for (i = 0; i < *SupRateLen; i++)
7859 for (j = 0; j < RateIdx; j++)
7860 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7861 NewRate[NewRateLen++] = SupRate[i];
7863 *SupRateLen = NewRateLen;
7864 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7867 BOOLEAN RTMPCheckChannel(
7868 IN PRTMP_ADAPTER pAd,
7869 IN UCHAR CentralChannel,
7873 UCHAR UpperChannel = 0, LowerChannel = 0;
7874 UCHAR NoEffectChannelinList = 0;
7876 // Find upper and lower channel according to 40MHz current operation.
7877 if (CentralChannel < Channel)
7879 UpperChannel = Channel;
7880 if (CentralChannel > 2)
7881 LowerChannel = CentralChannel - 2;
7885 else if (CentralChannel > Channel)
7887 UpperChannel = CentralChannel + 2;
7888 LowerChannel = Channel;
7891 for (k = 0;k < pAd->ChannelListNum;k++)
7893 if (pAd->ChannelList[k].Channel == UpperChannel)
7895 NoEffectChannelinList ++;
7897 if (pAd->ChannelList[k].Channel == LowerChannel)
7899 NoEffectChannelinList ++;
7903 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7904 if (NoEffectChannelinList == 2)
7911 ========================================================================
7913 Routine Description:
7914 Verify the support rate for HT phy type
7917 pAd Pointer to our adapter
7920 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7922 IRQL = PASSIVE_LEVEL
7924 ========================================================================
7926 BOOLEAN RTMPCheckHt(
7927 IN PRTMP_ADAPTER pAd,
7929 IN HT_CAPABILITY_IE *pHtCapability,
7930 IN ADD_HT_INFO_IE *pAddHtInfo)
7932 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7935 // If use AMSDU, set flag.
7936 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7937 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7938 // Save Peer Capability
7939 if (pHtCapability->HtCapInfo.ShortGIfor20)
7940 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7941 if (pHtCapability->HtCapInfo.ShortGIfor40)
7942 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7943 if (pHtCapability->HtCapInfo.TxSTBC)
7944 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7945 if (pHtCapability->HtCapInfo.RxSTBC)
7946 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7947 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7949 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7952 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7954 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7957 // Will check ChannelWidth for MCSSet[4] below
7958 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7959 switch (pAd->CommonCfg.RxStream)
7962 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7963 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7964 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7965 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7968 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7969 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7970 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7971 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7974 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7975 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7976 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7977 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7981 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7983 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7984 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7985 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7987 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7989 // Send Assoc Req with my HT capability.
7990 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7991 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7992 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7993 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7994 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7995 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7996 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7997 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7998 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7999 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8000 if (pAd->CommonCfg.bRdg)
8002 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8003 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8006 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8007 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8009 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8014 ========================================================================
8016 Routine Description:
8017 Verify the support rate for different PHY type
8020 pAd Pointer to our adapter
8025 IRQL = PASSIVE_LEVEL
8027 ========================================================================
8029 VOID RTMPUpdateMlmeRate(
8030 IN PRTMP_ADAPTER pAd)
8033 UCHAR ProperMlmeRate; //= RATE_54;
8034 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8035 BOOLEAN bMatch = FALSE;
8037 switch (pAd->CommonCfg.PhyMode)
8040 ProperMlmeRate = RATE_11;
8041 MinimumRate = RATE_1;
8043 case PHY_11BG_MIXED:
8044 case PHY_11ABGN_MIXED:
8045 case PHY_11BGN_MIXED:
8046 if ((pAd->MlmeAux.SupRateLen == 4) &&
8047 (pAd->MlmeAux.ExtRateLen == 0))
8049 ProperMlmeRate = RATE_11;
8051 ProperMlmeRate = RATE_24;
8053 if (pAd->MlmeAux.Channel <= 14)
8054 MinimumRate = RATE_1;
8056 MinimumRate = RATE_6;
8059 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8060 case PHY_11GN_MIXED:
8061 case PHY_11AGN_MIXED:
8062 case PHY_11AN_MIXED:
8064 ProperMlmeRate = RATE_24;
8065 MinimumRate = RATE_6;
8067 case PHY_11ABG_MIXED:
8068 ProperMlmeRate = RATE_24;
8069 if (pAd->MlmeAux.Channel <= 14)
8070 MinimumRate = RATE_1;
8072 MinimumRate = RATE_6;
8075 ProperMlmeRate = RATE_1;
8076 MinimumRate = RATE_1;
8080 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8082 for (j = 0; j < RateIdx; j++)
8084 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8086 if (j == ProperMlmeRate)
8098 if (bMatch == FALSE)
8100 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8102 for (j = 0; j < RateIdx; j++)
8104 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8106 if (j == ProperMlmeRate)
8119 if (bMatch == FALSE)
8121 ProperMlmeRate = MinimumRate;
8124 pAd->CommonCfg.MlmeRate = MinimumRate;
8125 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8126 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8128 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8129 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8130 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8131 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8135 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8136 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8137 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8138 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8141 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8145 IN PRTMP_ADAPTER pAd,
8152 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8157 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8159 larger = max(Rssi0, Rssi1);
8162 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8164 larger = max(larger, Rssi2);
8174 // Antenna divesity use GPIO3 and EESK pin for control
8175 // Antenna and EEPROM access are both using EESK pin,
8176 // Therefor we should avoid accessing EESK at the same time
8177 // Then restore antenna after EEPROM access
8179 IN PRTMP_ADAPTER pAd,
8185 if ((pAd->EepromAccess) ||
8186 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8187 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8188 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8189 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8194 // the antenna selection is through firmware and MAC register(GPIO3)
8198 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8200 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8202 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8204 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8205 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8210 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8212 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8214 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8217 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8218 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8224 ========================================================================
8225 Routine Description:
8226 Periodic evaluate antenna link status
8229 pAd - Adapter pointer
8234 ========================================================================
8236 VOID AsicEvaluateRxAnt(
8237 IN PRTMP_ADAPTER pAd)
8241 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8242 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8243 fRTMP_ADAPTER_RADIO_OFF |
8244 fRTMP_ADAPTER_NIC_NOT_EXIST |
8245 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
8247 || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8248 || (pAd->EepromAccess)
8254 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8255 // one is antenna diversity:there is only one antenna can rx and tx
8256 // the other is failed antenna remove:two physical antenna can rx and tx
8257 if (pAd->NicConfig2.field.AntDiversity)
8259 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8260 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8262 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8264 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8265 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8266 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8268 // a one-shot timer to end the evalution
8269 // dynamic adjust antenna evaluation period according to the traffic
8270 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8271 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8273 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8278 if (pAd->StaCfg.Psm == PWR_SAVE)
8281 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8283 if(pAd->Antenna.field.RxPath == 3)
8287 else if(pAd->Antenna.field.RxPath == 2)
8291 else if(pAd->Antenna.field.RxPath == 1)
8295 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8298 pAd->StaCfg.BBPR3 = BBPR3;
8302 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8305 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8306 pAd->RalinkCounters.OneSecTxRetryOkCount +
8307 pAd->RalinkCounters.OneSecTxFailCount;
8309 // dynamic adjust antenna evaluation period according to the traffic
8310 if (TxTotalCnt > 50)
8312 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8313 pAd->Mlme.bLowThroughput = FALSE;
8317 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8318 pAd->Mlme.bLowThroughput = TRUE;
8324 ========================================================================
8325 Routine Description:
8326 After evaluation, check antenna link status
8329 pAd - Adapter pointer
8334 ========================================================================
8336 VOID AsicRxAntEvalTimeout(
8337 IN PVOID SystemSpecific1,
8338 IN PVOID FunctionContext,
8339 IN PVOID SystemSpecific2,
8340 IN PVOID SystemSpecific3)
8342 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8344 CHAR larger = -127, rssi0, rssi1, rssi2;
8348 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8349 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8350 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8351 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8354 if (pAd->StaCfg.Psm == PWR_SAVE)
8358 // if the traffic is low, use average rssi as the criteria
8359 if (pAd->Mlme.bLowThroughput == TRUE)
8361 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8362 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8363 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8367 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8368 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8369 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8372 if(pAd->Antenna.field.RxPath == 3)
8374 larger = max(rssi0, rssi1);
8376 if (larger > (rssi2 + 20))
8377 pAd->Mlme.RealRxPath = 2;
8379 pAd->Mlme.RealRxPath = 3;
8381 else if(pAd->Antenna.field.RxPath == 2)
8383 if (rssi0 > (rssi1 + 20))
8384 pAd->Mlme.RealRxPath = 1;
8386 pAd->Mlme.RealRxPath = 2;
8389 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8391 if(pAd->Mlme.RealRxPath == 3)
8395 else if(pAd->Mlme.RealRxPath == 2)
8399 else if(pAd->Mlme.RealRxPath == 1)
8403 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8405 pAd->StaCfg.BBPR3 = BBPR3;
8410 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8411 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8412 fRTMP_ADAPTER_RADIO_OFF |
8413 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8414 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8416 || (pAd->EepromAccess)
8422 //if (pAd->StaCfg.Psm == PWR_SAVE)
8425 if (pAd->NicConfig2.field.AntDiversity)
8427 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8432 // select PrimaryRxAntPair
8433 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8434 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8436 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8437 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8438 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8440 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8441 pAd->RxAnt.EvaluateStableCnt = 0;
8445 // if the evaluated antenna is not better than original, switch back to original antenna
8446 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8447 pAd->RxAnt.EvaluateStableCnt ++;
8450 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8452 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8453 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8457 if (pAd->StaCfg.Psm == PWR_SAVE)
8460 // if the traffic is low, use average rssi as the criteria
8461 if (pAd->Mlme.bLowThroughput == TRUE)
8463 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8464 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8465 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8469 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8470 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8471 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8474 if(pAd->Antenna.field.RxPath == 3)
8476 larger = max(rssi0, rssi1);
8478 if (larger > (rssi2 + 20))
8479 pAd->Mlme.RealRxPath = 2;
8481 pAd->Mlme.RealRxPath = 3;
8483 else if(pAd->Antenna.field.RxPath == 2)
8485 if (rssi0 > (rssi1 + 20))
8486 pAd->Mlme.RealRxPath = 1;
8488 pAd->Mlme.RealRxPath = 2;
8491 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8493 if(pAd->Mlme.RealRxPath == 3)
8497 else if(pAd->Mlme.RealRxPath == 2)
8501 else if(pAd->Mlme.RealRxPath == 1)
8505 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8513 VOID APSDPeriodicExec(
8514 IN PVOID SystemSpecific1,
8515 IN PVOID FunctionContext,
8516 IN PVOID SystemSpecific2,
8517 IN PVOID SystemSpecific3)
8519 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8521 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8524 pAd->CommonCfg.TriggerTimerCount++;
8529 ========================================================================
8530 Routine Description:
8531 Set/reset MAC registers according to bPiggyBack parameter
8534 pAd - Adapter pointer
8535 bPiggyBack - Enable / Disable Piggy-Back
8540 ========================================================================
8542 VOID RTMPSetPiggyBack(
8543 IN PRTMP_ADAPTER pAd,
8544 IN BOOLEAN bPiggyBack)
8546 TX_LINK_CFG_STRUC TxLinkCfg;
8548 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8550 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8551 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8555 ========================================================================
8556 Routine Description:
8557 check if this entry need to switch rate automatically
8567 ========================================================================
8569 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8570 IN PRTMP_ADAPTER pAd,
8571 IN PMAC_TABLE_ENTRY pEntry)
8573 BOOLEAN result = TRUE;
8576 // only associated STA counts
8577 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8579 result = pAd->StaCfg.bAutoTxRateSwitch;
8589 BOOLEAN RTMPAutoRateSwitchCheck(
8590 IN PRTMP_ADAPTER pAd)
8592 if (pAd->StaCfg.bAutoTxRateSwitch)
8600 ========================================================================
8601 Routine Description:
8602 check if this entry need to fix tx legacy rate
8612 ========================================================================
8614 UCHAR RTMPStaFixedTxMode(
8615 IN PRTMP_ADAPTER pAd,
8616 IN PMAC_TABLE_ENTRY pEntry)
8618 UCHAR tx_mode = FIXED_TXMODE_HT;
8620 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8626 ========================================================================
8627 Routine Description:
8628 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8638 ========================================================================
8640 VOID RTMPUpdateLegacyTxSetting(
8641 UCHAR fixed_tx_mode,
8642 PMAC_TABLE_ENTRY pEntry)
8644 HTTRANSMIT_SETTING TransmitSetting;
8646 if (fixed_tx_mode == FIXED_TXMODE_HT)
8649 TransmitSetting.word = 0;
8651 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8652 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8654 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8656 TransmitSetting.field.MODE = MODE_CCK;
8657 // CCK mode allow MCS 0~3
8658 if (TransmitSetting.field.MCS > MCS_3)
8659 TransmitSetting.field.MCS = MCS_3;
8663 TransmitSetting.field.MODE = MODE_OFDM;
8664 // OFDM mode allow MCS 0~7
8665 if (TransmitSetting.field.MCS > MCS_7)
8666 TransmitSetting.field.MCS = MCS_7;
8669 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8671 pEntry->HTPhyMode.word = TransmitSetting.word;
8672 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8673 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8678 ==========================================================================
8680 dynamic tune BBP R66 to find a balance between sensibility and
8683 IRQL = DISPATCH_LEVEL
8685 ==========================================================================
8687 VOID AsicStaBbpTuning(
8688 IN PRTMP_ADAPTER pAd)
8690 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8693 // 2860C did not support Fase CCA, therefore can't tune
8694 if (pAd->MACVersion == 0x28600100)
8700 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8703 if ((pAd->OpMode == OPMODE_STA)
8704 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8706 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8708 && (pAd->bPCIclkOff == FALSE))
8714 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8717 if (pAd->Antenna.field.RxPath > 1)
8718 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8720 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8722 if (pAd->LatchRfRegs.Channel <= 14)
8725 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8726 // Otherwise, it will have some throughput side effect when low RSSI
8734 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8736 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8737 if (OrigR66Value != R66)
8738 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8742 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8743 if (OrigR66Value != R66)
8744 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8750 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8752 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8753 if (OrigR66Value != R66)
8755 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8760 R66 = 0x2E + GET_LNA_GAIN(pAd);
8761 if (OrigR66Value != R66)
8763 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8770 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8772 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8774 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8775 if (OrigR66Value != R66)
8777 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8782 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8783 if (OrigR66Value != R66)
8785 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8791 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8793 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8794 if (OrigR66Value != R66)
8796 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8801 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8802 if (OrigR66Value != R66)
8804 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8815 VOID AsicResetFromDMABusy(
8816 IN PRTMP_ADAPTER pAd)
8819 BOOLEAN bCtrl = FALSE;
8821 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8823 // Be sure restore link control value so we can write register.
8824 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8825 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8827 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8828 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8829 RTMPusecDelay(6000);
8830 pAd->bPCIclkOff = FALSE;
8834 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8836 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8838 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8839 // Reset DMA/CPU ring index
8840 RTMPRingCleanUp(pAd, QID_AC_BK);
8841 RTMPRingCleanUp(pAd, QID_AC_BE);
8842 RTMPRingCleanUp(pAd, QID_AC_VI);
8843 RTMPRingCleanUp(pAd, QID_AC_VO);
8844 RTMPRingCleanUp(pAd, QID_HCCA);
8845 RTMPRingCleanUp(pAd, QID_MGMT);
8846 RTMPRingCleanUp(pAd, QID_RX);
8849 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8851 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8853 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8854 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8855 RTMPPCIeLinkCtrlSetting(pAd, 3);
8857 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8858 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8859 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8863 IN PRTMP_ADAPTER pAd)
8865 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8867 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8868 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8869 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8871 // After hard-reset BBP, initialize all BBP values.
8872 NICRestoreBBPValue(pAd);
8873 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8877 IN PRTMP_ADAPTER pAd)
8881 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8882 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8884 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8886 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8888 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8892 IN PRTMP_ADAPTER pAd)
8894 ULONG Value1, Value2;
8897 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8898 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8901 // sum should be equals to 0xff, which is the total buffer size.
8902 if ((Value1 + Value2) < 0xff)
8904 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8905 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8907 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8909 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8911 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8916 VOID RTMPSetAGCInitValue(
8917 IN PRTMP_ADAPTER pAd,
8922 if (pAd->LatchRfRegs.Channel <= 14)
8924 R66 = 0x2E + GET_LNA_GAIN(pAd);
8925 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8929 if (BandWidth == BW_20)
8931 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8932 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8936 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8937 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8943 VOID AsicTurnOffRFClk(
8944 IN PRTMP_ADAPTER pAd,
8949 UINT32 R1 = 0, R2 = 0, R3 = 0;
8951 RTMP_RF_REGS *RFRegTable;
8953 // The RF programming sequence is difference between 3xxx and 2xxx
8956 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8960 RFRegTable = RF2850RegTable;
8962 switch (pAd->RfIcType)
8969 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8971 if (Channel == RFRegTable[index].Channel)
8973 R1 = RFRegTable[index].R1 & 0xffffdfff;
8974 R2 = RFRegTable[index].R2 & 0xfffbffff;
8975 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8977 RTMP_RF_IO_WRITE32(pAd, R1);
8978 RTMP_RF_IO_WRITE32(pAd, R2);
8980 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8981 // Set RF R2 bit18=0, R3 bit[18:19]=0
8982 //if (pAd->StaCfg.bRadio == FALSE)
8985 RTMP_RF_IO_WRITE32(pAd, R3);
8987 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8988 Channel, pAd->RfIcType, R2, R3));
8991 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8992 Channel, pAd->RfIcType, R2));
9004 VOID AsicTurnOnRFClk(
9005 IN PRTMP_ADAPTER pAd,
9010 UINT32 R1 = 0, R2 = 0, R3 = 0;
9012 RTMP_RF_REGS *RFRegTable;
9014 // The RF programming sequence is difference between 3xxx and 2xxx
9018 RFRegTable = RF2850RegTable;
9020 switch (pAd->RfIcType)
9027 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9029 if (Channel == RFRegTable[index].Channel)
9031 R3 = pAd->LatchRfRegs.R3;
9034 RTMP_RF_IO_WRITE32(pAd, R3);
9036 R1 = RFRegTable[index].R1;
9037 RTMP_RF_IO_WRITE32(pAd, R1);
9039 R2 = RFRegTable[index].R2;
9040 if (pAd->Antenna.field.TxPath == 1)
9042 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
9045 if (pAd->Antenna.field.RxPath == 2)
9047 R2 |= 0x40; // write 1 to off Rxpath.
9049 else if (pAd->Antenna.field.RxPath == 1)
9051 R2 |= 0x20040; // write 1 to off RxPath
9053 RTMP_RF_IO_WRITE32(pAd, R2);
9064 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",