2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
55 UCHAR RateSwitchTable[] = {
56 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
57 0x11, 0x00, 0, 0, 0, // Initial used item after association
58 0x00, 0x00, 0, 40, 101,
59 0x01, 0x00, 1, 40, 50,
60 0x02, 0x00, 2, 35, 45,
61 0x03, 0x00, 3, 20, 45,
62 0x04, 0x21, 0, 30, 50,
63 0x05, 0x21, 1, 20, 50,
64 0x06, 0x21, 2, 20, 50,
65 0x07, 0x21, 3, 15, 50,
66 0x08, 0x21, 4, 15, 30,
67 0x09, 0x21, 5, 10, 25,
70 0x0c, 0x20, 12, 15, 30,
71 0x0d, 0x20, 13, 8, 20,
72 0x0e, 0x20, 14, 8, 20,
73 0x0f, 0x20, 15, 8, 25,
74 0x10, 0x22, 15, 8, 25,
92 UCHAR RateSwitchTable11B[] = {
93 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
94 0x04, 0x03, 0, 0, 0, // Initial used item after association
95 0x00, 0x00, 0, 40, 101,
96 0x01, 0x00, 1, 40, 50,
97 0x02, 0x00, 2, 35, 45,
98 0x03, 0x00, 3, 20, 45,
101 UCHAR RateSwitchTable11BG[] = {
102 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
103 0x0a, 0x00, 0, 0, 0, // Initial used item after association
104 0x00, 0x00, 0, 40, 101,
105 0x01, 0x00, 1, 40, 50,
106 0x02, 0x00, 2, 35, 45,
107 0x03, 0x00, 3, 20, 45,
108 0x04, 0x10, 2, 20, 35,
109 0x05, 0x10, 3, 16, 35,
110 0x06, 0x10, 4, 10, 25,
111 0x07, 0x10, 5, 16, 25,
112 0x08, 0x10, 6, 10, 25,
113 0x09, 0x10, 7, 10, 13,
116 UCHAR RateSwitchTable11G[] = {
117 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
118 0x08, 0x00, 0, 0, 0, // Initial used item after association
119 0x00, 0x10, 0, 20, 101,
120 0x01, 0x10, 1, 20, 35,
121 0x02, 0x10, 2, 20, 35,
122 0x03, 0x10, 3, 16, 35,
123 0x04, 0x10, 4, 10, 25,
124 0x05, 0x10, 5, 16, 25,
125 0x06, 0x10, 6, 10, 25,
126 0x07, 0x10, 7, 10, 13,
129 UCHAR RateSwitchTable11N1S[] = {
130 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
131 0x09, 0x00, 0, 0, 0, // Initial used item after association
132 0x00, 0x21, 0, 30, 101,
133 0x01, 0x21, 1, 20, 50,
134 0x02, 0x21, 2, 20, 50,
135 0x03, 0x21, 3, 15, 50,
136 0x04, 0x21, 4, 15, 30,
137 0x05, 0x21, 5, 10, 25,
138 0x06, 0x21, 6, 8, 14,
139 0x07, 0x21, 7, 8, 14,
140 0x08, 0x23, 7, 8, 14,
143 UCHAR RateSwitchTable11N2S[] = {
144 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
145 0x0a, 0x00, 0, 0, 0, // Initial used item after association
146 0x00, 0x21, 0, 30, 101,
147 0x01, 0x21, 1, 20, 50,
148 0x02, 0x21, 2, 20, 50,
149 0x03, 0x21, 3, 15, 50,
150 0x04, 0x21, 4, 15, 30,
151 0x05, 0x20, 12, 15, 30,
152 0x06, 0x20, 13, 8, 20,
153 0x07, 0x20, 14, 8, 20,
154 0x08, 0x20, 15, 8, 25,
155 0x09, 0x22, 15, 8, 25,
158 UCHAR RateSwitchTable11N3S[] = {
159 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
160 0x0a, 0x00, 0, 0, 0, // Initial used item after association
161 0x00, 0x21, 0, 30, 101,
162 0x01, 0x21, 1, 20, 50,
163 0x02, 0x21, 2, 20, 50,
164 0x03, 0x21, 3, 15, 50,
165 0x04, 0x21, 4, 15, 30,
166 0x05, 0x20, 12, 15, 30,
167 0x06, 0x20, 13, 8, 20,
168 0x07, 0x20, 14, 8, 20,
169 0x08, 0x20, 15, 8, 25,
170 0x09, 0x22, 15, 8, 25,
173 UCHAR RateSwitchTable11N2SForABand[] = {
174 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
175 0x0b, 0x09, 0, 0, 0, // Initial used item after association
176 0x00, 0x21, 0, 30, 101,
177 0x01, 0x21, 1, 20, 50,
178 0x02, 0x21, 2, 20, 50,
179 0x03, 0x21, 3, 15, 50,
180 0x04, 0x21, 4, 15, 30,
181 0x05, 0x21, 5, 15, 30,
182 0x06, 0x20, 12, 15, 30,
183 0x07, 0x20, 13, 8, 20,
184 0x08, 0x20, 14, 8, 20,
185 0x09, 0x20, 15, 8, 25,
186 0x0a, 0x22, 15, 8, 25,
189 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
190 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
191 0x0b, 0x09, 0, 0, 0, // Initial used item after association
192 0x00, 0x21, 0, 30, 101,
193 0x01, 0x21, 1, 20, 50,
194 0x02, 0x21, 2, 20, 50,
195 0x03, 0x21, 3, 15, 50,
196 0x04, 0x21, 4, 15, 30,
197 0x05, 0x21, 5, 15, 30,
198 0x06, 0x20, 12, 15, 30,
199 0x07, 0x20, 13, 8, 20,
200 0x08, 0x20, 14, 8, 20,
201 0x09, 0x20, 15, 8, 25,
202 0x0a, 0x22, 15, 8, 25,
205 UCHAR RateSwitchTable11BGN1S[] = {
206 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
207 0x0d, 0x00, 0, 0, 0, // Initial used item after association
208 0x00, 0x00, 0, 40, 101,
209 0x01, 0x00, 1, 40, 50,
210 0x02, 0x00, 2, 35, 45,
211 0x03, 0x00, 3, 20, 45,
212 0x04, 0x21, 0, 30,101, //50
213 0x05, 0x21, 1, 20, 50,
214 0x06, 0x21, 2, 20, 50,
215 0x07, 0x21, 3, 15, 50,
216 0x08, 0x21, 4, 15, 30,
217 0x09, 0x21, 5, 10, 25,
218 0x0a, 0x21, 6, 8, 14,
219 0x0b, 0x21, 7, 8, 14,
220 0x0c, 0x23, 7, 8, 14,
223 UCHAR RateSwitchTable11BGN2S[] = {
224 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
225 0x0a, 0x00, 0, 0, 0, // Initial used item after association
226 0x00, 0x21, 0, 30,101, //50
227 0x01, 0x21, 1, 20, 50,
228 0x02, 0x21, 2, 20, 50,
229 0x03, 0x21, 3, 15, 50,
230 0x04, 0x21, 4, 15, 30,
231 0x05, 0x20, 12, 15, 30,
232 0x06, 0x20, 13, 8, 20,
233 0x07, 0x20, 14, 8, 20,
234 0x08, 0x20, 15, 8, 25,
235 0x09, 0x22, 15, 8, 25,
238 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
239 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
240 0x0a, 0x00, 0, 0, 0, // Initial used item after association
241 0x00, 0x21, 0, 30,101, //50
242 0x01, 0x21, 1, 20, 50,
243 0x02, 0x21, 2, 20, 50,
244 0x03, 0x21, 3, 20, 50,
245 0x04, 0x21, 4, 15, 50,
246 0x05, 0x20, 20, 15, 30,
247 0x06, 0x20, 21, 8, 20,
248 0x07, 0x20, 22, 8, 20,
249 0x08, 0x20, 23, 8, 25,
250 0x09, 0x22, 23, 8, 25,
253 UCHAR RateSwitchTable11BGN2SForABand[] = {
254 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
255 0x0b, 0x09, 0, 0, 0, // Initial used item after association
256 0x00, 0x21, 0, 30,101, //50
257 0x01, 0x21, 1, 20, 50,
258 0x02, 0x21, 2, 20, 50,
259 0x03, 0x21, 3, 15, 50,
260 0x04, 0x21, 4, 15, 30,
261 0x05, 0x21, 5, 15, 30,
262 0x06, 0x20, 12, 15, 30,
263 0x07, 0x20, 13, 8, 20,
264 0x08, 0x20, 14, 8, 20,
265 0x09, 0x20, 15, 8, 25,
266 0x0a, 0x22, 15, 8, 25,
269 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
270 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
271 0x0c, 0x09, 0, 0, 0, // Initial used item after association
272 0x00, 0x21, 0, 30,101, //50
273 0x01, 0x21, 1, 20, 50,
274 0x02, 0x21, 2, 20, 50,
275 0x03, 0x21, 3, 15, 50,
276 0x04, 0x21, 4, 15, 30,
277 0x05, 0x21, 5, 15, 30,
278 0x06, 0x21, 12, 15, 30,
279 0x07, 0x20, 20, 15, 30,
280 0x08, 0x20, 21, 8, 20,
281 0x09, 0x20, 22, 8, 20,
282 0x0a, 0x20, 23, 8, 25,
283 0x0b, 0x22, 23, 8, 25,
286 PUCHAR ReasonString[] = {
288 /* 1 */ "Unspecified Reason",
289 /* 2 */ "Previous Auth no longer valid",
290 /* 3 */ "STA is leaving / has left",
291 /* 4 */ "DIS-ASSOC due to inactivity",
292 /* 5 */ "AP unable to hanle all associations",
293 /* 6 */ "class 2 error",
294 /* 7 */ "class 3 error",
295 /* 8 */ "STA is leaving / has left",
296 /* 9 */ "require auth before assoc/re-assoc",
300 /* 13 */ "invalid IE",
301 /* 14 */ "MIC error",
302 /* 15 */ "4-way handshake timeout",
303 /* 16 */ "2-way (group key) handshake timeout",
304 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
308 extern UCHAR OfdmRateToRxwiMCS[];
309 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
310 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
311 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
312 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
313 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
315 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
316 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
317 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
319 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
320 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
321 // clean environment.
322 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
323 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
325 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
326 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
328 UCHAR SsidIe = IE_SSID;
329 UCHAR SupRateIe = IE_SUPP_RATES;
330 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
331 UCHAR HtCapIe = IE_HT_CAP;
332 UCHAR AddHtInfoIe = IE_ADD_HT;
333 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
334 UCHAR ErpIe = IE_ERP;
335 UCHAR DsIe = IE_DS_PARM;
336 UCHAR TimIe = IE_TIM;
337 UCHAR WpaIe = IE_WPA;
338 UCHAR Wpa2Ie = IE_WPA2;
339 UCHAR IbssIe = IE_IBSS_PARM;
340 UCHAR Ccx2Ie = IE_CCX_V2;
342 extern UCHAR WPA_OUI[];
344 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
346 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
347 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
349 // Reset the RFIC setting to new series
350 RTMP_RF_REGS RF2850RegTable[] = {
351 // ch R1 R2 R3(TX0~4=0) R4
352 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
353 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
354 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
355 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
356 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
357 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
358 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
359 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
360 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
361 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
362 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
363 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
364 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
365 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
367 // 802.11 UNI / HyperLan 2
368 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
369 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
370 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
371 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
372 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
373 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
374 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
375 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
376 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
377 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
378 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
379 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
382 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
384 // 2008.04.30 modified
385 // The system team has AN to improve the EVM value
386 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
387 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
388 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
389 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
391 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
392 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
393 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
394 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
395 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
396 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
397 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
398 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
399 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
400 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
401 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
402 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
405 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
406 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
407 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
408 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
409 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
410 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
411 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
414 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
415 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
416 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
417 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
418 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
419 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
420 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
422 // still lack of MMAC(Japan) ch 34,38,42,46
424 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
426 FREQUENCY_ITEM FreqItems3020[] =
428 /**************************************************/
429 // ISM : 2.4 to 2.483 GHz //
430 /**************************************************/
432 /**************************************************/
433 //-CH---N-------R---K-----------
449 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
452 ==========================================================================
454 initialize the MLME task and its data structure (queue, spinlock,
455 timer, state machines).
460 always return NDIS_STATUS_SUCCESS
462 ==========================================================================
464 NDIS_STATUS MlmeInit(
465 IN PRTMP_ADAPTER pAd)
467 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
469 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
473 Status = MlmeQueueInit(&pAd->Mlme.Queue);
474 if(Status != NDIS_STATUS_SUCCESS)
477 pAd->Mlme.bRunning = FALSE;
478 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
481 BssTableInit(&pAd->ScanTab);
483 // init STA state machines
484 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
485 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
486 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
487 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
488 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
489 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
491 // Since we are using switch/case to implement it, the init is different from the above
492 // state machine init
493 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
496 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
498 // Init mlme periodic timer
499 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
501 // Set mlme periodic timer
502 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
504 // software-based RX Antenna diversity
505 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);
517 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
523 ==========================================================================
525 main loop of the MLME
527 Mlme has to be initialized, and there are something inside the queue
529 This function is invoked from MPSetInformation and MPReceive;
530 This task guarantee only one MlmeHandler will run.
532 IRQL = DISPATCH_LEVEL
534 ==========================================================================
537 IN PRTMP_ADAPTER pAd)
539 MLME_QUEUE_ELEM *Elem = NULL;
541 // Only accept MLME and Frame from peer side, no other (control/data) frame should
542 // get into this state machine
544 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
545 if(pAd->Mlme.bRunning)
547 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
552 pAd->Mlme.bRunning = TRUE;
554 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
556 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
558 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
559 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
560 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
562 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
566 //From message type, determine which state machine I should drive
567 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
570 // if dequeue success
571 switch (Elem->Machine)
573 // STA state machines
574 case ASSOC_STATE_MACHINE:
575 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
577 case AUTH_STATE_MACHINE:
578 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
580 case AUTH_RSP_STATE_MACHINE:
581 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
583 case SYNC_STATE_MACHINE:
584 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
586 case MLME_CNTL_STATE_MACHINE:
587 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
589 case WPA_PSK_STATE_MACHINE:
590 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
592 case AIRONET_STATE_MACHINE:
593 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
595 case ACTION_STATE_MACHINE:
596 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
603 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
608 Elem->Occupied = FALSE;
613 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
617 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
618 pAd->Mlme.bRunning = FALSE;
619 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
623 ==========================================================================
625 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
627 Adapter - NIC Adapter pointer
629 The MLME task will no longer work properly
633 ==========================================================================
636 IN PRTMP_ADAPTER pAd)
640 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
642 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
644 // disable BEACON generation and other BEACON related hardware timers
645 AsicDisableSync(pAd);
649 // Cancel pending timers
650 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
651 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
652 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
653 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
654 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
655 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
656 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
658 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
659 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
663 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
664 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
668 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
671 RTMPSetLED(pAd, LED_HALT);
672 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
675 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
677 MlmeQueueDestroy(&pAd->Mlme.Queue);
678 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
680 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
683 VOID MlmeResetRalinkCounters(
684 IN PRTMP_ADAPTER pAd)
686 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
687 // clear all OneSecxxx counters.
688 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
689 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
690 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
691 pAd->RalinkCounters.OneSecRxOkCnt = 0;
692 pAd->RalinkCounters.OneSecTxFailCount = 0;
693 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
694 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
695 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
697 // TODO: for debug only. to be removed
698 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
699 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
700 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
701 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
702 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
703 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
704 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
705 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
706 pAd->RalinkCounters.OneSecTxDoneCount = 0;
707 pAd->RalinkCounters.OneSecRxCount = 0;
708 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
709 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
714 unsigned long rx_AMSDU;
715 unsigned long rx_Total;
718 ==========================================================================
720 This routine is executed periodically to -
721 1. Decide if it's a right time to turn on PwrMgmt bit of all
723 2. Calculate ChannelQuality based on statistics of the last
724 period, so that TX rate won't toggling very frequently between a
725 successful TX and a failed TX.
726 3. If the calculated ChannelQuality indicated current connection not
727 healthy, then a ROAMing attempt is tried here.
729 IRQL = DISPATCH_LEVEL
731 ==========================================================================
733 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
734 VOID MlmePeriodicExec(
735 IN PVOID SystemSpecific1,
736 IN PVOID FunctionContext,
737 IN PVOID SystemSpecific2,
738 IN PVOID SystemSpecific3)
741 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
744 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
745 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
746 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
747 if(pAd->StaCfg.WepStatus<2)
749 pAd->StaCfg.WpaSupplicantUP = 0;
753 pAd->StaCfg.WpaSupplicantUP = 1;
757 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
758 // Move code to here, because following code will return when radio is off
759 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
760 (pAd->StaCfg.bHardwareRadio == TRUE) &&
761 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
762 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
763 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
767 // Read GPIO pin2 as Hardware controlled radio state
768 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
771 pAd->StaCfg.bHwRadio = TRUE;
775 pAd->StaCfg.bHwRadio = FALSE;
777 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
779 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
780 if (pAd->StaCfg.bRadio == TRUE)
783 // Update extra information
784 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
789 // Update extra information
790 pAd->ExtraInfo = HW_RADIO_OFF;
796 // Do nothing if the driver is starting halt state.
797 // This might happen when timer already been fired before cancel timer with mlmehalt
798 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
799 fRTMP_ADAPTER_RADIO_OFF |
800 fRTMP_ADAPTER_RADIO_MEASUREMENT |
801 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
805 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
807 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
808 pAd->SameRxByteCount++;
811 pAd->SameRxByteCount = 0;
813 // If after BBP, still not work...need to check to reset PBF&MAC.
814 if (pAd->SameRxByteCount == 702)
816 pAd->SameRxByteCount = 0;
821 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
822 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
824 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
826 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
827 pAd->SameRxByteCount = 700;
832 // Update lastReceiveByteCount.
833 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
835 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
837 pAd->CheckDmaBusyCount = 0;
838 AsicResetFromDMABusy(pAd);
842 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
845 // Do nothing if monitor mode is on
849 if (pAd->Mlme.PeriodicRound & 0x1)
851 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
852 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
853 (STA_TGN_WIFI_ON(pAd)) &&
854 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
857 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
858 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
860 else if ((STA_TGN_WIFI_ON(pAd)) &&
861 ((pAd->MACVersion & 0xffff) == 0x0101))
863 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
864 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
869 pAd->bUpdateBcnCntDone = FALSE;
871 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
872 pAd->Mlme.PeriodicRound ++;
874 // execute every 500ms
875 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
877 // perform dynamic tx rate switching based on past TX history
879 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
881 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
882 MlmeDynamicTxRateSwitching(pAd);
886 // Normal 1 second Mlme PeriodicExec.
887 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
889 pAd->Mlme.OneSecPeriodicRound ++;
899 // Media status changed, report to NDIS
900 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
902 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
903 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
905 pAd->IndicateMediaState = NdisMediaStateConnected;
906 RTMP_IndicateMediaState(pAd);
911 pAd->IndicateMediaState = NdisMediaStateDisconnected;
912 RTMP_IndicateMediaState(pAd);
916 NdisGetSystemUpTime(&pAd->Mlme.Now32);
918 // add the most up-to-date h/w raw counters into software variable, so that
919 // the dynamic tuning mechanism below are based on most up-to-date information
920 NICUpdateRawCounters(pAd);
922 // Need statistics after read counter. So put after NICUpdateRawCounters
923 ORIBATimerTimeout(pAd);
925 // The time period for checking antenna is according to traffic
926 if (pAd->Mlme.bEnableAutoAntennaCheck)
928 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
929 pAd->RalinkCounters.OneSecTxRetryOkCount +
930 pAd->RalinkCounters.OneSecTxFailCount;
934 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
936 AsicEvaluateRxAnt(pAd);
941 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
943 AsicEvaluateRxAnt(pAd);
948 STAMlmePeriodicExec(pAd);
950 MlmeResetRalinkCounters(pAd);
953 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
955 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
956 // and sending CTS-to-self over and over.
957 // Software Patch Solution:
958 // 1. Polling debug state register 0x10F4 every one second.
959 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
960 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
964 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
965 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
967 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
969 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
971 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
976 RT28XX_MLME_HANDLER(pAd);
980 pAd->bUpdateBcnCntDone = FALSE;
983 VOID STAMlmePeriodicExec(
988 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
990 // WPA MIC error should block association attempt for 60 seconds
991 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
992 pAd->StaCfg.bBlockAssoc = FALSE;
996 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
997 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
998 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
999 if(pAd->StaCfg.WepStatus<2)
1001 pAd->StaCfg.WpaSupplicantUP = 0;
1005 pAd->StaCfg.WpaSupplicantUP = 1;
1008 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1010 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1012 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1014 pAd->PreMediaState = pAd->IndicateMediaState;
1017 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1018 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1019 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1020 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1021 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1022 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1024 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1029 AsicStaBbpTuning(pAd);
1031 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1032 pAd->RalinkCounters.OneSecTxRetryOkCount +
1033 pAd->RalinkCounters.OneSecTxFailCount;
1035 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1037 // update channel quality for Roaming and UI LinkQuality display
1038 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1041 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1042 // Radio is currently in noisy environment
1043 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1044 AsicAdjustTxPower(pAd);
1048 // Is PSM bit consistent with user power management policy?
1049 // This is the only place that will set PSM bit ON.
1050 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1051 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1053 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1055 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1056 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1057 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1059 RTMPSetAGCInitValue(pAd, BW_20);
1060 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1064 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1066 // When APSD is enabled, the period changes as 20 sec
1067 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1068 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1072 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1073 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1075 if (pAd->CommonCfg.bWmmCapable)
1076 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1078 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1083 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1085 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1086 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1087 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1089 // Lost AP, send disconnect & link down event
1090 LinkDown(pAd, FALSE);
1093 union iwreq_data wrqu;
1094 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1095 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1098 MlmeAutoReconnectLastSSID(pAd);
1100 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1102 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1103 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1104 MlmeAutoReconnectLastSSID(pAd);
1107 // Add auto seamless roaming
1108 if (pAd->StaCfg.bFastRoaming)
1110 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1112 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));
1114 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1116 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1120 else if (ADHOC_ON(pAd))
1122 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1123 // the "TX BEACON competition" for the entire past 1 sec.
1124 // So that even when ASIC's BEACONgen engine been blocked
1125 // by peer's BEACON due to slower system clock, this STA still can send out
1126 // minimum BEACON to tell the peer I'm alive.
1127 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1128 // EnqueueBeaconFrame(pAd); // software send BEACON
1130 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1131 // restore outgoing BEACON to support B/G-mixed mode
1132 if ((pAd->CommonCfg.Channel <= 14) &&
1133 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1134 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1135 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1137 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1138 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1139 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1140 MlmeUpdateTxRates(pAd, FALSE, 0);
1141 MakeIbssBeacon(pAd); // re-build BEACON frame
1142 AsicEnableIbssSync(pAd); // copy to on-chip memory
1143 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1146 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1148 if ((pAd->StaCfg.AdhocBGJoined) &&
1149 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1151 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1152 pAd->StaCfg.AdhocBGJoined = FALSE;
1155 if ((pAd->StaCfg.Adhoc20NJoined) &&
1156 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1158 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1159 pAd->StaCfg.Adhoc20NJoined = FALSE;
1164 if ((pAd->CommonCfg.Channel > 14)
1165 && (pAd->CommonCfg.bIEEE80211H == 1)
1166 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1168 RadarDetectPeriodic(pAd);
1171 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1172 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1174 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1175 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1177 MLME_START_REQ_STRUCT StartReq;
1179 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1180 LinkDown(pAd, FALSE);
1182 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1183 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1184 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1187 else // no INFRA nor ADHOC connection
1190 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1191 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1192 goto SKIP_AUTO_SCAN_CONN;
1194 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1196 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1197 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1198 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1200 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1202 MLME_SCAN_REQ_STRUCT ScanReq;
1204 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1206 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1207 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1208 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1209 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1210 // Reset Missed scan number
1211 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1213 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1214 MlmeAutoReconnectLastSSID(pAd);
1216 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1218 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1221 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1225 MlmeAutoReconnectLastSSID(pAd);
1231 SKIP_AUTO_SCAN_CONN:
1233 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1235 pAd->MacTab.fAnyBASession = TRUE;
1236 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1238 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1240 pAd->MacTab.fAnyBASession = FALSE;
1241 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1249 IN PVOID SystemSpecific1,
1250 IN PVOID FunctionContext,
1251 IN PVOID SystemSpecific2,
1252 IN PVOID SystemSpecific3)
1255 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1257 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1258 RTMP_IndicateMediaState(pAd);
1259 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1262 // IRQL = DISPATCH_LEVEL
1264 IN PRTMP_ADAPTER pAd)
1266 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1267 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1269 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1271 MLME_CNTL_STATE_MACHINE,
1272 OID_802_11_BSSID_LIST_SCAN,
1275 RT28XX_MLME_HANDLER(pAd);
1279 // IRQL = DISPATCH_LEVEL
1280 VOID MlmeAutoReconnectLastSSID(
1281 IN PRTMP_ADAPTER pAd)
1285 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1286 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1287 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1289 NDIS_802_11_SSID OidSsid;
1290 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1291 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1293 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1295 MLME_CNTL_STATE_MACHINE,
1297 sizeof(NDIS_802_11_SSID),
1299 RT28XX_MLME_HANDLER(pAd);
1304 ==========================================================================
1305 Validate SSID for connection try and rescan purpose
1306 Valid SSID will have visible chars only.
1307 The valid length is from 0 to 32.
1308 IRQL = DISPATCH_LEVEL
1309 ==========================================================================
1311 BOOLEAN MlmeValidateSSID(
1317 if (SsidLen > MAX_LEN_OF_SSID)
1320 // Check each character value
1321 for (index = 0; index < SsidLen; index++)
1323 if (pSsid[index] < 0x20)
1331 VOID MlmeSelectTxRateTable(
1332 IN PRTMP_ADAPTER pAd,
1333 IN PMAC_TABLE_ENTRY pEntry,
1335 IN PUCHAR pTableSize,
1336 IN PUCHAR pInitTxRateIdx)
1340 // decide the rate table for tuning
1341 if (pAd->CommonCfg.TxRateTableSize > 0)
1343 *ppTable = RateSwitchTable;
1344 *pTableSize = RateSwitchTable[0];
1345 *pInitTxRateIdx = RateSwitchTable[1];
1350 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1352 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1353 !pAd->StaCfg.AdhocBOnlyJoined &&
1354 !pAd->StaCfg.AdhocBGJoined &&
1355 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1356 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1358 *ppTable = RateSwitchTable11N1S;
1359 *pTableSize = RateSwitchTable11N1S[0];
1360 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1363 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1364 !pAd->StaCfg.AdhocBOnlyJoined &&
1365 !pAd->StaCfg.AdhocBGJoined &&
1366 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1367 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1368 (pAd->Antenna.field.TxPath == 2))
1370 if (pAd->LatchRfRegs.Channel <= 14)
1372 *ppTable = RateSwitchTable11N2S;
1373 *pTableSize = RateSwitchTable11N2S[0];
1374 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1378 *ppTable = RateSwitchTable11N2SForABand;
1379 *pTableSize = RateSwitchTable11N2SForABand[0];
1380 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1385 if (pAd->CommonCfg.PhyMode == PHY_11B)
1387 *ppTable = RateSwitchTable11B;
1388 *pTableSize = RateSwitchTable11B[0];
1389 *pInitTxRateIdx = RateSwitchTable11B[1];
1392 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1394 // USe B Table when Only b-only Station in my IBSS .
1395 *ppTable = RateSwitchTable11B;
1396 *pTableSize = RateSwitchTable11B[0];
1397 *pInitTxRateIdx = RateSwitchTable11B[1];
1400 else if (pAd->LatchRfRegs.Channel <= 14)
1402 *ppTable = RateSwitchTable11BG;
1403 *pTableSize = RateSwitchTable11BG[0];
1404 *pInitTxRateIdx = RateSwitchTable11BG[1];
1409 *ppTable = RateSwitchTable11G;
1410 *pTableSize = RateSwitchTable11G[0];
1411 *pInitTxRateIdx = RateSwitchTable11G[1];
1417 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1418 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1420 *ppTable = RateSwitchTable11BGN1S;
1421 *pTableSize = RateSwitchTable11BGN1S[0];
1422 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1427 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1428 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1430 if (pAd->LatchRfRegs.Channel <= 14)
1432 *ppTable = RateSwitchTable11BGN2S;
1433 *pTableSize = RateSwitchTable11BGN2S[0];
1434 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1439 *ppTable = RateSwitchTable11BGN2SForABand;
1440 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1441 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1447 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1449 *ppTable = RateSwitchTable11N1S;
1450 *pTableSize = RateSwitchTable11N1S[0];
1451 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1456 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1458 if (pAd->LatchRfRegs.Channel <= 14)
1460 *ppTable = RateSwitchTable11N2S;
1461 *pTableSize = RateSwitchTable11N2S[0];
1462 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1466 *ppTable = RateSwitchTable11N2SForABand;
1467 *pTableSize = RateSwitchTable11N2SForABand[0];
1468 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1474 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1475 if ((pEntry->RateLen == 4)
1476 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1479 *ppTable = RateSwitchTable11B;
1480 *pTableSize = RateSwitchTable11B[0];
1481 *pInitTxRateIdx = RateSwitchTable11B[1];
1486 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1487 if ((pEntry->RateLen > 8)
1488 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1491 *ppTable = RateSwitchTable11BG;
1492 *pTableSize = RateSwitchTable11BG[0];
1493 *pInitTxRateIdx = RateSwitchTable11BG[1];
1498 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1499 if ((pEntry->RateLen == 8)
1500 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1503 *ppTable = RateSwitchTable11G;
1504 *pTableSize = RateSwitchTable11G[0];
1505 *pInitTxRateIdx = RateSwitchTable11G[1];
1511 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1512 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1514 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1516 *ppTable = RateSwitchTable11B;
1517 *pTableSize = RateSwitchTable11B[0];
1518 *pInitTxRateIdx = RateSwitchTable11B[1];
1520 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1522 *ppTable = RateSwitchTable11G;
1523 *pTableSize = RateSwitchTable11G[0];
1524 *pInitTxRateIdx = RateSwitchTable11G[1];
1529 *ppTable = RateSwitchTable11BG;
1530 *pTableSize = RateSwitchTable11BG[0];
1531 *pInitTxRateIdx = RateSwitchTable11BG[1];
1536 if (pAd->LatchRfRegs.Channel <= 14)
1538 if (pAd->CommonCfg.TxStream == 1)
1540 *ppTable = RateSwitchTable11N1S;
1541 *pTableSize = RateSwitchTable11N1S[0];
1542 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1543 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1547 *ppTable = RateSwitchTable11N2S;
1548 *pTableSize = RateSwitchTable11N2S[0];
1549 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1550 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1555 if (pAd->CommonCfg.TxStream == 1)
1557 *ppTable = RateSwitchTable11N1S;
1558 *pTableSize = RateSwitchTable11N1S[0];
1559 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1560 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1564 *ppTable = RateSwitchTable11N2SForABand;
1565 *pTableSize = RateSwitchTable11N2SForABand[0];
1566 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1567 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1571 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1572 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1578 ==========================================================================
1580 This routine checks if there're other APs out there capable for
1581 roaming. Caller should call this routine only when Link up in INFRA mode
1582 and channel quality is below CQI_GOOD_THRESHOLD.
1584 IRQL = DISPATCH_LEVEL
1587 ==========================================================================
1589 VOID MlmeCheckForRoaming(
1590 IN PRTMP_ADAPTER pAd,
1594 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1597 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1598 // put all roaming candidates into RoamTab, and sort in RSSI order
1599 BssTableInit(pRoamTab);
1600 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1602 pBss = &pAd->ScanTab.BssEntry[i];
1604 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1605 continue; // AP disappear
1606 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1607 continue; // RSSI too weak. forget it.
1608 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1609 continue; // skip current AP
1610 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1611 continue; // only AP with stronger RSSI is eligible for roaming
1613 // AP passing all above rules is put into roaming candidate table
1614 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1615 pRoamTab->BssNr += 1;
1618 if (pRoamTab->BssNr > 0)
1620 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1621 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1623 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1624 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1625 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1626 RT28XX_MLME_HANDLER(pAd);
1629 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1633 ==========================================================================
1635 This routine checks if there're other APs out there capable for
1636 roaming. Caller should call this routine only when link up in INFRA mode
1637 and channel quality is below CQI_GOOD_THRESHOLD.
1639 IRQL = DISPATCH_LEVEL
1642 ==========================================================================
1644 VOID MlmeCheckForFastRoaming(
1645 IN PRTMP_ADAPTER pAd,
1649 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1652 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1653 // put all roaming candidates into RoamTab, and sort in RSSI order
1654 BssTableInit(pRoamTab);
1655 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1657 pBss = &pAd->ScanTab.BssEntry[i];
1659 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1660 continue; // RSSI too weak. forget it.
1661 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1662 continue; // skip current AP
1663 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1664 continue; // skip different SSID
1665 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1666 continue; // skip AP without better RSSI
1668 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));
1669 // AP passing all above rules is put into roaming candidate table
1670 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1671 pRoamTab->BssNr += 1;
1674 if (pRoamTab->BssNr > 0)
1676 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1677 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1679 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1680 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1681 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1682 RT28XX_MLME_HANDLER(pAd);
1685 // Maybe site survey required
1688 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1690 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1691 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1692 pAd->StaCfg.ScanCnt = 2;
1693 pAd->StaCfg.LastScanTime = Now;
1698 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1702 ==========================================================================
1704 This routine calculates TxPER, RxPER of the past N-sec period. And
1705 according to the calculation result, ChannelQuality is calculated here
1706 to decide if current AP is still doing the job.
1708 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1710 StaCfg.ChannelQuality - 0..100
1712 IRQL = DISPATCH_LEVEL
1714 NOTE: This routine decide channle quality based on RX CRC error ratio.
1715 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1716 is performed right before this routine, so that this routine can decide
1717 channel quality based on the most up-to-date information
1718 ==========================================================================
1720 VOID MlmeCalculateChannelQuality(
1721 IN PRTMP_ADAPTER pAd,
1724 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1728 ULONG BeaconLostTime = BEACON_LOST_TIME;
1730 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1733 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1735 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1736 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1744 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1745 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1749 // calculate RX PER - don't take RxPER into consideration if too few sample
1751 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1755 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1758 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1760 if (INFRA_ON(pAd) &&
1761 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1762 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1764 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1765 pAd->Mlme.ChannelQuality = 0;
1772 else if (MaxRssi < -90)
1775 NorRssi = (MaxRssi + 90) * 2;
1777 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1778 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1779 TX_WEIGHTING * (100 - TxPRR) +
1780 RX_WEIGHTING* (100 - RxPER)) / 100;
1781 if (pAd->Mlme.ChannelQuality >= 100)
1782 pAd->Mlme.ChannelQuality = 100;
1788 IN PRTMP_ADAPTER pAd,
1789 IN PMAC_TABLE_ENTRY pEntry,
1790 IN PRTMP_TX_RATE_SWITCH pTxRate)
1792 UCHAR MaxMode = MODE_OFDM;
1794 MaxMode = MODE_HTGREENFIELD;
1796 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1797 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1799 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1801 if (pTxRate->CurrMCS < MCS_AUTO)
1802 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1804 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1805 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1809 // If peer adhoc is b-only mode, we can't send 11g rate.
1810 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1811 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1814 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1816 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1817 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1818 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1820 // Patch speed error in status page
1821 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1825 if (pTxRate->Mode <= MaxMode)
1826 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1828 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1829 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1831 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1833 // Reexam each bandwidth's SGI support.
1834 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1836 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1837 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1838 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1839 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1842 // Turn RTS/CTS rate to 6Mbps.
1843 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1845 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1846 if (pAd->MacTab.fAnyBASession)
1848 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1852 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1855 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1857 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1858 if (pAd->MacTab.fAnyBASession)
1860 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1864 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1867 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1869 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1872 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1874 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1877 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1878 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1879 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1880 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1882 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1883 pAd->WIFItestbed.bGreenField)
1884 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1887 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1891 ==========================================================================
1893 This routine calculates the acumulated TxPER of eaxh TxRate. And
1894 according to the calculation result, change CommonCfg.TxRate which
1895 is the stable TX Rate we expect the Radio situation could sustained.
1897 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1901 IRQL = DISPATCH_LEVEL
1904 call this routine every second
1905 ==========================================================================
1907 VOID MlmeDynamicTxRateSwitching(
1908 IN PRTMP_ADAPTER pAd)
1910 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1911 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1912 ULONG TxErrorRatio = 0;
1913 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1914 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1916 UCHAR TableSize = 0;
1917 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1918 CHAR Rssi, RssiOffset = 0;
1919 TX_STA_CNT1_STRUC StaTx1;
1920 TX_STA_CNT0_STRUC TxStaCnt0;
1921 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1922 MAC_TABLE_ENTRY *pEntry;
1925 // walk through MAC table, see if need to change AP's TX rate toward each entry
1927 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1929 pEntry = &pAd->MacTab.Content[i];
1931 // check if this entry need to switch rate automatically
1932 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1935 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1937 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
1939 // Update statistic counter
1940 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1941 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1942 pAd->bUpdateBcnCntDone = TRUE;
1943 TxRetransmit = StaTx1.field.TxRetransmit;
1944 TxSuccess = StaTx1.field.TxSuccess;
1945 TxFailCount = TxStaCnt0.field.TxFailCount;
1946 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1948 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1949 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1950 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1951 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1952 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1953 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1955 // if no traffic in the past 1-sec period, don't change TX rate,
1956 // but clear all bad history. because the bad history may affect the next
1957 // Chariot throughput test
1958 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1959 pAd->RalinkCounters.OneSecTxRetryOkCount +
1960 pAd->RalinkCounters.OneSecTxFailCount;
1963 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1967 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
1969 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1970 pEntry->OneSecTxRetryOkCount +
1971 pEntry->OneSecTxFailCount;
1974 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1977 CurrRateIdx = pEntry->CurrTxRateIndex;
1979 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1981 if (CurrRateIdx >= TableSize)
1983 CurrRateIdx = TableSize - 1;
1986 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1987 // So need to sync here.
1988 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1989 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1990 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1994 // Need to sync Real Tx rate and our record.
1995 // Then return for next DRS.
1996 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1997 pEntry->CurrTxRateIndex = InitTxRateIdx;
1998 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2000 // reset all OneSecTx counters
2001 RESET_ONE_SEC_TX_CNT(pEntry);
2005 // decide the next upgrade rate and downgrade rate, if any
2006 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2008 UpRateIdx = CurrRateIdx + 1;
2009 DownRateIdx = CurrRateIdx -1;
2011 else if (CurrRateIdx == 0)
2013 UpRateIdx = CurrRateIdx + 1;
2014 DownRateIdx = CurrRateIdx;
2016 else if (CurrRateIdx == (TableSize - 1))
2018 UpRateIdx = CurrRateIdx;
2019 DownRateIdx = CurrRateIdx - 1;
2022 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2024 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2026 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2027 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2031 TrainUp = pCurrTxRate->TrainUp;
2032 TrainDown = pCurrTxRate->TrainDown;
2035 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2038 // Keep the last time TxRateChangeAction status.
2040 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2045 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2046 // (criteria copied from RT2500 for Netopia case)
2048 if (TxTotalCnt <= 15)
2052 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2053 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2054 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2055 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2057 // check the existence and index of each needed MCS
2058 while (idx < pTable[0])
2060 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2062 if (pCurrTxRate->CurrMCS == MCS_0)
2066 else if (pCurrTxRate->CurrMCS == MCS_1)
2070 else if (pCurrTxRate->CurrMCS == MCS_2)
2074 else if (pCurrTxRate->CurrMCS == MCS_3)
2078 else if (pCurrTxRate->CurrMCS == MCS_4)
2082 else if (pCurrTxRate->CurrMCS == MCS_5)
2086 else if (pCurrTxRate->CurrMCS == MCS_6)
2090 //else if (pCurrTxRate->CurrMCS == MCS_7)
2091 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2095 else if (pCurrTxRate->CurrMCS == MCS_12)
2099 else if (pCurrTxRate->CurrMCS == MCS_13)
2103 else if (pCurrTxRate->CurrMCS == MCS_14)
2107 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
2111 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2115 else if (pCurrTxRate->CurrMCS == MCS_21)
2119 else if (pCurrTxRate->CurrMCS == MCS_22)
2123 else if (pCurrTxRate->CurrMCS == MCS_23)
2130 if (pAd->LatchRfRegs.Channel <= 14)
2132 if (pAd->NicConfig2.field.ExternalLNAForG)
2143 if (pAd->NicConfig2.field.ExternalLNAForA)
2154 if ((pTable == RateSwitchTable11BGN3S) ||
2155 (pTable == RateSwitchTable11N3S) ||
2156 (pTable == RateSwitchTable))
2157 {// N mode with 3 stream // 3*3
2158 if (MCS23 && (Rssi >= -70))
2160 else if (MCS22 && (Rssi >= -72))
2162 else if (MCS21 && (Rssi >= -76))
2164 else if (MCS20 && (Rssi >= -78))
2166 else if (MCS4 && (Rssi >= -82))
2168 else if (MCS3 && (Rssi >= -84))
2170 else if (MCS2 && (Rssi >= -86))
2172 else if (MCS1 && (Rssi >= -88))
2177 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2178 {// N mode with 2 stream
2179 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2181 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2183 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2185 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2187 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2189 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2191 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2193 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2198 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2199 {// N mode with 1 stream
2200 if (MCS7 && (Rssi > (-72+RssiOffset)))
2202 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2204 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2206 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2208 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2210 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2212 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2219 if (MCS7 && (Rssi > -70))
2221 else if (MCS6 && (Rssi > -74))
2223 else if (MCS5 && (Rssi > -78))
2225 else if (MCS4 && (Rssi > -82))
2227 else if (MCS4 == 0) // for B-only mode
2229 else if (MCS3 && (Rssi > -85))
2231 else if (MCS2 && (Rssi > -87))
2233 else if (MCS1 && (Rssi > -90))
2240 pEntry->CurrTxRateIndex = TxRateIdx;
2241 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2242 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2245 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2246 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2247 pEntry->fLastSecAccordingRSSI = TRUE;
2248 // reset all OneSecTx counters
2249 RESET_ONE_SEC_TX_CNT(pEntry);
2254 if (pEntry->fLastSecAccordingRSSI == TRUE)
2256 pEntry->fLastSecAccordingRSSI = FALSE;
2257 pEntry->LastSecTxRateChangeAction = 0;
2258 // reset all OneSecTx counters
2259 RESET_ONE_SEC_TX_CNT(pEntry);
2266 BOOLEAN bTrainUpDown = FALSE;
2268 pEntry->CurrTxRateStableTime ++;
2270 // downgrade TX quality if PER >= Rate-Down threshold
2271 if (TxErrorRatio >= TrainDown)
2273 bTrainUpDown = TRUE;
2274 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2276 // upgrade TX quality if PER <= Rate-Up threshold
2277 else if (TxErrorRatio <= TrainUp)
2279 bTrainUpDown = TRUE;
2280 bUpgradeQuality = TRUE;
2281 if (pEntry->TxQuality[CurrRateIdx])
2282 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2284 if (pEntry->TxRateUpPenalty)
2285 pEntry->TxRateUpPenalty --;
2286 else if (pEntry->TxQuality[UpRateIdx])
2287 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2290 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2294 // perform DRS - consider TxRate Down first, then rate up.
2295 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2297 pEntry->CurrTxRateIndex = DownRateIdx;
2299 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2301 pEntry->CurrTxRateIndex = UpRateIdx;
2306 // if rate-up happen, clear all bad history of all TX rates
2307 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2309 pEntry->CurrTxRateStableTime = 0;
2310 pEntry->TxRateUpPenalty = 0;
2311 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2312 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2313 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2316 // For TxRate fast train up
2318 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2320 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2322 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2324 bTxRateChanged = TRUE;
2326 // if rate-down happen, only clear DownRate's bad history
2327 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2329 pEntry->CurrTxRateStableTime = 0;
2330 pEntry->TxRateUpPenalty = 0; // no penalty
2331 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2332 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2333 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2336 // For TxRate fast train down
2338 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2340 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2342 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2344 bTxRateChanged = TRUE;
2348 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2349 bTxRateChanged = FALSE;
2352 pEntry->LastTxOkCount = TxSuccess;
2354 // reset all OneSecTx counters
2355 RESET_ONE_SEC_TX_CNT(pEntry);
2357 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2358 if (bTxRateChanged && pNextTxRate)
2360 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2366 ========================================================================
2367 Routine Description:
2368 Station side, Auto TxRate faster train up timer call back function.
2371 SystemSpecific1 - Not used.
2372 FunctionContext - Pointer to our Adapter context.
2373 SystemSpecific2 - Not used.
2374 SystemSpecific3 - Not used.
2379 ========================================================================
2381 VOID StaQuickResponeForRateUpExec(
2382 IN PVOID SystemSpecific1,
2383 IN PVOID FunctionContext,
2384 IN PVOID SystemSpecific2,
2385 IN PVOID SystemSpecific3)
2387 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2388 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2390 ULONG TxErrorRatio = 0;
2391 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2392 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2394 UCHAR TableSize = 0;
2395 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2396 TX_STA_CNT1_STRUC StaTx1;
2397 TX_STA_CNT0_STRUC TxStaCnt0;
2399 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2400 MAC_TABLE_ENTRY *pEntry;
2403 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2406 // walk through MAC table, see if need to change AP's TX rate toward each entry
2408 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2410 pEntry = &pAd->MacTab.Content[i];
2412 // check if this entry need to switch rate automatically
2413 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2416 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2417 if (pAd->Antenna.field.TxPath > 1)
2418 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2420 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2422 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2424 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2426 // decide the next upgrade rate and downgrade rate, if any
2427 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2429 UpRateIdx = CurrRateIdx + 1;
2430 DownRateIdx = CurrRateIdx -1;
2432 else if (CurrRateIdx == 0)
2434 UpRateIdx = CurrRateIdx + 1;
2435 DownRateIdx = CurrRateIdx;
2437 else if (CurrRateIdx == (TableSize - 1))
2439 UpRateIdx = CurrRateIdx;
2440 DownRateIdx = CurrRateIdx - 1;
2443 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2445 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2447 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2448 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2452 TrainUp = pCurrTxRate->TrainUp;
2453 TrainDown = pCurrTxRate->TrainDown;
2456 if (pAd->MacTab.Size == 1)
2458 // Update statistic counter
2459 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2460 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2462 TxRetransmit = StaTx1.field.TxRetransmit;
2463 TxSuccess = StaTx1.field.TxSuccess;
2464 TxFailCount = TxStaCnt0.field.TxFailCount;
2465 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2467 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2468 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2469 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2470 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2471 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2472 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2475 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2479 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2480 pEntry->OneSecTxRetryOkCount +
2481 pEntry->OneSecTxFailCount;
2484 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2489 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2490 // (criteria copied from RT2500 for Netopia case)
2492 if (TxTotalCnt <= 12)
2494 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2495 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2497 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2499 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2500 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2502 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2504 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2507 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2513 ULONG OneSecTxNoRetryOKRationCount;
2515 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2520 // downgrade TX quality if PER >= Rate-Down threshold
2521 if (TxErrorRatio >= TrainDown)
2523 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2526 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2528 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2530 // perform DRS - consider TxRate Down first, then rate up.
2531 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2533 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2535 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2536 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2541 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2543 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2547 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2549 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2554 // if rate-up happen, clear all bad history of all TX rates
2555 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2557 pAd->DrsCounters.TxRateUpPenalty = 0;
2558 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2559 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2561 // if rate-down happen, only clear DownRate's bad history
2562 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2564 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2566 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2567 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2568 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2572 bTxRateChanged = FALSE;
2575 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2576 if (bTxRateChanged && pNextTxRate)
2578 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2584 ==========================================================================
2586 This routine is executed periodically inside MlmePeriodicExec() after
2587 association with an AP.
2588 It checks if StaCfg.Psm is consistent with user policy (recorded in
2589 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2590 there're some conditions to consider:
2591 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2592 the time when Mibss==TRUE
2593 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2594 if outgoing traffic available in TxRing or MgmtRing.
2596 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2598 IRQL = DISPATCH_LEVEL
2600 ==========================================================================
2602 VOID MlmeCheckPsmChange(
2603 IN PRTMP_ADAPTER pAd,
2609 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2610 // 2. user wants either MAX_PSP or FAST_PSP
2611 // 3. but current psm is not in PWR_SAVE
2612 // 4. CNTL state machine is not doing SCANning
2613 // 5. no TX SUCCESS event for the past 1-sec period
2614 #ifdef NDIS51_MINIPORT
2615 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2616 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2619 PowerMode = pAd->StaCfg.WindowsPowerMode;
2621 if (INFRA_ON(pAd) &&
2622 (PowerMode != Ndis802_11PowerModeCAM) &&
2623 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2624 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2626 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2627 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2628 MlmeSetPsmBit(pAd, PWR_SAVE);
2629 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2631 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2635 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2640 // IRQL = PASSIVE_LEVEL
2641 // IRQL = DISPATCH_LEVEL
2643 IN PRTMP_ADAPTER pAd,
2646 AUTO_RSP_CFG_STRUC csr4;
2648 pAd->StaCfg.Psm = psm;
2649 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2650 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2651 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2652 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2655 // IRQL = DISPATCH_LEVEL
2656 VOID MlmeSetTxPreamble(
2657 IN PRTMP_ADAPTER pAd,
2658 IN USHORT TxPreamble)
2660 AUTO_RSP_CFG_STRUC csr4;
2663 // Always use Long preamble before verifiation short preamble functionality works well.
2664 // Todo: remove the following line if short preamble functionality works
2666 //TxPreamble = Rt802_11PreambleLong;
2668 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2669 if (TxPreamble == Rt802_11PreambleLong)
2671 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2672 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2673 csr4.field.AutoResponderPreamble = 0;
2677 // NOTE: 1Mbps should always use long preamble
2678 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2679 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2680 csr4.field.AutoResponderPreamble = 1;
2683 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2687 ==========================================================================
2689 Update basic rate bitmap
2690 ==========================================================================
2693 VOID UpdateBasicRateBitmap(
2694 IN PRTMP_ADAPTER pAdapter)
2697 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2698 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2699 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2700 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2701 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2704 /* if A mode, always use fix BasicRateBitMap */
2705 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2706 if (pAdapter->CommonCfg.Channel > 14)
2707 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2710 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2712 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2716 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2722 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2724 if (bitmap & (1 << i))
2726 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2728 if (sup_p[j] == rate[i])
2733 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2735 if (ext_p[j] == rate[i])
2741 } /* End of UpdateBasicRateBitmap */
2743 // IRQL = PASSIVE_LEVEL
2744 // IRQL = DISPATCH_LEVEL
2745 // bLinkUp is to identify the inital link speed.
2746 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2747 VOID MlmeUpdateTxRates(
2748 IN PRTMP_ADAPTER pAd,
2753 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2754 UCHAR MinSupport = RATE_54;
2755 ULONG BasicRateBitmap = 0;
2756 UCHAR CurrBasicRate = RATE_1;
2757 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2758 PHTTRANSMIT_SETTING pHtPhy = NULL;
2759 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2760 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2761 BOOLEAN *auto_rate_cur_p;
2762 UCHAR HtMcs = MCS_AUTO;
2764 // find max desired rate
2765 UpdateBasicRateBitmap(pAd);
2768 auto_rate_cur_p = NULL;
2769 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2771 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2773 case 2: Rate = RATE_1; num++; break;
2774 case 4: Rate = RATE_2; num++; break;
2775 case 11: Rate = RATE_5_5; num++; break;
2776 case 22: Rate = RATE_11; num++; break;
2777 case 12: Rate = RATE_6; num++; break;
2778 case 18: Rate = RATE_9; num++; break;
2779 case 24: Rate = RATE_12; num++; break;
2780 case 36: Rate = RATE_18; num++; break;
2781 case 48: Rate = RATE_24; num++; break;
2782 case 72: Rate = RATE_36; num++; break;
2783 case 96: Rate = RATE_48; num++; break;
2784 case 108: Rate = RATE_54; num++; break;
2785 //default: Rate = RATE_1; break;
2787 if (MaxDesire < Rate) MaxDesire = Rate;
2790 //===========================================================================
2791 //===========================================================================
2793 pHtPhy = &pAd->StaCfg.HTPhyMode;
2794 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2795 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2797 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2798 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2800 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2801 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2802 (MaxDesire > RATE_11))
2804 MaxDesire = RATE_11;
2808 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2809 pMinHtPhy->word = 0;
2810 pMaxHtPhy->word = 0;
2813 // Auto rate switching is enabled only if more than one DESIRED RATES are
2814 // specified; otherwise disabled
2817 *auto_rate_cur_p = FALSE;
2821 *auto_rate_cur_p = TRUE;
2825 if (HtMcs != MCS_AUTO)
2827 *auto_rate_cur_p = FALSE;
2831 *auto_rate_cur_p = TRUE;
2835 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2837 pSupRate = &pAd->StaActive.SupRate[0];
2838 pExtRate = &pAd->StaActive.ExtRate[0];
2839 SupRateLen = pAd->StaActive.SupRateLen;
2840 ExtRateLen = pAd->StaActive.ExtRateLen;
2844 pSupRate = &pAd->CommonCfg.SupRate[0];
2845 pExtRate = &pAd->CommonCfg.ExtRate[0];
2846 SupRateLen = pAd->CommonCfg.SupRateLen;
2847 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2850 // find max supported rate
2851 for (i=0; i<SupRateLen; i++)
2853 switch (pSupRate[i] & 0x7f)
2855 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2856 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2857 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2858 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2859 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2860 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2861 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2862 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2863 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2864 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2865 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2866 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2867 default: Rate = RATE_1; break;
2869 if (MaxSupport < Rate) MaxSupport = Rate;
2871 if (MinSupport > Rate) MinSupport = Rate;
2874 for (i=0; i<ExtRateLen; i++)
2876 switch (pExtRate[i] & 0x7f)
2878 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2879 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2880 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2881 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2882 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2883 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2884 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2885 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2886 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2887 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2888 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2889 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2890 default: Rate = RATE_1; break;
2892 if (MaxSupport < Rate) MaxSupport = Rate;
2894 if (MinSupport > Rate) MinSupport = Rate;
2897 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2899 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2900 // the DURATION field of outgoing uniicast DATA/MGMT frame
2901 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2903 if (BasicRateBitmap & (0x01 << i))
2904 CurrBasicRate = (UCHAR)i;
2905 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2908 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2909 // max tx rate = min {max desire rate, max supported rate}
2910 if (MaxSupport < MaxDesire)
2911 pAd->CommonCfg.MaxTxRate = MaxSupport;
2913 pAd->CommonCfg.MaxTxRate = MaxDesire;
2915 pAd->CommonCfg.MinTxRate = MinSupport;
2916 if (*auto_rate_cur_p)
2920 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2922 if (bLinkUp == TRUE)
2923 pAd->CommonCfg.TxRate = RATE_24;
2925 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2928 pAd->CommonCfg.TxRate = RATE_11;
2930 pAd->CommonCfg.TxRate = RATE_24;
2932 // should never exceed MaxTxRate (consider 11B-only mode)
2933 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2934 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2936 pAd->CommonCfg.TxRateIndex = 0;
2940 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2941 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2942 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2944 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2945 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2946 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2947 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
2950 if (pAd->CommonCfg.TxRate <= RATE_11)
2952 pMaxHtPhy->field.MODE = MODE_CCK;
2953 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
2954 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
2958 pMaxHtPhy->field.MODE = MODE_OFDM;
2959 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
2960 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
2961 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
2963 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
2966 pHtPhy->word = (pMaxHtPhy->word);
2967 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
2969 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
2970 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
2971 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
2975 switch (pAd->CommonCfg.PhyMode)
2977 case PHY_11BG_MIXED:
2979 case PHY_11BGN_MIXED:
2980 pAd->CommonCfg.MlmeRate = RATE_1;
2981 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
2982 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
2983 pAd->CommonCfg.RtsRate = RATE_11;
2987 case PHY_11AGN_MIXED:
2988 case PHY_11GN_MIXED:
2990 case PHY_11AN_MIXED:
2992 pAd->CommonCfg.MlmeRate = RATE_6;
2993 pAd->CommonCfg.RtsRate = RATE_6;
2994 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2995 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2997 case PHY_11ABG_MIXED:
2998 case PHY_11ABGN_MIXED:
2999 if (pAd->CommonCfg.Channel <= 14)
3001 pAd->CommonCfg.MlmeRate = RATE_1;
3002 pAd->CommonCfg.RtsRate = RATE_1;
3003 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3004 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3008 pAd->CommonCfg.MlmeRate = RATE_6;
3009 pAd->CommonCfg.RtsRate = RATE_6;
3010 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3011 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3015 pAd->CommonCfg.MlmeRate = RATE_6;
3016 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3017 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3018 pAd->CommonCfg.RtsRate = RATE_1;
3022 // Keep Basic Mlme Rate.
3024 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3025 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3026 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3028 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3029 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3032 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3033 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3034 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3035 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3036 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3037 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3038 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 ));
3042 ==========================================================================
3044 This function update HT Rate setting.
3045 Input Wcid value is valid for 2 case :
3046 1. it's used for Station in infra mode that copy AP rate to Mactable.
3047 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3049 IRQL = DISPATCH_LEVEL
3051 ==========================================================================
3053 VOID MlmeUpdateHtTxRates(
3054 IN PRTMP_ADAPTER pAd,
3057 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3059 RT_HT_CAPABILITY *pRtHtCap = NULL;
3060 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3063 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3064 PHTTRANSMIT_SETTING pHtPhy = NULL;
3065 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3066 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3067 BOOLEAN *auto_rate_cur_p;
3069 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3071 auto_rate_cur_p = NULL;
3074 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3075 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3076 pHtPhy = &pAd->StaCfg.HTPhyMode;
3077 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3078 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3080 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3083 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3085 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3088 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3089 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3090 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3091 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3092 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3093 pMaxHtPhy->field.STBC = STBC_USE;
3095 pMaxHtPhy->field.STBC = STBC_NONE;
3099 if (pDesireHtPhy->bHtEnable == FALSE)
3102 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3103 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3104 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3105 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3106 pMaxHtPhy->field.STBC = STBC_USE;
3108 pMaxHtPhy->field.STBC = STBC_NONE;
3111 // Decide MAX ht rate.
3112 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3113 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3115 pMaxHtPhy->field.MODE = MODE_HTMIX;
3117 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3118 pMaxHtPhy->field.BW = BW_40;
3120 pMaxHtPhy->field.BW = BW_20;
3122 if (pMaxHtPhy->field.BW == BW_20)
3123 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3125 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3127 for (i=23; i>=0; i--) // 3*3
3130 bitmask = (1<<(i-(j*8)));
3132 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3134 pMaxHtPhy->field.MCS = i;
3142 // Copy MIN ht rate. rt2860???
3143 pMinHtPhy->field.BW = BW_20;
3144 pMinHtPhy->field.MCS = 0;
3145 pMinHtPhy->field.STBC = 0;
3146 pMinHtPhy->field.ShortGI = 0;
3147 //If STA assigns fixed rate. update to fixed here.
3148 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3150 if (pDesireHtPhy->MCSSet[4] != 0)
3152 pMaxHtPhy->field.MCS = 32;
3153 pMinHtPhy->field.MCS = 32;
3154 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3157 for (i=23; (CHAR)i >= 0; i--) // 3*3
3160 bitmask = (1<<(i-(j*8)));
3161 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3163 pMaxHtPhy->field.MCS = i;
3164 pMinHtPhy->field.MCS = i;
3173 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3174 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3175 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3176 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3177 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3179 // use default now. rt2860
3180 if (pDesireHtPhy->MCSSet[0] != 0xff)
3181 *auto_rate_cur_p = FALSE;
3183 *auto_rate_cur_p = TRUE;
3185 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3186 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3187 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3188 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3191 // IRQL = DISPATCH_LEVEL
3193 IN PRTMP_ADAPTER pAd)
3195 RT28XX_MLME_RADIO_OFF(pAd);
3198 // IRQL = DISPATCH_LEVEL
3200 IN PRTMP_ADAPTER pAd)
3202 RT28XX_MLME_RADIO_ON(pAd);
3205 // ===========================================================================================
3207 // ===========================================================================================
3210 /*! \brief initialize BSS table
3211 * \param p_tab pointer to the table
3216 IRQL = PASSIVE_LEVEL
3217 IRQL = DISPATCH_LEVEL
3226 Tab->BssOverlapNr = 0;
3227 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3229 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3230 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3235 IN PRTMP_ADAPTER pAd,
3240 Tab->numAsOriginator = 0;
3241 Tab->numAsRecipient = 0;
3242 NdisAllocateSpinLock(&pAd->BATabLock);
3243 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3245 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3246 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3248 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3250 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3254 /*! \brief search the BSS table by SSID
3255 * \param p_tab pointer to the bss table
3256 * \param ssid SSID string
3257 * \return index of the table, BSS_NOT_FOUND if not in the table
3260 * \note search by sequential search
3262 IRQL = DISPATCH_LEVEL
3265 ULONG BssTableSearch(
3272 for (i = 0; i < Tab->BssNr; i++)
3275 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3276 // We should distinguish this case.
3278 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3279 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3280 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3285 return (ULONG)BSS_NOT_FOUND;
3288 ULONG BssSsidTableSearch(
3297 for (i = 0; i < Tab->BssNr; i++)
3300 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3301 // We should distinguish this case.
3303 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3304 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3305 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3306 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3311 return (ULONG)BSS_NOT_FOUND;
3314 ULONG BssTableSearchWithSSID(
3323 for (i = 0; i < Tab->BssNr; i++)
3325 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3326 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3327 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3328 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3329 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3330 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3335 return (ULONG)BSS_NOT_FOUND;
3338 // IRQL = DISPATCH_LEVEL
3339 VOID BssTableDeleteEntry(
3340 IN OUT BSS_TABLE *Tab,
3346 for (i = 0; i < Tab->BssNr; i++)
3348 if ((Tab->BssEntry[i].Channel == Channel) &&
3349 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3351 for (j = i; j < Tab->BssNr - 1; j++)
3353 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3355 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3363 ========================================================================
3364 Routine Description:
3365 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3368 // IRQL = DISPATCH_LEVEL
3369 ========================================================================
3371 VOID BATableDeleteORIEntry(
3372 IN OUT PRTMP_ADAPTER pAd,
3373 IN BA_ORI_ENTRY *pBAORIEntry)
3376 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3378 NdisAcquireSpinLock(&pAd->BATabLock);
3379 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3381 pAd->BATable.numAsOriginator -= 1;
3382 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3383 // Erase Bitmap flag.
3385 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3386 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3387 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3388 pBAORIEntry->Token = 1;
3389 // Not clear Sequence here.
3390 NdisReleaseSpinLock(&pAd->BATabLock);
3400 IRQL = DISPATCH_LEVEL
3404 IN PRTMP_ADAPTER pAd,
3405 OUT BSS_ENTRY *pBss,
3410 IN USHORT BeaconPeriod,
3411 IN PCF_PARM pCfParm,
3413 IN USHORT CapabilityInfo,
3415 IN UCHAR SupRateLen,
3417 IN UCHAR ExtRateLen,
3418 IN HT_CAPABILITY_IE *pHtCapability,
3419 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3420 IN UCHAR HtCapabilityLen,
3421 IN UCHAR AddHtInfoLen,
3422 IN UCHAR NewExtChanOffset,
3425 IN LARGE_INTEGER TimeStamp,
3427 IN PEDCA_PARM pEdcaParm,
3428 IN PQOS_CAPABILITY_PARM pQosCapability,
3429 IN PQBSS_LOAD_PARM pQbssLoad,
3430 IN USHORT LengthVIE,
3431 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3433 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3434 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3438 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3439 // Or send beacon /probe response with SSID len matching real SSID length,
3440 // but SSID is all zero. such as "00-00-00-00" with length 4.
3441 // We have to prevent this case overwrite correct table
3442 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3444 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3445 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3446 pBss->SsidLen = SsidLen;
3452 pBss->BssType = BssType;
3453 pBss->BeaconPeriod = BeaconPeriod;
3454 if (BssType == BSS_INFRA)
3456 if (pCfParm->bValid)
3458 pBss->CfpCount = pCfParm->CfpCount;
3459 pBss->CfpPeriod = pCfParm->CfpPeriod;
3460 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3461 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3466 pBss->AtimWin = AtimWin;
3469 pBss->CapabilityInfo = CapabilityInfo;
3470 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3471 // Combine with AuthMode, they will decide the connection methods.
3472 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3473 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3474 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3475 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3477 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3478 pBss->SupRateLen = SupRateLen;
3479 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3480 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3481 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3482 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3483 pBss->NewExtChanOffset = NewExtChanOffset;
3484 pBss->ExtRateLen = ExtRateLen;
3485 pBss->Channel = Channel;
3486 pBss->CentralChannel = Channel;
3488 // Update CkipFlag. if not exists, the value is 0x0
3489 pBss->CkipFlag = CkipFlag;
3491 // New for microsoft Fixed IEs
3492 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3493 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3494 pBss->FixIEs.Capabilities = CapabilityInfo;
3496 // New for microsoft Variable IEs
3499 pBss->VarIELen = LengthVIE;
3500 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3507 pBss->AddHtInfoLen = 0;
3508 pBss->HtCapabilityLen = 0;
3510 if (HtCapabilityLen> 0)
3512 pBss->HtCapabilityLen = HtCapabilityLen;
3513 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3514 if (AddHtInfoLen > 0)
3516 pBss->AddHtInfoLen = AddHtInfoLen;
3517 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3519 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3521 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3523 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3525 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3530 BssCipherParse(pBss);
3534 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3536 pBss->EdcaParm.bValid = FALSE;
3538 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3540 pBss->QosCapability.bValid = FALSE;
3542 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3544 pBss->QbssLoad.bValid = FALSE;
3551 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3552 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3554 pEid = (PEID_STRUCT) pVIE;
3556 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3561 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3563 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3565 pBss->WpaIE.IELen = 0;
3568 pBss->WpaIE.IELen = pEid->Len + 2;
3569 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3573 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3575 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3577 pBss->RsnIE.IELen = 0;
3580 pBss->RsnIE.IELen = pEid->Len + 2;
3581 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3585 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3586 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3592 * \brief insert an entry into the bss table
3593 * \param p_tab The BSS table
3594 * \param Bssid BSSID
3596 * \param ssid_len Length of SSID
3598 * \param beacon_period
3605 * \param channel_idx
3609 * \note If SSID is identical, the old entry will be replaced by the new one
3611 IRQL = DISPATCH_LEVEL
3614 ULONG BssTableSetEntry(
3615 IN PRTMP_ADAPTER pAd,
3621 IN USHORT BeaconPeriod,
3624 IN USHORT CapabilityInfo,
3626 IN UCHAR SupRateLen,
3628 IN UCHAR ExtRateLen,
3629 IN HT_CAPABILITY_IE *pHtCapability,
3630 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3631 IN UCHAR HtCapabilityLen,
3632 IN UCHAR AddHtInfoLen,
3633 IN UCHAR NewExtChanOffset,
3636 IN LARGE_INTEGER TimeStamp,
3638 IN PEDCA_PARM pEdcaParm,
3639 IN PQOS_CAPABILITY_PARM pQosCapability,
3640 IN PQBSS_LOAD_PARM pQbssLoad,
3641 IN USHORT LengthVIE,
3642 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3646 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3647 if (Idx == BSS_NOT_FOUND)
3649 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3652 // It may happen when BSS Table was full.
3653 // The desired AP will not be added into BSS Table
3654 // In this case, if we found the desired AP then overwrite BSS Table.
3656 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3658 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3659 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3661 Idx = Tab->BssOverlapNr;
3662 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3663 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3664 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3665 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3671 return BSS_NOT_FOUND;
3675 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3676 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3677 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3682 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3683 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3684 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3690 // IRQL = DISPATCH_LEVEL
3691 VOID BssTableSsidSort(
3692 IN PRTMP_ADAPTER pAd,
3693 OUT BSS_TABLE *OutTab,
3698 BssTableInit(OutTab);
3700 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3702 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3703 BOOLEAN bIsHiddenApIncluded = FALSE;
3705 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3706 (pAd->MlmeAux.Channel > 14) &&
3707 RadarChannelCheck(pAd, pInBss->Channel))
3711 bIsHiddenApIncluded = TRUE;
3714 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3715 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3717 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3719 // 2.4G/5G N only mode
3720 if ((pInBss->HtCapabilityLen == 0) &&
3721 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3723 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3728 // Check the Authmode first
3729 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3731 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3732 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3736 // Check cipher suite, AP must have more secured cipher than station setting
3737 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3739 // If it's not mixed mode, we should only let BSS pass with the same encryption
3740 if (pInBss->WPA.bMixMode == FALSE)
3741 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3744 // check group cipher
3745 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3746 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3747 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3750 // check pairwise cipher, skip if none matched
3751 // If profile set to AES, let it pass without question.
3752 // If profile set to TKIP, we must find one mateched
3753 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3754 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3755 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3758 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3760 // If it's not mixed mode, we should only let BSS pass with the same encryption
3761 if (pInBss->WPA2.bMixMode == FALSE)
3762 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3765 // check group cipher
3766 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3767 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3768 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3771 // check pairwise cipher, skip if none matched
3772 // If profile set to AES, let it pass without question.
3773 // If profile set to TKIP, we must find one mateched
3774 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3775 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3776 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3780 // Bss Type matched, SSID matched.
3781 // We will check wepstatus for qualification Bss
3782 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3784 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3786 // For the SESv2 case, we will not qualify WepStatus.
3792 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3793 // It definitely will fail. So, skip it.
3794 // CCX also require not even try to connect it!!
3798 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3799 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3800 if ((pInBss->CentralChannel != pInBss->Channel) &&
3801 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3803 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3805 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3807 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3811 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3818 // copy matching BSS from InTab to OutTab
3819 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3823 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3825 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3827 // 2.4G/5G N only mode
3828 if ((pInBss->HtCapabilityLen == 0) &&
3829 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3831 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3836 // Check the Authmode first
3837 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3839 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3840 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3844 // Check cipher suite, AP must have more secured cipher than station setting
3845 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3847 // If it's not mixed mode, we should only let BSS pass with the same encryption
3848 if (pInBss->WPA.bMixMode == FALSE)
3849 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3852 // check group cipher
3853 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3856 // check pairwise cipher, skip if none matched
3857 // If profile set to AES, let it pass without question.
3858 // If profile set to TKIP, we must find one mateched
3859 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3860 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3861 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3864 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3866 // If it's not mixed mode, we should only let BSS pass with the same encryption
3867 if (pInBss->WPA2.bMixMode == FALSE)
3868 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3871 // check group cipher
3872 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3875 // check pairwise cipher, skip if none matched
3876 // If profile set to AES, let it pass without question.
3877 // If profile set to TKIP, we must find one mateched
3878 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3879 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3880 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3884 // Bss Type matched, SSID matched.
3885 // We will check wepstatus for qualification Bss
3886 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3889 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3890 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3891 if ((pInBss->CentralChannel != pInBss->Channel) &&
3892 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3894 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3896 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3898 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3902 // copy matching BSS from InTab to OutTab
3903 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3908 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3912 BssTableSortByRssi(OutTab);
3916 // IRQL = DISPATCH_LEVEL
3917 VOID BssTableSortByRssi(
3918 IN OUT BSS_TABLE *OutTab)
3923 for (i = 0; i < OutTab->BssNr - 1; i++)
3925 for (j = i+1; j < OutTab->BssNr; j++)
3927 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
3929 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
3930 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
3931 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
3937 VOID BssCipherParse(
3938 IN OUT PBSS_ENTRY pBss)
3942 PRSN_IE_HEADER_STRUCT pRsnHeader;
3943 PCIPHER_SUITE_STRUCT pCipher;
3944 PAKM_SUITE_STRUCT pAKM;
3947 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
3950 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
3954 pBss->WepStatus = Ndis802_11WEPEnabled;
3958 pBss->WepStatus = Ndis802_11WEPDisabled;
3960 // Set default to disable & open authentication before parsing variable IE
3961 pBss->AuthMode = Ndis802_11AuthModeOpen;
3962 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
3965 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
3966 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
3967 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
3968 pBss->WPA.RsnCapability = 0;
3969 pBss->WPA.bMixMode = FALSE;
3971 // Init WPA2 setting
3972 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
3973 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
3974 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
3975 pBss->WPA2.RsnCapability = 0;
3976 pBss->WPA2.bMixMode = FALSE;
3979 Length = (INT) pBss->VarIELen;
3983 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
3984 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
3985 pEid = (PEID_STRUCT) pTmp;
3989 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
3990 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
3996 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
3997 pBss->WepStatus = Ndis802_11Encryption1Enabled;
3998 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
3999 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4002 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4003 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4004 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4007 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4008 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4009 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4015 // if Cisco IE_WPA, break
4018 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4023 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4025 // if unsupported vendor specific IE
4028 // Skip OUI, version, and multicast suite
4029 // This part should be improved in the future when AP supported multiple cipher suite.
4030 // For now, it's OK since almost all APs have fixed cipher suite supported.
4031 // pTmp = (PUCHAR) pEid->Octet;
4034 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4042 // Parse group cipher
4046 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4049 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4052 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4055 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4060 // number of unicast suite
4063 // skip all unicast cipher suites
4064 //Count = *(PUSHORT) pTmp;
4065 Count = (pTmp[1]<<8) + pTmp[0];
4066 pTmp += sizeof(USHORT);
4068 // Parsing all unicast cipher suite
4073 TmpCipher = Ndis802_11WEPDisabled;
4077 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4078 TmpCipher = Ndis802_11Encryption1Enabled;
4081 TmpCipher = Ndis802_11Encryption2Enabled;
4084 TmpCipher = Ndis802_11Encryption3Enabled;
4089 if (TmpCipher > pBss->WPA.PairCipher)
4091 // Move the lower cipher suite to PairCipherAux
4092 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4093 pBss->WPA.PairCipher = TmpCipher;
4097 pBss->WPA.PairCipherAux = TmpCipher;
4103 // 4. get AKM suite counts
4104 //Count = *(PUSHORT) pTmp;
4105 Count = (pTmp[1]<<8) + pTmp[0];
4106 pTmp += sizeof(USHORT);
4112 // Set AP support WPA mode
4113 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4114 pBss->AuthMode = Ndis802_11AuthModeWPA;
4116 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4119 // Set AP support WPA mode
4120 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4121 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4123 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4130 // Fixed for WPA-None
4131 if (pBss->BssType == BSS_ADHOC)
4133 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4134 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4135 pBss->WepStatus = pBss->WPA.GroupCipher;
4136 // Patched bugs for old driver
4137 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4138 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4141 pBss->WepStatus = pBss->WPA.PairCipher;
4143 // Check the Pair & Group, if different, turn on mixed mode flag
4144 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4145 pBss->WPA.bMixMode = TRUE;
4150 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4152 // 0. Version must be 1
4153 if (le2cpu16(pRsnHeader->Version) != 1)
4155 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4157 // 1. Check group cipher
4158 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4159 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4162 // Parse group cipher
4163 switch (pCipher->Type)
4166 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4169 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4172 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4175 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4180 // set to correct offset for next parsing
4181 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4183 // 2. Get pairwise cipher counts
4184 //Count = *(PUSHORT) pTmp;
4185 Count = (pTmp[1]<<8) + pTmp[0];
4186 pTmp += sizeof(USHORT);
4188 // 3. Get pairwise cipher
4189 // Parsing all unicast cipher suite
4193 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4194 TmpCipher = Ndis802_11WEPDisabled;
4195 switch (pCipher->Type)
4198 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4199 TmpCipher = Ndis802_11Encryption1Enabled;
4202 TmpCipher = Ndis802_11Encryption2Enabled;
4205 TmpCipher = Ndis802_11Encryption3Enabled;
4210 if (TmpCipher > pBss->WPA2.PairCipher)
4212 // Move the lower cipher suite to PairCipherAux
4213 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4214 pBss->WPA2.PairCipher = TmpCipher;
4218 pBss->WPA2.PairCipherAux = TmpCipher;
4220 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4224 // 4. get AKM suite counts
4225 //Count = *(PUSHORT) pTmp;
4226 Count = (pTmp[1]<<8) + pTmp[0];
4227 pTmp += sizeof(USHORT);
4229 // 5. Get AKM ciphers
4230 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4231 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4237 // Set AP support WPA mode
4238 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4239 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4241 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4244 // Set AP support WPA mode
4245 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4246 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4248 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4253 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4255 // Fixed for WPA-None
4256 if (pBss->BssType == BSS_ADHOC)
4258 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4259 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4260 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4261 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4262 pBss->WepStatus = pBss->WPA.GroupCipher;
4263 // Patched bugs for old driver
4264 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4265 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4267 pBss->WepStatus = pBss->WPA2.PairCipher;
4269 // 6. Get RSN capability
4270 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4271 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4272 pTmp += sizeof(USHORT);
4274 // Check the Pair & Group, if different, turn on mixed mode flag
4275 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4276 pBss->WPA2.bMixMode = TRUE;
4282 Length -= (pEid->Len + 2);
4286 // ===========================================================================================
4288 // ===========================================================================================
4290 /*! \brief generates a random mac address value for IBSS BSSID
4291 * \param Addr the bssid location
4296 VOID MacAddrRandomBssid(
4297 IN PRTMP_ADAPTER pAd,
4302 for (i = 0; i < MAC_ADDR_LEN; i++)
4304 pAddr[i] = RandomByte(pAd);
4307 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4310 /*! \brief init the management mac frame header
4311 * \param p_hdr mac header
4312 * \param subtype subtype of the frame
4313 * \param p_ds destination address, don't care if it is a broadcast address
4315 * \pre the station has the following information in the pAd->StaCfg
4319 * \note this function initializes the following field
4321 IRQL = PASSIVE_LEVEL
4322 IRQL = DISPATCH_LEVEL
4325 VOID MgtMacHeaderInit(
4326 IN PRTMP_ADAPTER pAd,
4327 IN OUT PHEADER_802_11 pHdr80211,
4333 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4335 pHdr80211->FC.Type = BTYPE_MGMT;
4336 pHdr80211->FC.SubType = SubType;
4337 pHdr80211->FC.ToDs = ToDs;
4338 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4340 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4342 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4345 // ===========================================================================================
4347 // ===========================================================================================
4349 /*!***************************************************************************
4350 * This routine build an outgoing frame, and fill all information specified
4351 * in argument list to the frame body. The actual frame size is the summation
4354 * Buffer - pointer to a pre-allocated memory segment
4355 * args - a list of <int arg_size, arg> pairs.
4356 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4357 * function will FAIL!!!
4359 * Size of the buffer
4361 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4363 IRQL = PASSIVE_LEVEL
4364 IRQL = DISPATCH_LEVEL
4366 ****************************************************************************/
4367 ULONG MakeOutgoingFrame(
4369 OUT ULONG *FrameLen, ...)
4376 // calculates the total length
4378 va_start(Args, FrameLen);
4381 leng = va_arg(Args, int);
4382 if (leng == END_OF_ARGS)
4386 p = va_arg(Args, PVOID);
4387 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4388 TotLeng = TotLeng + leng;
4391 va_end(Args); /* clean up */
4392 *FrameLen = TotLeng;
4396 // ===========================================================================================
4398 // ===========================================================================================
4400 /*! \brief Initialize The MLME Queue, used by MLME Functions
4401 * \param *Queue The MLME Queue
4402 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4405 * \note Because this is done only once (at the init stage), no need to be locked
4407 IRQL = PASSIVE_LEVEL
4410 NDIS_STATUS MlmeQueueInit(
4411 IN MLME_QUEUE *Queue)
4415 NdisAllocateSpinLock(&Queue->Lock);
4421 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4423 Queue->Entry[i].Occupied = FALSE;
4424 Queue->Entry[i].MsgLen = 0;
4425 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4428 return NDIS_STATUS_SUCCESS;
4431 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4432 * \param *Queue The MLME Queue
4433 * \param Machine The State Machine Id
4434 * \param MsgType The Message Type
4435 * \param MsgLen The Message length
4436 * \param *Msg The message pointer
4437 * \return TRUE if enqueue is successful, FALSE if the queue is full
4440 * \note The message has to be initialized
4442 IRQL = PASSIVE_LEVEL
4443 IRQL = DISPATCH_LEVEL
4446 BOOLEAN MlmeEnqueue(
4447 IN PRTMP_ADAPTER pAd,
4454 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4456 // Do nothing if the driver is starting halt state.
4457 // This might happen when timer already been fired before cancel timer with mlmehalt
4458 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4461 // First check the size, it MUST not exceed the mlme queue size
4462 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4464 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4468 if (MlmeQueueFull(Queue))
4473 NdisAcquireSpinLock(&(Queue->Lock));
4477 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4482 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4483 Queue->Entry[Tail].Occupied = TRUE;
4484 Queue->Entry[Tail].Machine = Machine;
4485 Queue->Entry[Tail].MsgType = MsgType;
4486 Queue->Entry[Tail].MsgLen = MsgLen;
4490 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4493 NdisReleaseSpinLock(&(Queue->Lock));
4497 /*! \brief This function is used when Recv gets a MLME message
4498 * \param *Queue The MLME Queue
4499 * \param TimeStampHigh The upper 32 bit of timestamp
4500 * \param TimeStampLow The lower 32 bit of timestamp
4501 * \param Rssi The receiving RSSI strength
4502 * \param MsgLen The length of the message
4503 * \param *Msg The message pointer
4504 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4508 IRQL = DISPATCH_LEVEL
4511 BOOLEAN MlmeEnqueueForRecv(
4512 IN PRTMP_ADAPTER pAd,
4514 IN ULONG TimeStampHigh,
4515 IN ULONG TimeStampLow,
4524 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4526 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4528 // Do nothing if the driver is starting halt state.
4529 // This might happen when timer already been fired before cancel timer with mlmehalt
4530 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4532 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4536 // First check the size, it MUST not exceed the mlme queue size
4537 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4539 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4543 if (MlmeQueueFull(Queue))
4549 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4551 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4556 // OK, we got all the informations, it is time to put things into queue
4557 NdisAcquireSpinLock(&(Queue->Lock));
4561 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4565 Queue->Entry[Tail].Occupied = TRUE;
4566 Queue->Entry[Tail].Machine = Machine;
4567 Queue->Entry[Tail].MsgType = MsgType;
4568 Queue->Entry[Tail].MsgLen = MsgLen;
4569 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4570 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4571 Queue->Entry[Tail].Rssi0 = Rssi0;
4572 Queue->Entry[Tail].Rssi1 = Rssi1;
4573 Queue->Entry[Tail].Rssi2 = Rssi2;
4574 Queue->Entry[Tail].Signal = Signal;
4575 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4577 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4581 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4584 NdisReleaseSpinLock(&(Queue->Lock));
4586 RT28XX_MLME_HANDLER(pAd);
4592 /*! \brief Dequeue a message from the MLME Queue
4593 * \param *Queue The MLME Queue
4594 * \param *Elem The message dequeued from MLME Queue
4595 * \return TRUE if the Elem contains something, FALSE otherwise
4599 IRQL = DISPATCH_LEVEL
4602 BOOLEAN MlmeDequeue(
4603 IN MLME_QUEUE *Queue,
4604 OUT MLME_QUEUE_ELEM **Elem)
4606 NdisAcquireSpinLock(&(Queue->Lock));
4607 *Elem = &(Queue->Entry[Queue->Head]);
4610 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4614 NdisReleaseSpinLock(&(Queue->Lock));
4618 // IRQL = DISPATCH_LEVEL
4619 VOID MlmeRestartStateMachine(
4620 IN PRTMP_ADAPTER pAd)
4622 MLME_QUEUE_ELEM *Elem = NULL;
4625 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4627 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4628 if(pAd->Mlme.bRunning)
4630 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4635 pAd->Mlme.bRunning = TRUE;
4637 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4639 // Remove all Mlme queues elements
4640 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4642 //From message type, determine which state machine I should drive
4643 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4645 // free MLME element
4646 Elem->Occupied = FALSE;
4651 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4656 // Cancel all timer events
4657 // Be careful to cancel new added timer
4658 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4659 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4660 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4661 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4662 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4663 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4666 // Change back to original channel in case of doing scan
4667 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4668 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4670 // Resume MSDU which is turned off durning scan
4671 RTMPResumeMsduTransmission(pAd);
4674 // Set all state machines back IDLE
4675 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4676 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4677 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4678 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4679 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4680 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4683 // Remove running state
4684 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4685 pAd->Mlme.bRunning = FALSE;
4686 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4689 /*! \brief test if the MLME Queue is empty
4690 * \param *Queue The MLME Queue
4691 * \return TRUE if the Queue is empty, FALSE otherwise
4695 IRQL = DISPATCH_LEVEL
4698 BOOLEAN MlmeQueueEmpty(
4699 IN MLME_QUEUE *Queue)
4703 NdisAcquireSpinLock(&(Queue->Lock));
4704 Ans = (Queue->Num == 0);
4705 NdisReleaseSpinLock(&(Queue->Lock));
4710 /*! \brief test if the MLME Queue is full
4711 * \param *Queue The MLME Queue
4712 * \return TRUE if the Queue is empty, FALSE otherwise
4716 IRQL = PASSIVE_LEVEL
4717 IRQL = DISPATCH_LEVEL
4720 BOOLEAN MlmeQueueFull(
4721 IN MLME_QUEUE *Queue)
4725 NdisAcquireSpinLock(&(Queue->Lock));
4726 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4727 NdisReleaseSpinLock(&(Queue->Lock));
4732 /*! \brief The destructor of MLME Queue
4737 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4739 IRQL = PASSIVE_LEVEL
4742 VOID MlmeQueueDestroy(
4743 IN MLME_QUEUE *pQueue)
4745 NdisAcquireSpinLock(&(pQueue->Lock));
4749 NdisReleaseSpinLock(&(pQueue->Lock));
4750 NdisFreeSpinLock(&(pQueue->Lock));
4753 /*! \brief To substitute the message type if the message is coming from external
4754 * \param pFrame The frame received
4755 * \param *Machine The state machine
4756 * \param *MsgType the message type for the state machine
4757 * \return TRUE if the substitution is successful, FALSE otherwise
4761 IRQL = DISPATCH_LEVEL
4764 BOOLEAN MsgTypeSubst(
4765 IN PRTMP_ADAPTER pAd,
4766 IN PFRAME_802_11 pFrame,
4774 // Pointer to start of data frames including SNAP header
4775 pData = (PUCHAR) pFrame + LENGTH_802_11;
4777 // The only data type will pass to this function is EAPOL frame
4778 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4780 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4782 // Cisco Aironet SNAP header
4783 *Machine = AIRONET_STATE_MACHINE;
4784 *MsgType = MT2_AIRONET_MSG;
4788 *Machine = WPA_PSK_STATE_MACHINE;
4789 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4790 return(WpaMsgTypeSubst(EAPType, MsgType));
4794 switch (pFrame->Hdr.FC.SubType)
4796 case SUBTYPE_ASSOC_REQ:
4797 *Machine = ASSOC_STATE_MACHINE;
4798 *MsgType = MT2_PEER_ASSOC_REQ;
4800 case SUBTYPE_ASSOC_RSP:
4801 *Machine = ASSOC_STATE_MACHINE;
4802 *MsgType = MT2_PEER_ASSOC_RSP;
4804 case SUBTYPE_REASSOC_REQ:
4805 *Machine = ASSOC_STATE_MACHINE;
4806 *MsgType = MT2_PEER_REASSOC_REQ;
4808 case SUBTYPE_REASSOC_RSP:
4809 *Machine = ASSOC_STATE_MACHINE;
4810 *MsgType = MT2_PEER_REASSOC_RSP;
4812 case SUBTYPE_PROBE_REQ:
4813 *Machine = SYNC_STATE_MACHINE;
4814 *MsgType = MT2_PEER_PROBE_REQ;
4816 case SUBTYPE_PROBE_RSP:
4817 *Machine = SYNC_STATE_MACHINE;
4818 *MsgType = MT2_PEER_PROBE_RSP;
4820 case SUBTYPE_BEACON:
4821 *Machine = SYNC_STATE_MACHINE;
4822 *MsgType = MT2_PEER_BEACON;
4825 *Machine = SYNC_STATE_MACHINE;
4826 *MsgType = MT2_PEER_ATIM;
4828 case SUBTYPE_DISASSOC:
4829 *Machine = ASSOC_STATE_MACHINE;
4830 *MsgType = MT2_PEER_DISASSOC_REQ;
4833 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4834 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4835 if (Seq == 1 || Seq == 3)
4837 *Machine = AUTH_RSP_STATE_MACHINE;
4838 *MsgType = MT2_PEER_AUTH_ODD;
4840 else if (Seq == 2 || Seq == 4)
4842 *Machine = AUTH_STATE_MACHINE;
4843 *MsgType = MT2_PEER_AUTH_EVEN;
4850 case SUBTYPE_DEAUTH:
4851 *Machine = AUTH_RSP_STATE_MACHINE;
4852 *MsgType = MT2_PEER_DEAUTH;
4854 case SUBTYPE_ACTION:
4855 *Machine = ACTION_STATE_MACHINE;
4856 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4857 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4859 *MsgType = MT2_ACT_INVALID;
4863 *MsgType = (pFrame->Octet[0]&0x7F);
4874 // ===========================================================================================
4876 // ===========================================================================================
4878 /*! \brief Initialize the state machine.
4879 * \param *S pointer to the state machine
4880 * \param Trans State machine transition function
4881 * \param StNr number of states
4882 * \param MsgNr number of messages
4883 * \param DefFunc default function, when there is invalid state/message combination
4884 * \param InitState initial state of the state machine
4885 * \param Base StateMachine base, internal use only
4886 * \pre p_sm should be a legal pointer
4889 IRQL = PASSIVE_LEVEL
4892 VOID StateMachineInit(
4893 IN STATE_MACHINE *S,
4894 IN STATE_MACHINE_FUNC Trans[],
4897 IN STATE_MACHINE_FUNC DefFunc,
4903 // set number of states and messages
4908 S->TransFunc = Trans;
4910 // init all state transition to default function
4911 for (i = 0; i < StNr; i++)
4913 for (j = 0; j < MsgNr; j++)
4915 S->TransFunc[i * MsgNr + j] = DefFunc;
4919 // set the starting state
4920 S->CurrState = InitState;
4923 /*! \brief This function fills in the function pointer into the cell in the state machine
4924 * \param *S pointer to the state machine
4926 * \param Msg incoming message
4927 * \param f the function to be executed when (state, message) combination occurs at the state machine
4928 * \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
4931 IRQL = PASSIVE_LEVEL
4934 VOID StateMachineSetAction(
4935 IN STATE_MACHINE *S,
4938 IN STATE_MACHINE_FUNC Func)
4942 MsgIdx = Msg - S->Base;
4944 if (St < S->NrState && MsgIdx < S->NrMsg)
4946 // boundary checking before setting the action
4947 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
4951 /*! \brief This function does the state transition
4952 * \param *Adapter the NIC adapter pointer
4953 * \param *S the state machine
4954 * \param *Elem the message to be executed
4957 IRQL = DISPATCH_LEVEL
4960 VOID StateMachinePerformAction(
4961 IN PRTMP_ADAPTER pAd,
4962 IN STATE_MACHINE *S,
4963 IN MLME_QUEUE_ELEM *Elem)
4965 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
4969 ==========================================================================
4971 The drop function, when machine executes this, the message is simply
4972 ignored. This function does nothing, the message is freed in
4973 StateMachinePerformAction()
4974 ==========================================================================
4977 IN PRTMP_ADAPTER pAd,
4978 IN MLME_QUEUE_ELEM *Elem)
4982 // ===========================================================================================
4984 // ===========================================================================================
4987 ==========================================================================
4990 IRQL = PASSIVE_LEVEL
4992 ==========================================================================
4995 IN PRTMP_ADAPTER pAd,
4999 pAd->Mlme.ShiftReg = 1;
5001 pAd->Mlme.ShiftReg = Seed;
5005 ==========================================================================
5007 ==========================================================================
5010 IN PRTMP_ADAPTER pAd)
5017 if (pAd->Mlme.ShiftReg == 0)
5018 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5020 for (i = 0; i < 8; i++)
5022 if (pAd->Mlme.ShiftReg & 0x00000001)
5024 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5029 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5032 R = (R << 1) | Result;
5038 VOID AsicUpdateAutoFallBackTable(
5039 IN PRTMP_ADAPTER pAd,
5040 IN PUCHAR pRateTable)
5043 HT_FBK_CFG0_STRUC HtCfg0;
5044 HT_FBK_CFG1_STRUC HtCfg1;
5045 LG_FBK_CFG0_STRUC LgCfg0;
5046 LG_FBK_CFG1_STRUC LgCfg1;
5047 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5049 // set to initial value
5050 HtCfg0.word = 0x65432100;
5051 HtCfg1.word = 0xedcba988;
5052 LgCfg0.word = 0xedcba988;
5053 LgCfg1.word = 0x00002100;
5055 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5056 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5058 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5059 switch (pCurrTxRate->Mode)
5065 switch(pCurrTxRate->CurrMCS)
5068 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5071 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5074 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5077 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5080 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5083 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5086 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5089 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5097 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5099 switch(pCurrTxRate->CurrMCS)
5102 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5105 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5108 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5111 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5114 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5117 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5120 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5123 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5126 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5129 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5132 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5135 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5138 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5141 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5144 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5147 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5150 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5157 pNextTxRate = pCurrTxRate;
5160 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5161 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5162 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5163 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5167 ========================================================================
5169 Routine Description:
5170 Set MAC register value according operation mode.
5171 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5172 If MM or GF mask is not set, those passing argument doesn't not take effect.
5174 Operation mode meaning:
5175 = 0 : Pure HT, no preotection.
5176 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5177 = 0x10: No Transmission in 40M is protected.
5178 = 0x11: Transmission in both 40M and 20M shall be protected
5180 we should choose not to use GF. But still set correct ASIC registers.
5181 ========================================================================
5183 VOID AsicUpdateProtect(
5184 IN PRTMP_ADAPTER pAd,
5185 IN USHORT OperationMode,
5187 IN BOOLEAN bDisableBGProtect,
5188 IN BOOLEAN bNonGFExist)
5190 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5196 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5201 if (pAd->BATable.numAsOriginator)
5204 // enable the RTS/CTS to avoid channel collision
5206 SetMask = ALLN_SETPROTECT;
5210 // Config ASIC RTS threshold register
5211 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5212 MacReg &= 0xFF0000FF;
5214 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5216 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5217 (pAd->CommonCfg.bAggregationCapable == TRUE))
5218 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5220 MacReg |= (0x1000 << 8);
5224 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5227 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5229 // Initial common protection settings
5230 RTMPZeroMemory(Protect, sizeof(Protect));
5233 ProtCfg.field.TxopAllowGF40 = 1;
5234 ProtCfg.field.TxopAllowGF20 = 1;
5235 ProtCfg.field.TxopAllowMM40 = 1;
5236 ProtCfg.field.TxopAllowMM20 = 1;
5237 ProtCfg.field.TxopAllowOfdm = 1;
5238 ProtCfg.field.TxopAllowCck = 1;
5239 ProtCfg.field.RTSThEn = 1;
5240 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5242 // update PHY mode and rate
5243 if (pAd->CommonCfg.Channel > 14)
5244 ProtCfg.field.ProtectRate = 0x4000;
5245 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5247 // Handle legacy(B/G) protection
5248 if (bDisableBGProtect)
5250 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5251 ProtCfg.field.ProtectCtrl = 0;
5252 Protect[0] = ProtCfg.word;
5253 Protect[1] = ProtCfg.word;
5257 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5258 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5259 Protect[0] = ProtCfg.word;
5260 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5261 Protect[1] = ProtCfg.word;
5264 // Decide HT frame protection.
5265 if ((SetMask & ALLN_SETPROTECT) != 0)
5267 switch(OperationMode)
5271 // 1.All STAs in the BSS are 20/40 MHz HT
5272 // 2. in ai 20/40MHz BSS
5273 // 3. all STAs are 20MHz in a 20MHz BSS
5274 // Pure HT. no protection.
5278 // PROT_TXOP(25:20) -- 010111
5279 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5280 // PROT_CTRL(17:16) -- 00 (None)
5281 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5282 Protect[2] = 0x01744004;
5286 // PROT_TXOP(25:20) -- 111111
5287 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5288 // PROT_CTRL(17:16) -- 00 (None)
5289 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5290 Protect[3] = 0x03f44084;
5294 // PROT_TXOP(25:20) -- 010111
5295 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5296 // PROT_CTRL(17:16) -- 00 (None)
5297 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5298 Protect[4] = 0x01744004;
5302 // PROT_TXOP(25:20) -- 111111
5303 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5304 // PROT_CTRL(17:16) -- 00 (None)
5305 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5306 Protect[5] = 0x03f44084;
5310 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5311 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5312 Protect[4] = 0x01754004;
5313 Protect[5] = 0x03f54084;
5315 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5319 // This is "HT non-member protection mode."
5320 // If there may be non-HT STAs my BSS
5321 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5322 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5323 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5325 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5326 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5328 //Assign Protection method for 20&40 MHz packets
5329 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5330 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5331 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5332 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5333 Protect[2] = ProtCfg.word;
5334 Protect[3] = ProtCfg4.word;
5335 Protect[4] = ProtCfg.word;
5336 Protect[5] = ProtCfg4.word;
5337 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5341 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5342 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5343 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5345 //Assign Protection method for 40MHz packets
5346 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5347 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5348 Protect[2] = ProtCfg.word;
5349 Protect[3] = ProtCfg4.word;
5352 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5353 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5355 Protect[4] = ProtCfg.word;
5356 Protect[5] = ProtCfg4.word;
5358 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5362 // HT mixed mode. PROTECT ALL!
5364 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5365 ProtCfg4.word = 0x03f44084;
5366 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5367 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5369 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5370 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5372 //Assign Protection method for 20&40 MHz packets
5373 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5374 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5375 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5376 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5377 Protect[2] = ProtCfg.word;
5378 Protect[3] = ProtCfg4.word;
5379 Protect[4] = ProtCfg.word;
5380 Protect[5] = ProtCfg4.word;
5381 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5385 // Special on for Atheros problem n chip.
5386 Protect[2] = 0x01754004;
5387 Protect[3] = 0x03f54084;
5388 Protect[4] = 0x01754004;
5389 Protect[5] = 0x03f54084;
5390 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5395 offset = CCK_PROT_CFG;
5396 for (i = 0;i < 6;i++)
5398 if ((SetMask & (1<< i)))
5400 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5406 ==========================================================================
5409 IRQL = PASSIVE_LEVEL
5410 IRQL = DISPATCH_LEVEL
5412 ==========================================================================
5414 VOID AsicSwitchChannel(
5415 IN PRTMP_ADAPTER pAd,
5419 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5420 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5422 UINT32 Value = 0; //BbpReg, Value;
5423 RTMP_RF_REGS *RFRegTable;
5425 // Search Tx power value
5426 for (index = 0; index < pAd->ChannelListNum; index++)
5428 if (Channel == pAd->ChannelList[index].Channel)
5430 TxPwer = pAd->ChannelList[index].Power;
5431 TxPwer2 = pAd->ChannelList[index].Power2;
5436 if (index == MAX_NUM_OF_CHANNELS)
5438 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5442 RFRegTable = RF2850RegTable;
5444 switch (pAd->RfIcType)
5451 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5453 if (Channel == RFRegTable[index].Channel)
5455 R2 = RFRegTable[index].R2;
5456 if (pAd->Antenna.field.TxPath == 1)
5458 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5461 if (pAd->Antenna.field.RxPath == 2)
5463 R2 |= 0x40; // write 1 to off Rxpath.
5465 else if (pAd->Antenna.field.RxPath == 1)
5467 R2 |= 0x20040; // write 1 to off RxPath
5472 // initialize R3, R4
5473 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5474 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5476 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5478 if ((TxPwer >= -7) && (TxPwer < 0))
5480 TxPwer = (7+TxPwer);
5481 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5482 R3 |= (TxPwer << 10);
5483 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5487 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5488 R3 |= (TxPwer << 10) | (1 << 9);
5492 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5494 TxPwer2 = (7+TxPwer2);
5495 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5496 R4 |= (TxPwer2 << 7);
5497 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5501 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5502 R4 |= (TxPwer2 << 7) | (1 << 6);
5507 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5508 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5511 // Based on BBP current mode before changing RF channel.
5512 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5518 pAd->LatchRfRegs.Channel = Channel;
5519 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5520 pAd->LatchRfRegs.R2 = R2;
5521 pAd->LatchRfRegs.R3 = R3;
5522 pAd->LatchRfRegs.R4 = R4;
5524 // Set RF value 1's set R3[bit2] = [0]
5525 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5526 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5527 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5528 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5532 // Set RF value 2's set R3[bit2] = [1]
5533 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5534 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5535 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5536 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5540 // Set RF value 3's set R3[bit2] = [0]
5541 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5542 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5543 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5544 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5556 // Change BBP setting during siwtch from a->g, g->a
5559 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5561 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5562 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5563 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5564 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.
5565 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5567 // Rx High power VGA offset for LNA select
5568 if (pAd->NicConfig2.field.ExternalLNAForG)
5570 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5571 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5575 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5576 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5579 // 5G band selection PIN, bit1 and bit2 are complement
5580 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5583 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5585 // Turn off unused PA or LNA when only 1T or 1R
5586 if (pAd->Antenna.field.TxPath == 1)
5588 TxPinCfg &= 0xFFFFFFF3;
5590 if (pAd->Antenna.field.RxPath == 1)
5592 TxPinCfg &= 0xFFFFF3FF;
5595 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5599 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5601 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5602 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5603 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5604 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.
5605 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5607 // Rx High power VGA offset for LNA select
5608 if (pAd->NicConfig2.field.ExternalLNAForA)
5610 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5614 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5617 // 5G band selection PIN, bit1 and bit2 are complement
5618 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5621 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5623 // Turn off unused PA or LNA when only 1T or 1R
5624 if (pAd->Antenna.field.TxPath == 1)
5626 TxPinCfg &= 0xFFFFFFF3;
5628 if (pAd->Antenna.field.RxPath == 1)
5630 TxPinCfg &= 0xFFFFF3FF;
5633 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5636 // R66 should be set according to Channel and use 20MHz when scanning
5637 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5639 RTMPSetAGCInitValue(pAd, BW_20);
5641 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5644 // On 11A, We should delay and wait RF/BBP to be stable
5645 // and the appropriate time should be 1000 micro seconds
5646 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5648 RTMPusecDelay(1000);
5650 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",
5653 (R3 & 0x00003e00) >> 9,
5654 (R4 & 0x000007c0) >> 6,
5655 pAd->Antenna.field.TxPath,
5656 pAd->LatchRfRegs.R1,
5657 pAd->LatchRfRegs.R2,
5658 pAd->LatchRfRegs.R3,
5659 pAd->LatchRfRegs.R4));
5663 ==========================================================================
5665 This function is required for 2421 only, and should not be used during
5666 site survey. It's only required after NIC decided to stay at a channel
5667 for a longer period.
5668 When this function is called, it's always after AsicSwitchChannel().
5670 IRQL = PASSIVE_LEVEL
5671 IRQL = DISPATCH_LEVEL
5673 ==========================================================================
5675 VOID AsicLockChannel(
5676 IN PRTMP_ADAPTER pAd,
5682 ==========================================================================
5685 IRQL = PASSIVE_LEVEL
5686 IRQL = DISPATCH_LEVEL
5688 ==========================================================================
5690 VOID AsicAntennaSelect(
5691 IN PRTMP_ADAPTER pAd,
5697 ========================================================================
5699 Routine Description:
5700 Antenna miscellaneous setting.
5703 pAd Pointer to our adapter
5704 BandState Indicate current Band State.
5709 IRQL <= DISPATCH_LEVEL
5712 1.) Frame End type control
5713 only valid for G only (RF_2527 & RF_2529)
5714 0: means DPDT, set BBP R4 bit 5 to 1
5715 1: means SPDT, set BBP R4 bit 5 to 0
5718 ========================================================================
5720 VOID AsicAntennaSetting(
5721 IN PRTMP_ADAPTER pAd,
5722 IN ABGBAND_STATE BandState)
5726 VOID AsicRfTuningExec(
5727 IN PVOID SystemSpecific1,
5728 IN PVOID FunctionContext,
5729 IN PVOID SystemSpecific2,
5730 IN PVOID SystemSpecific3)
5735 ==========================================================================
5737 Gives CCK TX rate 2 more dB TX power.
5738 This routine works only in LINK UP in INFRASTRUCTURE mode.
5740 calculate desired Tx power in RF R3.Tx0~5, should consider -
5741 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5742 1. TxPowerPercentage
5743 2. auto calibration based on TSSI feedback
5744 3. extra 2 db for CCK
5745 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5747 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5748 it should be called AFTER MlmeDynamicTxRatSwitching()
5749 ==========================================================================
5751 VOID AsicAdjustTxPower(
5752 IN PRTMP_ADAPTER pAd)
5756 BOOLEAN bAutoTxAgc = FALSE;
5757 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5758 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5759 PCHAR pTxAgcCompensate;
5763 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5764 || (pAd->bPCIclkOff == TRUE)
5765 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
5766 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
5769 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5771 if (pAd->CommonCfg.CentralChannel > 14)
5773 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5774 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5775 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5776 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5777 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5781 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5782 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5783 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5784 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5785 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5790 if (pAd->CommonCfg.Channel > 14)
5792 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5793 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5794 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5795 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5796 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5800 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5801 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5802 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5803 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5804 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5808 // TX power compensation for temperature variation based on TSSI. try every 4 second
5809 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5811 if (pAd->CommonCfg.Channel <= 14)
5814 bAutoTxAgc = pAd->bAutoTxAgcG;
5815 TssiRef = pAd->TssiRefG;
5816 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5817 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5818 TxAgcStep = pAd->TxAgcStepG;
5819 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5824 bAutoTxAgc = pAd->bAutoTxAgcA;
5825 TssiRef = pAd->TssiRefA;
5826 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
5827 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
5828 TxAgcStep = pAd->TxAgcStepA;
5829 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5834 /* BbpR1 is unsigned char */
5835 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
5837 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
5838 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
5839 /* step value is defined in pAd->TxAgcStepG for tx power value */
5841 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
5842 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
5843 above value are examined in mass factory production */
5844 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
5846 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
5847 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
5848 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
5850 if (BbpR49 > pTssiMinusBoundary[1])
5852 // Reading is larger than the reference value
5853 // check for how large we need to decrease the Tx power
5854 for (idx = 1; idx < 5; idx++)
5856 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
5859 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
5860 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
5862 DeltaPwr += (*pTxAgcCompensate);
5863 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
5864 BbpR49, TssiRef, TxAgcStep, idx-1));
5866 else if (BbpR49 < pTssiPlusBoundary[1])
5868 // Reading is smaller than the reference value
5869 // check for how large we need to increase the Tx power
5870 for (idx = 1; idx < 5; idx++)
5872 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
5875 // The index is the step we should increase, idx = 0 means there is nothing to compensate
5876 *pTxAgcCompensate = TxAgcStep * (idx-1);
5877 DeltaPwr += (*pTxAgcCompensate);
5878 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5879 BbpR49, TssiRef, TxAgcStep, idx-1));
5883 *pTxAgcCompensate = 0;
5884 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5885 BbpR49, TssiRef, TxAgcStep, 0));
5891 if (pAd->CommonCfg.Channel <= 14)
5893 bAutoTxAgc = pAd->bAutoTxAgcG;
5894 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5898 bAutoTxAgc = pAd->bAutoTxAgcA;
5899 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5903 DeltaPwr += (*pTxAgcCompensate);
5906 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
5909 /* calculate delta power based on the percentage specified from UI */
5910 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
5911 // We lower TX power here according to the percentage specified from UI
5912 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
5914 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
5916 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
5920 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
5924 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
5928 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
5933 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
5938 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
5940 /* reset different new tx power for different TX rate */
5943 if (TxPwr[i] != 0xffffffff)
5947 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
5949 if ((Value + DeltaPwr) < 0)
5951 Value = 0; /* min */
5953 else if ((Value + DeltaPwr) > 0xF)
5955 Value = 0xF; /* max */
5959 Value += DeltaPwr; /* temperature compensation */
5962 /* fill new value to CSR offset */
5963 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
5966 /* write tx power value to CSR */
5967 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
5968 TX power for OFDM 6M/9M
5969 TX power for CCK5.5M/11M
5970 TX power for CCK1M/2M */
5971 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
5972 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
5979 ==========================================================================
5981 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
5982 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
5983 the wakeup timer timeout. Driver has to issue a separate command to wake
5986 IRQL = DISPATCH_LEVEL
5988 ==========================================================================
5990 VOID AsicSleepThenAutoWakeup(
5991 IN PRTMP_ADAPTER pAd,
5992 IN USHORT TbttNumToNextWakeUp)
5994 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
5998 ==========================================================================
6000 AsicForceWakeup() is used whenever manual wakeup is required
6001 AsicForceSleep() should only be used when not in INFRA BSS. When
6002 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6003 ==========================================================================
6005 VOID AsicForceSleep(
6006 IN PRTMP_ADAPTER pAd)
6012 ==========================================================================
6014 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6017 IRQL = PASSIVE_LEVEL
6018 IRQL = DISPATCH_LEVEL
6019 ==========================================================================
6021 VOID AsicForceWakeup(
6022 IN PRTMP_ADAPTER pAd,
6025 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6026 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6030 ==========================================================================
6034 IRQL = DISPATCH_LEVEL
6036 ==========================================================================
6039 IN PRTMP_ADAPTER pAd,
6043 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6044 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6046 Addr4 = (ULONG)(pBssid[0]) |
6047 (ULONG)(pBssid[1] << 8) |
6048 (ULONG)(pBssid[2] << 16) |
6049 (ULONG)(pBssid[3] << 24);
6050 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6053 // always one BSSID in STA mode
6054 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6056 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6059 VOID AsicSetMcastWC(
6060 IN PRTMP_ADAPTER pAd)
6062 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6065 pEntry->Sst = SST_ASSOC;
6066 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6067 pEntry->PsMode = PWR_ACTIVE;
6068 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6069 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6073 ==========================================================================
6076 IRQL = DISPATCH_LEVEL
6078 ==========================================================================
6080 VOID AsicDelWcidTab(
6081 IN PRTMP_ADAPTER pAd,
6084 ULONG Addr0 = 0x0, Addr1 = 0x0;
6087 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6088 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6089 RTMP_IO_WRITE32(pAd, offset, Addr0);
6091 RTMP_IO_WRITE32(pAd, offset, Addr1);
6095 ==========================================================================
6098 IRQL = DISPATCH_LEVEL
6100 ==========================================================================
6103 IN PRTMP_ADAPTER pAd)
6105 TX_LINK_CFG_STRUC TxLinkCfg;
6108 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6109 TxLinkCfg.field.TxRDGEn = 1;
6110 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6112 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6115 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6117 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6121 ==========================================================================
6124 IRQL = DISPATCH_LEVEL
6126 ==========================================================================
6128 VOID AsicDisableRDG(
6129 IN PRTMP_ADAPTER pAd)
6131 TX_LINK_CFG_STRUC TxLinkCfg;
6135 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6136 TxLinkCfg.field.TxRDGEn = 0;
6137 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6139 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6142 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6143 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6146 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6147 if (pAd->CommonCfg.bEnableTxBurst)
6150 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6154 ==========================================================================
6157 IRQL = PASSIVE_LEVEL
6158 IRQL = DISPATCH_LEVEL
6160 ==========================================================================
6162 VOID AsicDisableSync(
6163 IN PRTMP_ADAPTER pAd)
6165 BCN_TIME_CFG_STRUC csr;
6167 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6169 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6170 // that NIC will never wakes up because TSF stops and no more
6172 pAd->TbttTickCount = 0;
6173 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6174 csr.field.bBeaconGen = 0;
6175 csr.field.bTBTTEnable = 0;
6176 csr.field.TsfSyncMode = 0;
6177 csr.field.bTsfTicking = 0;
6178 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6183 ==========================================================================
6186 IRQL = DISPATCH_LEVEL
6188 ==========================================================================
6190 VOID AsicEnableBssSync(
6191 IN PRTMP_ADAPTER pAd)
6193 BCN_TIME_CFG_STRUC csr;
6195 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6197 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6200 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6201 csr.field.bTsfTicking = 1;
6202 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6203 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6204 csr.field.bTBTTEnable = 1;
6207 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6211 ==========================================================================
6214 BEACON frame in shared memory should be built ok before this routine
6215 can be called. Otherwise, a garbage frame maybe transmitted out every
6218 IRQL = DISPATCH_LEVEL
6220 ==========================================================================
6222 VOID AsicEnableIbssSync(
6223 IN PRTMP_ADAPTER pAd)
6225 BCN_TIME_CFG_STRUC csr9;
6229 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6231 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6232 csr9.field.bBeaconGen = 0;
6233 csr9.field.bTBTTEnable = 0;
6234 csr9.field.bTsfTicking = 0;
6235 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6237 // move BEACON TXD and frame content to on-chip memory
6238 ptr = (PUCHAR)&pAd->BeaconTxWI;
6239 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6241 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6242 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6246 // start right after the 16-byte TXWI field
6247 ptr = pAd->BeaconBuf;
6248 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6250 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6251 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6255 // start sending BEACON
6256 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6257 csr9.field.bTsfTicking = 1;
6258 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6259 csr9.field.bTBTTEnable = 1;
6260 csr9.field.bBeaconGen = 1;
6261 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6265 ==========================================================================
6268 IRQL = PASSIVE_LEVEL
6269 IRQL = DISPATCH_LEVEL
6271 ==========================================================================
6273 VOID AsicSetEdcaParm(
6274 IN PRTMP_ADAPTER pAd,
6275 IN PEDCA_PARM pEdcaParm)
6277 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6278 AC_TXOP_CSR0_STRUC csr0;
6279 AC_TXOP_CSR1_STRUC csr1;
6280 AIFSN_CSR_STRUC AifsnCsr;
6281 CWMIN_CSR_STRUC CwminCsr;
6282 CWMAX_CSR_STRUC CwmaxCsr;
6289 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6291 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6292 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6293 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6295 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6296 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6299 //========================================================
6300 // MAC Register has a copy .
6301 //========================================================
6302 if( pAd->CommonCfg.bEnableTxBurst )
6304 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6305 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6308 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6309 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6310 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6311 Ac0Cfg.field.Aifsn = 2;
6312 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6314 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6315 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6316 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6317 Ac1Cfg.field.Aifsn = 2;
6318 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6320 if (pAd->CommonCfg.PhyMode == PHY_11B)
6322 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6323 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6327 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6328 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6330 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6331 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6332 Ac2Cfg.field.Aifsn = 2;
6333 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6334 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6335 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6336 Ac3Cfg.field.Aifsn = 2;
6337 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6339 //========================================================
6340 // DMA Register has a copy too.
6341 //========================================================
6342 csr0.field.Ac0Txop = 0; // QID_AC_BE
6343 csr0.field.Ac1Txop = 0; // QID_AC_BK
6344 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6345 if (pAd->CommonCfg.PhyMode == PHY_11B)
6347 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6348 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6352 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6353 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6355 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6358 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6359 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6360 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6361 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6362 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6365 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6366 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6367 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6368 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6369 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6371 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6373 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6377 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6378 //========================================================
6379 // MAC Register has a copy.
6380 //========================================================
6382 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6383 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6385 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6387 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6388 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6389 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6390 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6392 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6393 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6394 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6395 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6397 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6398 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6399 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6400 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6403 // Tuning for Wi-Fi WMM S06
6404 if (pAd->CommonCfg.bWiFiTest &&
6405 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6406 Ac2Cfg.field.Aifsn -= 1;
6408 // Tuning for TGn Wi-Fi 5.2.32
6409 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6410 if (STA_TGN_WIFI_ON(pAd) &&
6411 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6413 Ac0Cfg.field.Aifsn = 3;
6414 Ac2Cfg.field.AcTxop = 5;
6418 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6419 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6420 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6421 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6424 if (pAd->CommonCfg.bWiFiTest)
6426 if (Ac3Cfg.field.AcTxop == 102)
6428 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6429 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6430 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6431 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6432 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6435 //#endif // WIFI_TEST //
6437 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6438 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6439 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6440 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6443 //========================================================
6444 // DMA Register has a copy too.
6445 //========================================================
6446 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6447 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6448 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6450 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6451 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6452 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6455 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6456 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6457 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6459 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6461 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6464 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6465 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6466 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6467 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6468 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6471 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6472 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6473 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6476 // Tuning for Wi-Fi WMM S06
6477 if (pAd->CommonCfg.bWiFiTest &&
6478 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6479 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6481 // Tuning for TGn Wi-Fi 5.2.32
6482 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6483 if (STA_TGN_WIFI_ON(pAd) &&
6484 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6486 AifsnCsr.field.Aifsn0 = 3;
6487 AifsnCsr.field.Aifsn2 = 7;
6491 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6493 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6495 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6498 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6499 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6500 pEdcaParm->Aifsn[0],
6501 pEdcaParm->Cwmin[0],
6502 pEdcaParm->Cwmax[0],
6503 pEdcaParm->Txop[0]<<5,
6504 pEdcaParm->bACM[0]));
6505 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6506 pEdcaParm->Aifsn[1],
6507 pEdcaParm->Cwmin[1],
6508 pEdcaParm->Cwmax[1],
6509 pEdcaParm->Txop[1]<<5,
6510 pEdcaParm->bACM[1]));
6511 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6512 pEdcaParm->Aifsn[2],
6513 pEdcaParm->Cwmin[2],
6514 pEdcaParm->Cwmax[2],
6515 pEdcaParm->Txop[2]<<5,
6516 pEdcaParm->bACM[2]));
6517 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6518 pEdcaParm->Aifsn[3],
6519 pEdcaParm->Cwmin[3],
6520 pEdcaParm->Cwmax[3],
6521 pEdcaParm->Txop[3]<<5,
6522 pEdcaParm->bACM[3]));
6528 ==========================================================================
6531 IRQL = PASSIVE_LEVEL
6532 IRQL = DISPATCH_LEVEL
6534 ==========================================================================
6536 VOID AsicSetSlotTime(
6537 IN PRTMP_ADAPTER pAd,
6538 IN BOOLEAN bUseShortSlotTime)
6541 UINT32 RegValue = 0;
6543 if (pAd->CommonCfg.Channel > 14)
6544 bUseShortSlotTime = TRUE;
6546 if (bUseShortSlotTime)
6547 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6549 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6551 SlotTime = (bUseShortSlotTime)? 9 : 20;
6554 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6555 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6556 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6559 // In this case, we will think it is doing Wi-Fi test
6560 // And we will not set to short slot when bEnableTxBurst is TRUE.
6562 else if (pAd->CommonCfg.bEnableTxBurst)
6567 // For some reasons, always set it to short slot time.
6569 // ToDo: Should consider capability with 11B
6571 if (pAd->StaCfg.BssType == BSS_ADHOC)
6574 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6575 RegValue = RegValue & 0xFFFFFF00;
6577 RegValue |= SlotTime;
6579 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6583 ========================================================================
6585 Add Shared key information into ASIC.
6586 Update shared key, TxMic and RxMic to Asic Shared key table
6587 Update its cipherAlg to Asic Shared key Mode.
6590 ========================================================================
6592 VOID AsicAddSharedKeyEntry(
6593 IN PRTMP_ADAPTER pAd,
6601 ULONG offset; //, csr0;
6602 SHAREDKEY_MODE_STRUC csr1;
6605 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6606 //============================================================================================
6608 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6609 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6610 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]));
6613 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6614 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6618 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6619 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6621 //============================================================================================
6623 // fill key material - key + TX MIC + RX MIC
6625 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6626 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6628 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6631 offset += MAX_LEN_OF_SHARE_KEY;
6636 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6645 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6651 // Update cipher algorithm. WSTA always use BSS0
6653 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6654 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6655 if ((BssIndex%2) == 0)
6658 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6659 else if (KeyIdx == 1)
6660 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6661 else if (KeyIdx == 2)
6662 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6664 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6669 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6670 else if (KeyIdx == 1)
6671 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6672 else if (KeyIdx == 2)
6673 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6675 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6677 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6678 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6682 // IRQL = DISPATCH_LEVEL
6683 VOID AsicRemoveSharedKeyEntry(
6684 IN PRTMP_ADAPTER pAd,
6689 SHAREDKEY_MODE_STRUC csr1;
6691 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6693 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6694 if ((BssIndex%2) == 0)
6697 csr1.field.Bss0Key0CipherAlg = 0;
6698 else if (KeyIdx == 1)
6699 csr1.field.Bss0Key1CipherAlg = 0;
6700 else if (KeyIdx == 2)
6701 csr1.field.Bss0Key2CipherAlg = 0;
6703 csr1.field.Bss0Key3CipherAlg = 0;
6708 csr1.field.Bss1Key0CipherAlg = 0;
6709 else if (KeyIdx == 1)
6710 csr1.field.Bss1Key1CipherAlg = 0;
6711 else if (KeyIdx == 2)
6712 csr1.field.Bss1Key2CipherAlg = 0;
6714 csr1.field.Bss1Key3CipherAlg = 0;
6716 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6717 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6718 ASSERT(BssIndex < 4);
6724 VOID AsicUpdateWCIDAttribute(
6725 IN PRTMP_ADAPTER pAd,
6729 IN BOOLEAN bUsePairewiseKeyTable)
6731 ULONG WCIDAttri = 0, offset;
6734 // Update WCID attribute.
6735 // Only TxKey could update WCID attribute.
6737 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6738 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6739 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6742 VOID AsicUpdateWCIDIVEIV(
6743 IN PRTMP_ADAPTER pAd,
6750 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6752 RTMP_IO_WRITE32(pAd, offset, uIV);
6753 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6756 VOID AsicUpdateRxWCIDTable(
6757 IN PRTMP_ADAPTER pAd,
6764 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6765 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6766 RTMP_IO_WRITE32(pAd, offset, Addr);
6767 Addr = pAddr[4] + (pAddr[5] << 8);
6768 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6773 ========================================================================
6775 Routine Description:
6776 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6779 pAd Pointer to our adapter
6780 WCID WCID Entry number.
6781 BssIndex BSSID index, station or none multiple BSSID support
6782 this value should be 0.
6783 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6784 pCipherKey Pointer to Cipher Key.
6785 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6786 otherwise PairewiseKey table
6787 bTxKey This is the transmit key if enabled.
6793 This routine will set the relative key stuff to Asic including WCID attribute,
6794 Cipher Key, Cipher algorithm and IV/EIV.
6796 IV/EIV will be update if this CipherKey is the transmission key because
6797 ASIC will base on IV's KeyID value to select Cipher Key.
6799 If bTxKey sets to FALSE, this is not the TX key, but it could be
6802 For AP mode bTxKey must be always set to TRUE.
6803 ========================================================================
6805 VOID AsicAddKeyEntry(
6806 IN PRTMP_ADAPTER pAd,
6810 IN PCIPHER_KEY pCipherKey,
6811 IN BOOLEAN bUsePairewiseKeyTable,
6816 PUCHAR pKey = pCipherKey->Key;
6817 PUCHAR pTxMic = pCipherKey->TxMic;
6818 PUCHAR pRxMic = pCipherKey->RxMic;
6819 PUCHAR pTxtsc = pCipherKey->TxTsc;
6820 UCHAR CipherAlg = pCipherKey->CipherAlg;
6821 SHAREDKEY_MODE_STRUC csr1;
6824 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
6826 // 1.) decide key table offset
6828 if (bUsePairewiseKeyTable)
6829 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6831 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
6834 // 2.) Set Key to Asic
6836 //for (i = 0; i < KeyLen; i++)
6837 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
6839 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6841 offset += MAX_LEN_OF_PEER_KEY;
6844 // 3.) Set MIC key if available
6848 for (i = 0; i < 8; i++)
6850 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6853 offset += LEN_TKIP_TXMICK;
6857 for (i = 0; i < 8; i++)
6859 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6865 // 4.) Modify IV/EIV if needs
6866 // This will force Asic to use this key ID by setting IV.
6870 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6874 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
6875 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
6876 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
6878 IV4 = (KeyIdx << 6);
6879 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
6880 IV4 |= 0x20; // turn on extension bit means EIV existence
6882 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
6888 for (i = 0; i < 4; i++)
6890 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
6893 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
6896 if (!bUsePairewiseKeyTable)
6899 // Only update the shared key security mode
6901 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
6902 if ((BssIndex % 2) == 0)
6905 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6906 else if (KeyIdx == 1)
6907 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6908 else if (KeyIdx == 2)
6909 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6911 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6916 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6917 else if (KeyIdx == 1)
6918 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6919 else if (KeyIdx == 2)
6920 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6922 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6924 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
6927 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
6932 ========================================================================
6934 Add Pair-wise key material into ASIC.
6935 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
6938 ========================================================================
6940 VOID AsicAddPairwiseKeyEntry(
6941 IN PRTMP_ADAPTER pAd,
6944 IN CIPHER_KEY *pCipherKey)
6948 PUCHAR pKey = pCipherKey->Key;
6949 PUCHAR pTxMic = pCipherKey->TxMic;
6950 PUCHAR pRxMic = pCipherKey->RxMic;
6952 UCHAR CipherAlg = pCipherKey->CipherAlg;
6956 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6957 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
6959 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6961 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
6964 RTMP_IO_READ32(pAd, offset + i, &Value);
6967 offset += MAX_LEN_OF_PEER_KEY;
6974 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
6982 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
6986 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
6987 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6988 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]));
6991 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6992 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6996 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6997 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7001 ========================================================================
7003 Remove Pair-wise key material from ASIC.
7006 ========================================================================
7008 VOID AsicRemovePairwiseKeyEntry(
7009 IN PRTMP_ADAPTER pAd,
7016 // re-set the entry's WCID attribute as OPEN-NONE.
7017 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7018 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7019 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7022 BOOLEAN AsicSendCommandToMcu(
7023 IN PRTMP_ADAPTER pAd,
7029 HOST_CMD_CSR_STRUC H2MCmd;
7030 H2M_MAILBOX_STRUC H2MMailbox;
7035 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7036 if (H2MMailbox.field.Owner == 0)
7048 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7050 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7052 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7053 // Reset DMA/CPU ring index
7054 RTMPRingCleanUp(pAd, QID_AC_BK);
7055 RTMPRingCleanUp(pAd, QID_AC_BE);
7056 RTMPRingCleanUp(pAd, QID_AC_VI);
7057 RTMPRingCleanUp(pAd, QID_AC_VO);
7058 RTMPRingCleanUp(pAd, QID_HCCA);
7059 RTMPRingCleanUp(pAd, QID_MGMT);
7060 RTMPRingCleanUp(pAd, QID_RX);
7063 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7065 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7066 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7071 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7072 H2MMailbox.field.CmdToken = Token;
7073 H2MMailbox.field.HighByte = Arg1;
7074 H2MMailbox.field.LowByte = Arg0;
7075 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7078 H2MCmd.field.HostCommand = Command;
7079 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7081 if (Command != 0x80)
7088 BOOLEAN AsicCheckCommanOk(
7089 IN PRTMP_ADAPTER pAd,
7092 UINT32 CmdStatus = 0, CID = 0, i;
7093 UINT32 ThisCIDMask = 0;
7098 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7099 // Find where the command is. Because this is randomly specified by firmware.
7100 if ((CID & CID0MASK) == Command)
7102 ThisCIDMask = CID0MASK;
7105 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7107 ThisCIDMask = CID1MASK;
7110 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7112 ThisCIDMask = CID2MASK;
7115 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7117 ThisCIDMask = CID3MASK;
7125 // Get CommandStatus Value
7126 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7128 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7131 // If Status is 1, the comamnd is success.
7132 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7133 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7135 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7136 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7137 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7140 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7144 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7146 // Clear Command and Status.
7147 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7148 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7154 ========================================================================
7156 Routine Description:
7157 Verify the support rate for different PHY type
7160 pAd Pointer to our adapter
7165 IRQL = PASSIVE_LEVEL
7167 ========================================================================
7169 VOID RTMPCheckRates(
7170 IN PRTMP_ADAPTER pAd,
7171 IN OUT UCHAR SupRate[],
7172 IN OUT UCHAR *SupRateLen)
7174 UCHAR RateIdx, i, j;
7175 UCHAR NewRate[12], NewRateLen;
7179 if (pAd->CommonCfg.PhyMode == PHY_11B)
7184 // Check for support rates exclude basic rate bit
7185 for (i = 0; i < *SupRateLen; i++)
7186 for (j = 0; j < RateIdx; j++)
7187 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7188 NewRate[NewRateLen++] = SupRate[i];
7190 *SupRateLen = NewRateLen;
7191 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7194 BOOLEAN RTMPCheckChannel(
7195 IN PRTMP_ADAPTER pAd,
7196 IN UCHAR CentralChannel,
7200 UCHAR UpperChannel = 0, LowerChannel = 0;
7201 UCHAR NoEffectChannelinList = 0;
7203 // Find upper and lower channel according to 40MHz current operation.
7204 if (CentralChannel < Channel)
7206 UpperChannel = Channel;
7207 if (CentralChannel > 2)
7208 LowerChannel = CentralChannel - 2;
7212 else if (CentralChannel > Channel)
7214 UpperChannel = CentralChannel + 2;
7215 LowerChannel = Channel;
7218 for (k = 0;k < pAd->ChannelListNum;k++)
7220 if (pAd->ChannelList[k].Channel == UpperChannel)
7222 NoEffectChannelinList ++;
7224 if (pAd->ChannelList[k].Channel == LowerChannel)
7226 NoEffectChannelinList ++;
7230 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7231 if (NoEffectChannelinList == 2)
7238 ========================================================================
7240 Routine Description:
7241 Verify the support rate for HT phy type
7244 pAd Pointer to our adapter
7247 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7249 IRQL = PASSIVE_LEVEL
7251 ========================================================================
7253 BOOLEAN RTMPCheckHt(
7254 IN PRTMP_ADAPTER pAd,
7256 IN HT_CAPABILITY_IE *pHtCapability,
7257 IN ADD_HT_INFO_IE *pAddHtInfo)
7259 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7262 // If use AMSDU, set flag.
7263 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7264 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7265 // Save Peer Capability
7266 if (pHtCapability->HtCapInfo.ShortGIfor20)
7267 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7268 if (pHtCapability->HtCapInfo.ShortGIfor40)
7269 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7270 if (pHtCapability->HtCapInfo.TxSTBC)
7271 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7272 if (pHtCapability->HtCapInfo.RxSTBC)
7273 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7274 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7276 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7279 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7281 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7284 // Will check ChannelWidth for MCSSet[4] below
7285 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7286 switch (pAd->CommonCfg.RxStream)
7289 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7290 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7291 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7292 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7295 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7296 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7297 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7298 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7301 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7302 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7303 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7304 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7308 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7310 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7311 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7312 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7314 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7316 // Send Assoc Req with my HT capability.
7317 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7318 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7319 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7320 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7321 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7322 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7323 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7324 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7325 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7326 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7327 if (pAd->CommonCfg.bRdg)
7329 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7330 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7333 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7334 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7336 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7341 ========================================================================
7343 Routine Description:
7344 Verify the support rate for different PHY type
7347 pAd Pointer to our adapter
7352 IRQL = PASSIVE_LEVEL
7354 ========================================================================
7356 VOID RTMPUpdateMlmeRate(
7357 IN PRTMP_ADAPTER pAd)
7360 UCHAR ProperMlmeRate; //= RATE_54;
7361 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7362 BOOLEAN bMatch = FALSE;
7364 switch (pAd->CommonCfg.PhyMode)
7367 ProperMlmeRate = RATE_11;
7368 MinimumRate = RATE_1;
7370 case PHY_11BG_MIXED:
7371 case PHY_11ABGN_MIXED:
7372 case PHY_11BGN_MIXED:
7373 if ((pAd->MlmeAux.SupRateLen == 4) &&
7374 (pAd->MlmeAux.ExtRateLen == 0))
7376 ProperMlmeRate = RATE_11;
7378 ProperMlmeRate = RATE_24;
7380 if (pAd->MlmeAux.Channel <= 14)
7381 MinimumRate = RATE_1;
7383 MinimumRate = RATE_6;
7386 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7387 case PHY_11GN_MIXED:
7388 case PHY_11AGN_MIXED:
7389 case PHY_11AN_MIXED:
7391 ProperMlmeRate = RATE_24;
7392 MinimumRate = RATE_6;
7394 case PHY_11ABG_MIXED:
7395 ProperMlmeRate = RATE_24;
7396 if (pAd->MlmeAux.Channel <= 14)
7397 MinimumRate = RATE_1;
7399 MinimumRate = RATE_6;
7402 ProperMlmeRate = RATE_1;
7403 MinimumRate = RATE_1;
7407 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7409 for (j = 0; j < RateIdx; j++)
7411 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7413 if (j == ProperMlmeRate)
7425 if (bMatch == FALSE)
7427 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7429 for (j = 0; j < RateIdx; j++)
7431 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7433 if (j == ProperMlmeRate)
7446 if (bMatch == FALSE)
7448 ProperMlmeRate = MinimumRate;
7451 pAd->CommonCfg.MlmeRate = MinimumRate;
7452 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7453 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7455 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7456 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7457 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7458 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7462 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7463 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7464 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7465 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7468 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7472 IN PRTMP_ADAPTER pAd,
7479 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7484 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7486 larger = max(Rssi0, Rssi1);
7489 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7491 larger = max(larger, Rssi2);
7501 ========================================================================
7502 Routine Description:
7503 Periodic evaluate antenna link status
7506 pAd - Adapter pointer
7511 ========================================================================
7513 VOID AsicEvaluateRxAnt(
7514 IN PRTMP_ADAPTER pAd)
7519 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7520 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7521 fRTMP_ADAPTER_RADIO_OFF |
7522 fRTMP_ADAPTER_NIC_NOT_EXIST |
7523 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7526 if (pAd->StaCfg.Psm == PWR_SAVE)
7530 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7532 if(pAd->Antenna.field.RxPath == 3)
7536 else if(pAd->Antenna.field.RxPath == 2)
7540 else if(pAd->Antenna.field.RxPath == 1)
7544 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7546 pAd->StaCfg.BBPR3 = BBPR3;
7548 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7551 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7552 pAd->RalinkCounters.OneSecTxRetryOkCount +
7553 pAd->RalinkCounters.OneSecTxFailCount;
7555 if (TxTotalCnt > 50)
7557 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7558 pAd->Mlme.bLowThroughput = FALSE;
7562 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7563 pAd->Mlme.bLowThroughput = TRUE;
7569 ========================================================================
7570 Routine Description:
7571 After evaluation, check antenna link status
7574 pAd - Adapter pointer
7579 ========================================================================
7581 VOID AsicRxAntEvalTimeout(
7582 IN PVOID SystemSpecific1,
7583 IN PVOID FunctionContext,
7584 IN PVOID SystemSpecific2,
7585 IN PVOID SystemSpecific3)
7587 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7589 CHAR larger = -127, rssi0, rssi1, rssi2;
7592 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7593 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7594 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7595 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7598 if (pAd->StaCfg.Psm == PWR_SAVE)
7602 // if the traffic is low, use average rssi as the criteria
7603 if (pAd->Mlme.bLowThroughput == TRUE)
7605 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7606 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7607 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7611 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7612 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7613 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7616 if(pAd->Antenna.field.RxPath == 3)
7618 larger = max(rssi0, rssi1);
7620 if (larger > (rssi2 + 20))
7621 pAd->Mlme.RealRxPath = 2;
7623 pAd->Mlme.RealRxPath = 3;
7625 else if(pAd->Antenna.field.RxPath == 2)
7627 if (rssi0 > (rssi1 + 20))
7628 pAd->Mlme.RealRxPath = 1;
7630 pAd->Mlme.RealRxPath = 2;
7633 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7635 if(pAd->Mlme.RealRxPath == 3)
7639 else if(pAd->Mlme.RealRxPath == 2)
7643 else if(pAd->Mlme.RealRxPath == 1)
7647 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7648 pAd->StaCfg.BBPR3 = BBPR3;
7654 VOID APSDPeriodicExec(
7655 IN PVOID SystemSpecific1,
7656 IN PVOID FunctionContext,
7657 IN PVOID SystemSpecific2,
7658 IN PVOID SystemSpecific3)
7660 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7662 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7665 pAd->CommonCfg.TriggerTimerCount++;
7670 ========================================================================
7671 Routine Description:
7672 Set/reset MAC registers according to bPiggyBack parameter
7675 pAd - Adapter pointer
7676 bPiggyBack - Enable / Disable Piggy-Back
7681 ========================================================================
7683 VOID RTMPSetPiggyBack(
7684 IN PRTMP_ADAPTER pAd,
7685 IN BOOLEAN bPiggyBack)
7687 TX_LINK_CFG_STRUC TxLinkCfg;
7689 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7691 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7692 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7696 ========================================================================
7697 Routine Description:
7698 check if this entry need to switch rate automatically
7708 ========================================================================
7710 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7711 IN PRTMP_ADAPTER pAd,
7712 IN PMAC_TABLE_ENTRY pEntry)
7714 BOOLEAN result = TRUE;
7717 // only associated STA counts
7718 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7720 result = pAd->StaCfg.bAutoTxRateSwitch;
7730 BOOLEAN RTMPAutoRateSwitchCheck(
7731 IN PRTMP_ADAPTER pAd)
7733 if (pAd->StaCfg.bAutoTxRateSwitch)
7741 ========================================================================
7742 Routine Description:
7743 check if this entry need to fix tx legacy rate
7753 ========================================================================
7755 UCHAR RTMPStaFixedTxMode(
7756 IN PRTMP_ADAPTER pAd,
7757 IN PMAC_TABLE_ENTRY pEntry)
7759 UCHAR tx_mode = FIXED_TXMODE_HT;
7761 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7767 ========================================================================
7768 Routine Description:
7769 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
7779 ========================================================================
7781 VOID RTMPUpdateLegacyTxSetting(
7782 UCHAR fixed_tx_mode,
7783 PMAC_TABLE_ENTRY pEntry)
7785 HTTRANSMIT_SETTING TransmitSetting;
7787 if (fixed_tx_mode == FIXED_TXMODE_HT)
7790 TransmitSetting.word = 0;
7792 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
7793 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
7795 if (fixed_tx_mode == FIXED_TXMODE_CCK)
7797 TransmitSetting.field.MODE = MODE_CCK;
7798 // CCK mode allow MCS 0~3
7799 if (TransmitSetting.field.MCS > MCS_3)
7800 TransmitSetting.field.MCS = MCS_3;
7804 TransmitSetting.field.MODE = MODE_OFDM;
7805 // OFDM mode allow MCS 0~7
7806 if (TransmitSetting.field.MCS > MCS_7)
7807 TransmitSetting.field.MCS = MCS_7;
7810 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
7812 pEntry->HTPhyMode.word = TransmitSetting.word;
7813 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
7814 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
7819 ==========================================================================
7821 dynamic tune BBP R66 to find a balance between sensibility and
7824 IRQL = DISPATCH_LEVEL
7826 ==========================================================================
7828 VOID AsicStaBbpTuning(
7829 IN PRTMP_ADAPTER pAd)
7831 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
7834 // 2860C did not support Fase CCA, therefore can't tune
7835 if (pAd->MACVersion == 0x28600100)
7841 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
7844 if ((pAd->OpMode == OPMODE_STA)
7845 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7847 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
7848 && (pAd->bPCIclkOff == FALSE))
7850 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
7853 if (pAd->Antenna.field.RxPath > 1)
7854 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
7856 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
7858 if (pAd->LatchRfRegs.Channel <= 14)
7861 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7863 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
7864 if (OrigR66Value != R66)
7866 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7871 R66 = 0x2E + GET_LNA_GAIN(pAd);
7872 if (OrigR66Value != R66)
7874 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7881 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
7883 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7885 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
7886 if (OrigR66Value != R66)
7888 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7893 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
7894 if (OrigR66Value != R66)
7896 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7902 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7904 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
7905 if (OrigR66Value != R66)
7907 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7912 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
7913 if (OrigR66Value != R66)
7915 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7925 VOID AsicResetFromDMABusy(
7926 IN PRTMP_ADAPTER pAd)
7929 BOOLEAN bCtrl = FALSE;
7931 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
7933 // Be sure restore link control value so we can write register.
7934 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
7935 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
7937 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
7938 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
7939 RTMPusecDelay(6000);
7940 pAd->bPCIclkOff = FALSE;
7944 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7946 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7948 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7949 // Reset DMA/CPU ring index
7950 RTMPRingCleanUp(pAd, QID_AC_BK);
7951 RTMPRingCleanUp(pAd, QID_AC_BE);
7952 RTMPRingCleanUp(pAd, QID_AC_VI);
7953 RTMPRingCleanUp(pAd, QID_AC_VO);
7954 RTMPRingCleanUp(pAd, QID_HCCA);
7955 RTMPRingCleanUp(pAd, QID_MGMT);
7956 RTMPRingCleanUp(pAd, QID_RX);
7959 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7961 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7963 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
7964 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
7965 RTMPPCIeLinkCtrlSetting(pAd, 3);
7967 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
7968 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
7969 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
7973 IN PRTMP_ADAPTER pAd)
7975 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
7977 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
7978 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
7979 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
7981 // After hard-reset BBP, initialize all BBP values.
7982 NICRestoreBBPValue(pAd);
7983 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
7987 IN PRTMP_ADAPTER pAd)
7991 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
7992 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7994 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7996 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7998 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8002 IN PRTMP_ADAPTER pAd)
8004 ULONG Value1, Value2;
8007 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8008 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8011 // sum should be equals to 0xff, which is the total buffer size.
8012 if ((Value1 + Value2) < 0xff)
8014 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8015 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8017 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8019 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8021 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8025 VOID RTMPSetAGCInitValue(
8026 IN PRTMP_ADAPTER pAd,
8031 if (pAd->LatchRfRegs.Channel <= 14)
8033 R66 = 0x2E + GET_LNA_GAIN(pAd);
8034 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8038 if (BandWidth == BW_20)
8040 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8041 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8045 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8046 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8052 VOID AsicTurnOffRFClk(
8053 IN PRTMP_ADAPTER pAd,
8058 UINT32 R1 = 0, R2 = 0, R3 = 0;
8060 RTMP_RF_REGS *RFRegTable;
8062 RFRegTable = RF2850RegTable;
8064 switch (pAd->RfIcType)
8071 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8073 if (Channel == RFRegTable[index].Channel)
8075 R1 = RFRegTable[index].R1 & 0xffffdfff;
8076 R2 = RFRegTable[index].R2 & 0xfffbffff;
8077 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8079 RTMP_RF_IO_WRITE32(pAd, R1);
8080 RTMP_RF_IO_WRITE32(pAd, R2);
8082 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8083 // Set RF R2 bit18=0, R3 bit[18:19]=0
8084 //if (pAd->StaCfg.bRadio == FALSE)
8087 RTMP_RF_IO_WRITE32(pAd, R3);
8089 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8090 Channel, pAd->RfIcType, R2, R3));
8093 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8094 Channel, pAd->RfIcType, R2));
8106 VOID AsicTurnOnRFClk(
8107 IN PRTMP_ADAPTER pAd,
8112 UINT32 R1 = 0, R2 = 0, R3 = 0;
8114 RTMP_RF_REGS *RFRegTable;
8116 RFRegTable = RF2850RegTable;
8118 switch (pAd->RfIcType)
8125 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8127 if (Channel == RFRegTable[index].Channel)
8129 R3 = pAd->LatchRfRegs.R3;
8132 RTMP_RF_IO_WRITE32(pAd, R3);
8134 R1 = RFRegTable[index].R1;
8135 RTMP_RF_IO_WRITE32(pAd, R1);
8137 R2 = RFRegTable[index].R2;
8138 if (pAd->Antenna.field.TxPath == 1)
8140 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8143 if (pAd->Antenna.field.RxPath == 2)
8145 R2 |= 0x40; // write 1 to off Rxpath.
8147 else if (pAd->Antenna.field.RxPath == 1)
8149 R2 |= 0x20040; // write 1 to off RxPath
8151 RTMP_RF_IO_WRITE32(pAd, R2);
8162 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",