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 UCHAR WapiIe = IE_WAPI;
345 extern UCHAR WPA_OUI[];
347 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
349 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
350 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
352 // Reset the RFIC setting to new series
353 RTMP_RF_REGS RF2850RegTable[] = {
354 // ch R1 R2 R3(TX0~4=0) R4
355 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
356 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
357 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
358 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
359 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
360 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
361 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
362 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
363 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
364 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
365 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
366 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
367 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
368 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
370 // 802.11 UNI / HyperLan 2
371 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
372 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
373 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
374 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
375 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
376 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
377 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
378 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
379 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
380 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
381 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
382 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
385 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
387 // 2008.04.30 modified
388 // The system team has AN to improve the EVM value
389 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
390 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
391 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
392 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
394 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
395 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
396 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
397 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
398 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
399 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
400 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
401 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
402 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
403 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
404 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
405 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
408 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
409 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
410 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
411 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
412 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
413 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
414 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
417 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
418 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
419 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
420 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
421 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
422 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
423 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
425 // still lack of MMAC(Japan) ch 34,38,42,46
427 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
429 FREQUENCY_ITEM FreqItems3020[] =
431 /**************************************************/
432 // ISM : 2.4 to 2.483 GHz //
433 /**************************************************/
435 /**************************************************/
436 //-CH---N-------R---K-----------
453 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
456 //2008/07/10:KH Modified to share this variable
457 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
461 ==========================================================================
463 initialize the MLME task and its data structure (queue, spinlock,
464 timer, state machines).
469 always return NDIS_STATUS_SUCCESS
471 ==========================================================================
473 NDIS_STATUS MlmeInit(
474 IN PRTMP_ADAPTER pAd)
476 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
478 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
482 Status = MlmeQueueInit(&pAd->Mlme.Queue);
483 if(Status != NDIS_STATUS_SUCCESS)
486 pAd->Mlme.bRunning = FALSE;
487 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
490 BssTableInit(&pAd->ScanTab);
492 // init STA state machines
493 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
494 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
495 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
496 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
497 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
498 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
500 // Since we are using switch/case to implement it, the init is different from the above
501 // state machine init
502 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
505 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
507 // Init mlme periodic timer
508 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
510 // Set mlme periodic timer
511 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
513 // software-based RX Antenna diversity
514 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
518 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
520 // only PCIe cards need these two timers
521 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
522 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
528 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
534 ==========================================================================
536 main loop of the MLME
538 Mlme has to be initialized, and there are something inside the queue
540 This function is invoked from MPSetInformation and MPReceive;
541 This task guarantee only one MlmeHandler will run.
543 IRQL = DISPATCH_LEVEL
545 ==========================================================================
548 IN PRTMP_ADAPTER pAd)
550 MLME_QUEUE_ELEM *Elem = NULL;
552 // Only accept MLME and Frame from peer side, no other (control/data) frame should
553 // get into this state machine
555 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
556 if(pAd->Mlme.bRunning)
558 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
563 pAd->Mlme.bRunning = TRUE;
565 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
567 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
569 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
570 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
571 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
573 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
577 //From message type, determine which state machine I should drive
578 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
581 if (Elem->MsgType == MT2_RESET_CONF)
583 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
584 MlmeRestartStateMachine(pAd);
585 Elem->Occupied = FALSE;
591 // if dequeue success
592 switch (Elem->Machine)
594 // STA state machines
595 case ASSOC_STATE_MACHINE:
596 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
598 case AUTH_STATE_MACHINE:
599 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
601 case AUTH_RSP_STATE_MACHINE:
602 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
604 case SYNC_STATE_MACHINE:
605 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
607 case MLME_CNTL_STATE_MACHINE:
608 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
610 case WPA_PSK_STATE_MACHINE:
611 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
613 case AIRONET_STATE_MACHINE:
614 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
616 case ACTION_STATE_MACHINE:
617 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
624 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
629 Elem->Occupied = FALSE;
634 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
638 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
639 pAd->Mlme.bRunning = FALSE;
640 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
644 ==========================================================================
646 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
648 Adapter - NIC Adapter pointer
650 The MLME task will no longer work properly
654 ==========================================================================
657 IN PRTMP_ADAPTER pAd)
661 UINT32 TxPinCfg = 0x00050F0F;
664 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
666 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
668 // disable BEACON generation and other BEACON related hardware timers
669 AsicDisableSync(pAd);
673 // Cancel pending timers
674 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
675 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
676 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
677 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
678 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
679 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
681 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
683 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
684 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
689 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
690 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
694 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
697 RTMPSetLED(pAd, LED_HALT);
698 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
701 LED_CFG_STRUC LedCfg;
702 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
703 LedCfg.field.LedPolar = 0;
704 LedCfg.field.RLedMode = 0;
705 LedCfg.field.GLedMode = 0;
706 LedCfg.field.YLedMode = 0;
707 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
714 if (IS_RT3070(pAd) || IS_RT3071(pAd))
716 TxPinCfg &= 0xFFFFF0F0;
717 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
722 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
724 MlmeQueueDestroy(&pAd->Mlme.Queue);
725 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
727 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
730 VOID MlmeResetRalinkCounters(
731 IN PRTMP_ADAPTER pAd)
733 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
734 // clear all OneSecxxx counters.
735 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
736 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
737 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
738 pAd->RalinkCounters.OneSecRxOkCnt = 0;
739 pAd->RalinkCounters.OneSecTxFailCount = 0;
740 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
741 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
742 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
744 // TODO: for debug only. to be removed
745 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
746 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
747 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
748 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
749 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
750 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
751 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
752 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
753 pAd->RalinkCounters.OneSecTxDoneCount = 0;
754 pAd->RalinkCounters.OneSecRxCount = 0;
755 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
756 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
761 unsigned long rx_AMSDU;
762 unsigned long rx_Total;
765 ==========================================================================
767 This routine is executed periodically to -
768 1. Decide if it's a right time to turn on PwrMgmt bit of all
770 2. Calculate ChannelQuality based on statistics of the last
771 period, so that TX rate won't toggling very frequently between a
772 successful TX and a failed TX.
773 3. If the calculated ChannelQuality indicated current connection not
774 healthy, then a ROAMing attempt is tried here.
776 IRQL = DISPATCH_LEVEL
778 ==========================================================================
780 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
781 VOID MlmePeriodicExec(
782 IN PVOID SystemSpecific1,
783 IN PVOID FunctionContext,
784 IN PVOID SystemSpecific2,
785 IN PVOID SystemSpecific3)
788 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
792 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
793 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
794 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
795 if(pAd->StaCfg.WepStatus<2)
797 pAd->StaCfg.WpaSupplicantUP = 0;
801 pAd->StaCfg.WpaSupplicantUP = 1;
805 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
806 // Move code to here, because following code will return when radio is off
807 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
808 (pAd->StaCfg.bHardwareRadio == TRUE) &&
809 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
810 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
811 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
815 // Read GPIO pin2 as Hardware controlled radio state
816 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
819 pAd->StaCfg.bHwRadio = TRUE;
823 pAd->StaCfg.bHwRadio = FALSE;
825 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
827 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
828 if (pAd->StaCfg.bRadio == TRUE)
831 // Update extra information
832 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
837 // Update extra information
838 pAd->ExtraInfo = HW_RADIO_OFF;
845 // Do nothing if the driver is starting halt state.
846 // This might happen when timer already been fired before cancel timer with mlmehalt
847 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
848 fRTMP_ADAPTER_RADIO_OFF |
849 fRTMP_ADAPTER_RADIO_MEASUREMENT |
850 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
855 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
857 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
858 pAd->SameRxByteCount++;
861 pAd->SameRxByteCount = 0;
863 // If after BBP, still not work...need to check to reset PBF&MAC.
864 if (pAd->SameRxByteCount == 702)
866 pAd->SameRxByteCount = 0;
871 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
872 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
874 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
876 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
877 pAd->SameRxByteCount = 700;
882 // Update lastReceiveByteCount.
883 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
885 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
887 pAd->CheckDmaBusyCount = 0;
888 AsicResetFromDMABusy(pAd);
892 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
895 // Do nothing if monitor mode is on
899 if (pAd->Mlme.PeriodicRound & 0x1)
901 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
902 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
903 (STA_TGN_WIFI_ON(pAd)) &&
904 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
907 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
908 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
910 else if ((STA_TGN_WIFI_ON(pAd)) &&
911 ((pAd->MACVersion & 0xffff) == 0x0101))
913 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
914 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
919 pAd->bUpdateBcnCntDone = FALSE;
921 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
922 pAd->Mlme.PeriodicRound ++;
925 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
926 NICUpdateFifoStaCounters(pAd);
928 // execute every 500ms
929 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
931 // perform dynamic tx rate switching based on past TX history
933 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
935 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
936 MlmeDynamicTxRateSwitching(pAd);
940 // Normal 1 second Mlme PeriodicExec.
941 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
943 pAd->Mlme.OneSecPeriodicRound ++;
953 // Media status changed, report to NDIS
954 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
956 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
957 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
959 pAd->IndicateMediaState = NdisMediaStateConnected;
960 RTMP_IndicateMediaState(pAd);
965 pAd->IndicateMediaState = NdisMediaStateDisconnected;
966 RTMP_IndicateMediaState(pAd);
970 NdisGetSystemUpTime(&pAd->Mlme.Now32);
972 // add the most up-to-date h/w raw counters into software variable, so that
973 // the dynamic tuning mechanism below are based on most up-to-date information
974 NICUpdateRawCounters(pAd);
977 RT2870_WatchDog(pAd);
980 // Need statistics after read counter. So put after NICUpdateRawCounters
981 ORIBATimerTimeout(pAd);
983 // The time period for checking antenna is according to traffic
984 if (pAd->Mlme.bEnableAutoAntennaCheck)
986 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
987 pAd->RalinkCounters.OneSecTxRetryOkCount +
988 pAd->RalinkCounters.OneSecTxFailCount;
990 // dynamic adjust antenna evaluation period according to the traffic
993 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
995 AsicEvaluateRxAnt(pAd);
1000 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
1002 AsicEvaluateRxAnt(pAd);
1007 STAMlmePeriodicExec(pAd);
1009 MlmeResetRalinkCounters(pAd);
1013 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1016 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1017 // and sending CTS-to-self over and over.
1018 // Software Patch Solution:
1019 // 1. Polling debug state register 0x10F4 every one second.
1020 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1021 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1025 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1026 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1028 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1030 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1032 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1037 RT28XX_MLME_HANDLER(pAd);
1040 pAd->bUpdateBcnCntDone = FALSE;
1043 VOID STAMlmePeriodicExec(
1054 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1056 // WPA MIC error should block association attempt for 60 seconds
1057 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1058 pAd->StaCfg.bBlockAssoc = FALSE;
1063 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1064 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1065 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1066 if(pAd->StaCfg.WepStatus<2)
1068 pAd->StaCfg.WpaSupplicantUP = 0;
1072 pAd->StaCfg.WpaSupplicantUP = 1;
1076 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1078 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1080 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1082 pAd->PreMediaState = pAd->IndicateMediaState;
1086 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1087 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1088 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1089 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1090 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1091 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1093 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1099 AsicStaBbpTuning(pAd);
1101 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1102 pAd->RalinkCounters.OneSecTxRetryOkCount +
1103 pAd->RalinkCounters.OneSecTxFailCount;
1105 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1107 // update channel quality for Roaming and UI LinkQuality display
1108 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1111 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1112 // Radio is currently in noisy environment
1113 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1114 AsicAdjustTxPower(pAd);
1118 // Is PSM bit consistent with user power management policy?
1119 // This is the only place that will set PSM bit ON.
1120 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1121 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1123 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1125 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1126 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1127 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1129 RTMPSetAGCInitValue(pAd, BW_20);
1130 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1134 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1136 // When APSD is enabled, the period changes as 20 sec
1137 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1138 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1142 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1143 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1145 if (pAd->CommonCfg.bWmmCapable)
1146 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1148 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1153 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1155 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1156 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1157 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1159 // Lost AP, send disconnect & link down event
1160 LinkDown(pAd, FALSE);
1163 union iwreq_data wrqu;
1164 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1165 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1168 MlmeAutoReconnectLastSSID(pAd);
1170 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1172 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1173 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1174 MlmeAutoReconnectLastSSID(pAd);
1177 // Add auto seamless roaming
1178 if (pAd->StaCfg.bFastRoaming)
1180 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1182 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));
1184 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1186 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1190 else if (ADHOC_ON(pAd))
1193 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1194 // the "TX BEACON competition" for the entire past 1 sec.
1195 // So that even when ASIC's BEACONgen engine been blocked
1196 // by peer's BEACON due to slower system clock, this STA still can send out
1197 // minimum BEACON to tell the peer I'm alive.
1198 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1199 // EnqueueBeaconFrame(pAd); // software send BEACON
1201 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1202 // restore outgoing BEACON to support B/G-mixed mode
1203 if ((pAd->CommonCfg.Channel <= 14) &&
1204 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1205 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1206 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1208 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1209 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1210 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1211 MlmeUpdateTxRates(pAd, FALSE, 0);
1212 MakeIbssBeacon(pAd); // re-build BEACON frame
1213 AsicEnableIbssSync(pAd); // copy to on-chip memory
1214 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1217 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1219 if ((pAd->StaCfg.AdhocBGJoined) &&
1220 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1222 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1223 pAd->StaCfg.AdhocBGJoined = FALSE;
1226 if ((pAd->StaCfg.Adhoc20NJoined) &&
1227 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1229 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1230 pAd->StaCfg.Adhoc20NJoined = FALSE;
1236 if ((pAd->CommonCfg.Channel > 14)
1237 && (pAd->CommonCfg.bIEEE80211H == 1)
1238 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1240 RadarDetectPeriodic(pAd);
1243 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1244 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1246 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1247 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1249 MLME_START_REQ_STRUCT StartReq;
1251 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1252 LinkDown(pAd, FALSE);
1254 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1255 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1256 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1260 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1262 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1264 if (pEntry->ValidAsCLI == FALSE)
1267 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1268 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1272 else // no INFRA nor ADHOC connection
1275 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1276 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1277 goto SKIP_AUTO_SCAN_CONN;
1279 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1281 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1282 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1283 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1285 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1287 MLME_SCAN_REQ_STRUCT ScanReq;
1289 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1291 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1292 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1293 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1294 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1295 // Reset Missed scan number
1296 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1298 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1299 MlmeAutoReconnectLastSSID(pAd);
1301 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1303 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1306 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1310 MlmeAutoReconnectLastSSID(pAd);
1316 SKIP_AUTO_SCAN_CONN:
1318 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1320 pAd->MacTab.fAnyBASession = TRUE;
1321 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1323 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1325 pAd->MacTab.fAnyBASession = FALSE;
1326 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1334 IN PVOID SystemSpecific1,
1335 IN PVOID FunctionContext,
1336 IN PVOID SystemSpecific2,
1337 IN PVOID SystemSpecific3)
1340 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1342 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1343 RTMP_IndicateMediaState(pAd);
1344 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1347 // IRQL = DISPATCH_LEVEL
1349 IN PRTMP_ADAPTER pAd)
1351 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1352 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1354 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1356 MLME_CNTL_STATE_MACHINE,
1357 OID_802_11_BSSID_LIST_SCAN,
1360 RT28XX_MLME_HANDLER(pAd);
1364 // IRQL = DISPATCH_LEVEL
1365 VOID MlmeAutoReconnectLastSSID(
1366 IN PRTMP_ADAPTER pAd)
1370 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1371 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1372 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1374 NDIS_802_11_SSID OidSsid;
1375 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1376 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1378 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1380 MLME_CNTL_STATE_MACHINE,
1382 sizeof(NDIS_802_11_SSID),
1384 RT28XX_MLME_HANDLER(pAd);
1389 ==========================================================================
1390 Validate SSID for connection try and rescan purpose
1391 Valid SSID will have visible chars only.
1392 The valid length is from 0 to 32.
1393 IRQL = DISPATCH_LEVEL
1394 ==========================================================================
1396 BOOLEAN MlmeValidateSSID(
1402 if (SsidLen > MAX_LEN_OF_SSID)
1405 // Check each character value
1406 for (index = 0; index < SsidLen; index++)
1408 if (pSsid[index] < 0x20)
1416 VOID MlmeSelectTxRateTable(
1417 IN PRTMP_ADAPTER pAd,
1418 IN PMAC_TABLE_ENTRY pEntry,
1420 IN PUCHAR pTableSize,
1421 IN PUCHAR pInitTxRateIdx)
1425 // decide the rate table for tuning
1426 if (pAd->CommonCfg.TxRateTableSize > 0)
1428 *ppTable = RateSwitchTable;
1429 *pTableSize = RateSwitchTable[0];
1430 *pInitTxRateIdx = RateSwitchTable[1];
1435 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1437 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1439 !pAd->StaCfg.AdhocBOnlyJoined &&
1440 !pAd->StaCfg.AdhocBGJoined &&
1441 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1442 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1445 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1446 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1449 *ppTable = RateSwitchTable11N1S;
1450 *pTableSize = RateSwitchTable11N1S[0];
1451 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1454 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1456 !pAd->StaCfg.AdhocBOnlyJoined &&
1457 !pAd->StaCfg.AdhocBGJoined &&
1458 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1459 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1462 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1463 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1465 (pAd->Antenna.field.TxPath == 2))
1467 if (pAd->LatchRfRegs.Channel <= 14)
1469 *ppTable = RateSwitchTable11N2S;
1470 *pTableSize = RateSwitchTable11N2S[0];
1471 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1475 *ppTable = RateSwitchTable11N2SForABand;
1476 *pTableSize = RateSwitchTable11N2SForABand[0];
1477 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1483 if (pAd->CommonCfg.PhyMode == PHY_11B)
1485 *ppTable = RateSwitchTable11B;
1486 *pTableSize = RateSwitchTable11B[0];
1487 *pInitTxRateIdx = RateSwitchTable11B[1];
1490 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1493 if ((pEntry->RateLen == 4)
1494 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1498 // USe B Table when Only b-only Station in my IBSS .
1499 *ppTable = RateSwitchTable11B;
1500 *pTableSize = RateSwitchTable11B[0];
1501 *pInitTxRateIdx = RateSwitchTable11B[1];
1504 else if (pAd->LatchRfRegs.Channel <= 14)
1506 *ppTable = RateSwitchTable11BG;
1507 *pTableSize = RateSwitchTable11BG[0];
1508 *pInitTxRateIdx = RateSwitchTable11BG[1];
1513 *ppTable = RateSwitchTable11G;
1514 *pTableSize = RateSwitchTable11G[0];
1515 *pInitTxRateIdx = RateSwitchTable11G[1];
1521 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1522 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1524 *ppTable = RateSwitchTable11BGN1S;
1525 *pTableSize = RateSwitchTable11BGN1S[0];
1526 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1531 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1532 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1534 if (pAd->LatchRfRegs.Channel <= 14)
1536 *ppTable = RateSwitchTable11BGN2S;
1537 *pTableSize = RateSwitchTable11BGN2S[0];
1538 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1543 *ppTable = RateSwitchTable11BGN2SForABand;
1544 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1545 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1551 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1553 *ppTable = RateSwitchTable11N1S;
1554 *pTableSize = RateSwitchTable11N1S[0];
1555 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1560 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1562 if (pAd->LatchRfRegs.Channel <= 14)
1564 *ppTable = RateSwitchTable11N2S;
1565 *pTableSize = RateSwitchTable11N2S[0];
1566 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1570 *ppTable = RateSwitchTable11N2SForABand;
1571 *pTableSize = RateSwitchTable11N2SForABand[0];
1572 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1578 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1579 if ((pEntry->RateLen == 4)
1581 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1582 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1586 *ppTable = RateSwitchTable11B;
1587 *pTableSize = RateSwitchTable11B[0];
1588 *pInitTxRateIdx = RateSwitchTable11B[1];
1593 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1594 if ((pEntry->RateLen > 8)
1595 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1598 *ppTable = RateSwitchTable11BG;
1599 *pTableSize = RateSwitchTable11BG[0];
1600 *pInitTxRateIdx = RateSwitchTable11BG[1];
1605 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1606 if ((pEntry->RateLen == 8)
1607 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1610 *ppTable = RateSwitchTable11G;
1611 *pTableSize = RateSwitchTable11G[0];
1612 *pInitTxRateIdx = RateSwitchTable11G[1];
1618 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1619 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1621 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1623 *ppTable = RateSwitchTable11B;
1624 *pTableSize = RateSwitchTable11B[0];
1625 *pInitTxRateIdx = RateSwitchTable11B[1];
1627 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1629 *ppTable = RateSwitchTable11G;
1630 *pTableSize = RateSwitchTable11G[0];
1631 *pInitTxRateIdx = RateSwitchTable11G[1];
1636 *ppTable = RateSwitchTable11BG;
1637 *pTableSize = RateSwitchTable11BG[0];
1638 *pInitTxRateIdx = RateSwitchTable11BG[1];
1643 if (pAd->LatchRfRegs.Channel <= 14)
1645 if (pAd->CommonCfg.TxStream == 1)
1647 *ppTable = RateSwitchTable11N1S;
1648 *pTableSize = RateSwitchTable11N1S[0];
1649 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1650 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1654 *ppTable = RateSwitchTable11N2S;
1655 *pTableSize = RateSwitchTable11N2S[0];
1656 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1657 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1662 if (pAd->CommonCfg.TxStream == 1)
1664 *ppTable = RateSwitchTable11N1S;
1665 *pTableSize = RateSwitchTable11N1S[0];
1666 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1667 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1671 *ppTable = RateSwitchTable11N2SForABand;
1672 *pTableSize = RateSwitchTable11N2SForABand[0];
1673 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1674 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1678 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1679 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1685 ==========================================================================
1687 This routine checks if there're other APs out there capable for
1688 roaming. Caller should call this routine only when Link up in INFRA mode
1689 and channel quality is below CQI_GOOD_THRESHOLD.
1691 IRQL = DISPATCH_LEVEL
1694 ==========================================================================
1696 VOID MlmeCheckForRoaming(
1697 IN PRTMP_ADAPTER pAd,
1701 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1704 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1705 // put all roaming candidates into RoamTab, and sort in RSSI order
1706 BssTableInit(pRoamTab);
1707 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1709 pBss = &pAd->ScanTab.BssEntry[i];
1711 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1712 continue; // AP disappear
1713 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1714 continue; // RSSI too weak. forget it.
1715 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1716 continue; // skip current AP
1717 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1718 continue; // only AP with stronger RSSI is eligible for roaming
1720 // AP passing all above rules is put into roaming candidate table
1721 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1722 pRoamTab->BssNr += 1;
1725 if (pRoamTab->BssNr > 0)
1727 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1728 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1730 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1731 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1732 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1733 RT28XX_MLME_HANDLER(pAd);
1736 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1740 ==========================================================================
1742 This routine checks if there're other APs out there capable for
1743 roaming. Caller should call this routine only when link up in INFRA mode
1744 and channel quality is below CQI_GOOD_THRESHOLD.
1746 IRQL = DISPATCH_LEVEL
1749 ==========================================================================
1751 VOID MlmeCheckForFastRoaming(
1752 IN PRTMP_ADAPTER pAd,
1756 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1759 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1760 // put all roaming candidates into RoamTab, and sort in RSSI order
1761 BssTableInit(pRoamTab);
1762 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1764 pBss = &pAd->ScanTab.BssEntry[i];
1766 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1767 continue; // RSSI too weak. forget it.
1768 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1769 continue; // skip current AP
1770 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1771 continue; // skip different SSID
1772 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1773 continue; // skip AP without better RSSI
1775 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));
1776 // AP passing all above rules is put into roaming candidate table
1777 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1778 pRoamTab->BssNr += 1;
1781 if (pRoamTab->BssNr > 0)
1783 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1784 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1786 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1787 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1788 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1789 RT28XX_MLME_HANDLER(pAd);
1792 // Maybe site survey required
1795 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1797 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1798 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1799 pAd->StaCfg.ScanCnt = 2;
1800 pAd->StaCfg.LastScanTime = Now;
1805 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1809 ==========================================================================
1811 This routine calculates TxPER, RxPER of the past N-sec period. And
1812 according to the calculation result, ChannelQuality is calculated here
1813 to decide if current AP is still doing the job.
1815 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1817 StaCfg.ChannelQuality - 0..100
1819 IRQL = DISPATCH_LEVEL
1821 NOTE: This routine decide channle quality based on RX CRC error ratio.
1822 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1823 is performed right before this routine, so that this routine can decide
1824 channel quality based on the most up-to-date information
1825 ==========================================================================
1827 VOID MlmeCalculateChannelQuality(
1828 IN PRTMP_ADAPTER pAd,
1831 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1835 ULONG BeaconLostTime = BEACON_LOST_TIME;
1837 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1840 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1842 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1843 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1851 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1852 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1856 // calculate RX PER - don't take RxPER into consideration if too few sample
1858 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1862 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1865 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1867 if (INFRA_ON(pAd) &&
1868 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1869 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1871 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1872 pAd->Mlme.ChannelQuality = 0;
1879 else if (MaxRssi < -90)
1882 NorRssi = (MaxRssi + 90) * 2;
1884 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1885 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1886 TX_WEIGHTING * (100 - TxPRR) +
1887 RX_WEIGHTING* (100 - RxPER)) / 100;
1888 if (pAd->Mlme.ChannelQuality >= 100)
1889 pAd->Mlme.ChannelQuality = 100;
1895 IN PRTMP_ADAPTER pAd,
1896 IN PMAC_TABLE_ENTRY pEntry,
1897 IN PRTMP_TX_RATE_SWITCH pTxRate)
1899 UCHAR MaxMode = MODE_OFDM;
1901 MaxMode = MODE_HTGREENFIELD;
1903 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1904 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1906 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1908 if (pTxRate->CurrMCS < MCS_AUTO)
1909 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1911 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1912 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1916 // If peer adhoc is b-only mode, we can't send 11g rate.
1917 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1918 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1921 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1923 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1924 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1925 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1927 // Patch speed error in status page
1928 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1932 if (pTxRate->Mode <= MaxMode)
1933 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1935 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1936 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1938 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1940 // Reexam each bandwidth's SGI support.
1941 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1943 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1944 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1945 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1946 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1949 // Turn RTS/CTS rate to 6Mbps.
1950 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1952 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1953 if (pAd->MacTab.fAnyBASession)
1955 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1959 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1962 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1964 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1965 if (pAd->MacTab.fAnyBASession)
1967 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1971 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1974 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1976 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1979 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1981 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1984 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1985 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1986 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1987 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1989 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1990 pAd->WIFItestbed.bGreenField)
1991 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1994 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1998 ==========================================================================
2000 This routine calculates the acumulated TxPER of eaxh TxRate. And
2001 according to the calculation result, change CommonCfg.TxRate which
2002 is the stable TX Rate we expect the Radio situation could sustained.
2004 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2008 IRQL = DISPATCH_LEVEL
2011 call this routine every second
2012 ==========================================================================
2014 VOID MlmeDynamicTxRateSwitching(
2015 IN PRTMP_ADAPTER pAd)
2017 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2018 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2019 ULONG TxErrorRatio = 0;
2020 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2021 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2023 UCHAR TableSize = 0;
2024 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2025 CHAR Rssi, RssiOffset = 0;
2026 TX_STA_CNT1_STRUC StaTx1;
2027 TX_STA_CNT0_STRUC TxStaCnt0;
2028 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2029 MAC_TABLE_ENTRY *pEntry;
2032 // walk through MAC table, see if need to change AP's TX rate toward each entry
2034 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2036 pEntry = &pAd->MacTab.Content[i];
2038 // check if this entry need to switch rate automatically
2039 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2042 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2045 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2048 Rssi = RTMPMaxRssi(pAd,
2049 pAd->StaCfg.RssiSample.AvgRssi0,
2050 pAd->StaCfg.RssiSample.AvgRssi1,
2051 pAd->StaCfg.RssiSample.AvgRssi2);
2054 // Update statistic counter
2055 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2056 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2057 pAd->bUpdateBcnCntDone = TRUE;
2058 TxRetransmit = StaTx1.field.TxRetransmit;
2059 TxSuccess = StaTx1.field.TxSuccess;
2060 TxFailCount = TxStaCnt0.field.TxFailCount;
2061 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2063 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2064 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2065 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2066 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2067 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2068 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2070 // if no traffic in the past 1-sec period, don't change TX rate,
2071 // but clear all bad history. because the bad history may affect the next
2072 // Chariot throughput test
2073 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2074 pAd->RalinkCounters.OneSecTxRetryOkCount +
2075 pAd->RalinkCounters.OneSecTxFailCount;
2078 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2083 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2086 if (INFRA_ON(pAd) && (i == 1))
2087 Rssi = RTMPMaxRssi(pAd,
2088 pAd->StaCfg.RssiSample.AvgRssi0,
2089 pAd->StaCfg.RssiSample.AvgRssi1,
2090 pAd->StaCfg.RssiSample.AvgRssi2);
2092 Rssi = RTMPMaxRssi(pAd,
2093 pEntry->RssiSample.AvgRssi0,
2094 pEntry->RssiSample.AvgRssi1,
2095 pEntry->RssiSample.AvgRssi2);
2098 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2099 pEntry->OneSecTxRetryOkCount +
2100 pEntry->OneSecTxFailCount;
2103 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2106 CurrRateIdx = pEntry->CurrTxRateIndex;
2108 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2110 if (CurrRateIdx >= TableSize)
2112 CurrRateIdx = TableSize - 1;
2115 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2116 // So need to sync here.
2117 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2118 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2119 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2123 // Need to sync Real Tx rate and our record.
2124 // Then return for next DRS.
2125 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2126 pEntry->CurrTxRateIndex = InitTxRateIdx;
2127 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2129 // reset all OneSecTx counters
2130 RESET_ONE_SEC_TX_CNT(pEntry);
2134 // decide the next upgrade rate and downgrade rate, if any
2135 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2137 UpRateIdx = CurrRateIdx + 1;
2138 DownRateIdx = CurrRateIdx -1;
2140 else if (CurrRateIdx == 0)
2142 UpRateIdx = CurrRateIdx + 1;
2143 DownRateIdx = CurrRateIdx;
2145 else if (CurrRateIdx == (TableSize - 1))
2147 UpRateIdx = CurrRateIdx;
2148 DownRateIdx = CurrRateIdx - 1;
2151 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2153 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2155 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2156 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2160 TrainUp = pCurrTxRate->TrainUp;
2161 TrainDown = pCurrTxRate->TrainDown;
2164 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2167 // Keep the last time TxRateChangeAction status.
2169 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2174 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2175 // (criteria copied from RT2500 for Netopia case)
2177 if (TxTotalCnt <= 15)
2181 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2182 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2183 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2184 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2186 // check the existence and index of each needed MCS
2187 while (idx < pTable[0])
2189 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2191 if (pCurrTxRate->CurrMCS == MCS_0)
2195 else if (pCurrTxRate->CurrMCS == MCS_1)
2199 else if (pCurrTxRate->CurrMCS == MCS_2)
2203 else if (pCurrTxRate->CurrMCS == MCS_3)
2207 else if (pCurrTxRate->CurrMCS == MCS_4)
2211 else if (pCurrTxRate->CurrMCS == MCS_5)
2215 else if (pCurrTxRate->CurrMCS == MCS_6)
2219 //else if (pCurrTxRate->CurrMCS == MCS_7)
2220 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2224 else if (pCurrTxRate->CurrMCS == MCS_12)
2228 else if (pCurrTxRate->CurrMCS == MCS_13)
2232 else if (pCurrTxRate->CurrMCS == MCS_14)
2236 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
2240 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2244 else if (pCurrTxRate->CurrMCS == MCS_21)
2248 else if (pCurrTxRate->CurrMCS == MCS_22)
2252 else if (pCurrTxRate->CurrMCS == MCS_23)
2259 if (pAd->LatchRfRegs.Channel <= 14)
2261 if (pAd->NicConfig2.field.ExternalLNAForG)
2272 if (pAd->NicConfig2.field.ExternalLNAForA)
2283 if ((pTable == RateSwitchTable11BGN3S) ||
2284 (pTable == RateSwitchTable11N3S) ||
2285 (pTable == RateSwitchTable))
2286 {// N mode with 3 stream // 3*3
2287 if (MCS23 && (Rssi >= -70))
2289 else if (MCS22 && (Rssi >= -72))
2291 else if (MCS21 && (Rssi >= -76))
2293 else if (MCS20 && (Rssi >= -78))
2295 else if (MCS4 && (Rssi >= -82))
2297 else if (MCS3 && (Rssi >= -84))
2299 else if (MCS2 && (Rssi >= -86))
2301 else if (MCS1 && (Rssi >= -88))
2306 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2307 {// N mode with 2 stream
2308 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2310 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2312 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2314 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2316 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2318 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2320 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2322 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2327 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2328 {// N mode with 1 stream
2329 if (MCS7 && (Rssi > (-72+RssiOffset)))
2331 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2333 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2335 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2337 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2339 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2341 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2348 if (MCS7 && (Rssi > -70))
2350 else if (MCS6 && (Rssi > -74))
2352 else if (MCS5 && (Rssi > -78))
2354 else if (MCS4 && (Rssi > -82))
2356 else if (MCS4 == 0) // for B-only mode
2358 else if (MCS3 && (Rssi > -85))
2360 else if (MCS2 && (Rssi > -87))
2362 else if (MCS1 && (Rssi > -90))
2369 pEntry->CurrTxRateIndex = TxRateIdx;
2370 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2371 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2374 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2375 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2376 pEntry->fLastSecAccordingRSSI = TRUE;
2377 // reset all OneSecTx counters
2378 RESET_ONE_SEC_TX_CNT(pEntry);
2383 if (pEntry->fLastSecAccordingRSSI == TRUE)
2385 pEntry->fLastSecAccordingRSSI = FALSE;
2386 pEntry->LastSecTxRateChangeAction = 0;
2387 // reset all OneSecTx counters
2388 RESET_ONE_SEC_TX_CNT(pEntry);
2395 BOOLEAN bTrainUpDown = FALSE;
2397 pEntry->CurrTxRateStableTime ++;
2399 // downgrade TX quality if PER >= Rate-Down threshold
2400 if (TxErrorRatio >= TrainDown)
2402 bTrainUpDown = TRUE;
2403 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2405 // upgrade TX quality if PER <= Rate-Up threshold
2406 else if (TxErrorRatio <= TrainUp)
2408 bTrainUpDown = TRUE;
2409 bUpgradeQuality = TRUE;
2410 if (pEntry->TxQuality[CurrRateIdx])
2411 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2413 if (pEntry->TxRateUpPenalty)
2414 pEntry->TxRateUpPenalty --;
2415 else if (pEntry->TxQuality[UpRateIdx])
2416 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2419 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2423 // perform DRS - consider TxRate Down first, then rate up.
2424 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2426 pEntry->CurrTxRateIndex = DownRateIdx;
2428 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2430 pEntry->CurrTxRateIndex = UpRateIdx;
2435 // if rate-up happen, clear all bad history of all TX rates
2436 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2438 pEntry->CurrTxRateStableTime = 0;
2439 pEntry->TxRateUpPenalty = 0;
2440 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2441 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2442 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2445 // For TxRate fast train up
2447 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2449 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2451 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2453 bTxRateChanged = TRUE;
2455 // if rate-down happen, only clear DownRate's bad history
2456 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2458 pEntry->CurrTxRateStableTime = 0;
2459 pEntry->TxRateUpPenalty = 0; // no penalty
2460 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2461 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2462 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2465 // For TxRate fast train down
2467 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2469 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2471 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2473 bTxRateChanged = TRUE;
2477 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2478 bTxRateChanged = FALSE;
2481 pEntry->LastTxOkCount = TxSuccess;
2483 // reset all OneSecTx counters
2484 RESET_ONE_SEC_TX_CNT(pEntry);
2486 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2487 if (bTxRateChanged && pNextTxRate)
2489 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2495 ========================================================================
2496 Routine Description:
2497 Station side, Auto TxRate faster train up timer call back function.
2500 SystemSpecific1 - Not used.
2501 FunctionContext - Pointer to our Adapter context.
2502 SystemSpecific2 - Not used.
2503 SystemSpecific3 - Not used.
2508 ========================================================================
2510 VOID StaQuickResponeForRateUpExec(
2511 IN PVOID SystemSpecific1,
2512 IN PVOID FunctionContext,
2513 IN PVOID SystemSpecific2,
2514 IN PVOID SystemSpecific3)
2516 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2517 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2519 ULONG TxErrorRatio = 0;
2521 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2524 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2526 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2528 UCHAR TableSize = 0;
2529 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2530 TX_STA_CNT1_STRUC StaTx1;
2531 TX_STA_CNT0_STRUC TxStaCnt0;
2533 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2534 MAC_TABLE_ENTRY *pEntry;
2537 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2540 // walk through MAC table, see if need to change AP's TX rate toward each entry
2542 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2544 pEntry = &pAd->MacTab.Content[i];
2546 // check if this entry need to switch rate automatically
2547 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2551 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2552 if (pAd->Antenna.field.TxPath > 1)
2553 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2555 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2558 if (INFRA_ON(pAd) && (i == 1))
2559 Rssi = RTMPMaxRssi(pAd,
2560 pAd->StaCfg.RssiSample.AvgRssi0,
2561 pAd->StaCfg.RssiSample.AvgRssi1,
2562 pAd->StaCfg.RssiSample.AvgRssi2);
2564 Rssi = RTMPMaxRssi(pAd,
2565 pEntry->RssiSample.AvgRssi0,
2566 pEntry->RssiSample.AvgRssi1,
2567 pEntry->RssiSample.AvgRssi2);
2570 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2572 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2574 // decide the next upgrade rate and downgrade rate, if any
2575 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2577 UpRateIdx = CurrRateIdx + 1;
2578 DownRateIdx = CurrRateIdx -1;
2580 else if (CurrRateIdx == 0)
2582 UpRateIdx = CurrRateIdx + 1;
2583 DownRateIdx = CurrRateIdx;
2585 else if (CurrRateIdx == (TableSize - 1))
2587 UpRateIdx = CurrRateIdx;
2588 DownRateIdx = CurrRateIdx - 1;
2591 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2593 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2595 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2596 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2600 TrainUp = pCurrTxRate->TrainUp;
2601 TrainDown = pCurrTxRate->TrainDown;
2604 if (pAd->MacTab.Size == 1)
2606 // Update statistic counter
2607 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2608 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2610 TxRetransmit = StaTx1.field.TxRetransmit;
2611 TxSuccess = StaTx1.field.TxSuccess;
2612 TxFailCount = TxStaCnt0.field.TxFailCount;
2613 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2615 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2616 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2617 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2618 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2619 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2620 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2623 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2627 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2628 pEntry->OneSecTxRetryOkCount +
2629 pEntry->OneSecTxFailCount;
2632 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2637 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2638 // (criteria copied from RT2500 for Netopia case)
2640 if (TxTotalCnt <= 12)
2642 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2643 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2645 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2647 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2648 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2650 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2652 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2655 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2661 ULONG OneSecTxNoRetryOKRationCount;
2663 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2668 // downgrade TX quality if PER >= Rate-Down threshold
2669 if (TxErrorRatio >= TrainDown)
2671 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2674 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2676 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2678 // perform DRS - consider TxRate Down first, then rate up.
2679 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2681 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2683 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2684 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2689 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2691 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2695 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2697 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2702 // if rate-up happen, clear all bad history of all TX rates
2703 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2705 pAd->DrsCounters.TxRateUpPenalty = 0;
2706 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2707 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2709 bTxRateChanged = TRUE;
2712 // if rate-down happen, only clear DownRate's bad history
2713 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2715 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2717 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2718 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2719 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2721 bTxRateChanged = TRUE;
2726 bTxRateChanged = FALSE;
2729 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2730 if (bTxRateChanged && pNextTxRate)
2732 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2738 ==========================================================================
2740 This routine is executed periodically inside MlmePeriodicExec() after
2741 association with an AP.
2742 It checks if StaCfg.Psm is consistent with user policy (recorded in
2743 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2744 there're some conditions to consider:
2745 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2746 the time when Mibss==TRUE
2747 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2748 if outgoing traffic available in TxRing or MgmtRing.
2750 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2752 IRQL = DISPATCH_LEVEL
2754 ==========================================================================
2756 VOID MlmeCheckPsmChange(
2757 IN PRTMP_ADAPTER pAd,
2763 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2764 // 2. user wants either MAX_PSP or FAST_PSP
2765 // 3. but current psm is not in PWR_SAVE
2766 // 4. CNTL state machine is not doing SCANning
2767 // 5. no TX SUCCESS event for the past 1-sec period
2768 #ifdef NDIS51_MINIPORT
2769 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2770 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2773 PowerMode = pAd->StaCfg.WindowsPowerMode;
2775 if (INFRA_ON(pAd) &&
2776 (PowerMode != Ndis802_11PowerModeCAM) &&
2777 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2779 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2781 #if !defined(RT2860) && !defined(RT30xx)
2782 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2786 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2787 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2788 MlmeSetPsmBit(pAd, PWR_SAVE);
2789 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2791 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2795 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2800 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2801 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2802 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2803 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2805 // add by johnli, use Rx OK data count per second to calculate throughput
2806 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2807 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2808 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2810 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2812 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2813 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2815 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2817 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2820 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2821 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2822 MlmeSetPsmBit(pAd, PWR_SAVE);
2823 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2825 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2829 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2836 // IRQL = PASSIVE_LEVEL
2837 // IRQL = DISPATCH_LEVEL
2839 IN PRTMP_ADAPTER pAd,
2842 AUTO_RSP_CFG_STRUC csr4;
2844 pAd->StaCfg.Psm = psm;
2845 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2846 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2847 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2849 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2853 // IRQL = DISPATCH_LEVEL
2854 VOID MlmeSetTxPreamble(
2855 IN PRTMP_ADAPTER pAd,
2856 IN USHORT TxPreamble)
2858 AUTO_RSP_CFG_STRUC csr4;
2861 // Always use Long preamble before verifiation short preamble functionality works well.
2862 // Todo: remove the following line if short preamble functionality works
2864 //TxPreamble = Rt802_11PreambleLong;
2866 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2867 if (TxPreamble == Rt802_11PreambleLong)
2869 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2870 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2871 csr4.field.AutoResponderPreamble = 0;
2875 // NOTE: 1Mbps should always use long preamble
2876 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2877 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2878 csr4.field.AutoResponderPreamble = 1;
2881 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2885 ==========================================================================
2887 Update basic rate bitmap
2888 ==========================================================================
2891 VOID UpdateBasicRateBitmap(
2892 IN PRTMP_ADAPTER pAdapter)
2895 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2896 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2897 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2898 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2899 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2902 /* if A mode, always use fix BasicRateBitMap */
2903 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2904 if (pAdapter->CommonCfg.Channel > 14)
2905 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2908 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2910 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2914 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2920 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2922 if (bitmap & (1 << i))
2924 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2926 if (sup_p[j] == rate[i])
2931 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2933 if (ext_p[j] == rate[i])
2939 } /* End of UpdateBasicRateBitmap */
2941 // IRQL = PASSIVE_LEVEL
2942 // IRQL = DISPATCH_LEVEL
2943 // bLinkUp is to identify the inital link speed.
2944 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2945 VOID MlmeUpdateTxRates(
2946 IN PRTMP_ADAPTER pAd,
2951 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2952 UCHAR MinSupport = RATE_54;
2953 ULONG BasicRateBitmap = 0;
2954 UCHAR CurrBasicRate = RATE_1;
2955 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2956 PHTTRANSMIT_SETTING pHtPhy = NULL;
2957 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2958 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2959 BOOLEAN *auto_rate_cur_p;
2960 UCHAR HtMcs = MCS_AUTO;
2962 // find max desired rate
2963 UpdateBasicRateBitmap(pAd);
2966 auto_rate_cur_p = NULL;
2967 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2969 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2971 case 2: Rate = RATE_1; num++; break;
2972 case 4: Rate = RATE_2; num++; break;
2973 case 11: Rate = RATE_5_5; num++; break;
2974 case 22: Rate = RATE_11; num++; break;
2975 case 12: Rate = RATE_6; num++; break;
2976 case 18: Rate = RATE_9; num++; break;
2977 case 24: Rate = RATE_12; num++; break;
2978 case 36: Rate = RATE_18; num++; break;
2979 case 48: Rate = RATE_24; num++; break;
2980 case 72: Rate = RATE_36; num++; break;
2981 case 96: Rate = RATE_48; num++; break;
2982 case 108: Rate = RATE_54; num++; break;
2983 //default: Rate = RATE_1; break;
2985 if (MaxDesire < Rate) MaxDesire = Rate;
2988 //===========================================================================
2989 //===========================================================================
2991 pHtPhy = &pAd->StaCfg.HTPhyMode;
2992 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2993 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2995 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2996 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2998 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2999 (pAd->CommonCfg.PhyMode == PHY_11B) &&
3000 (MaxDesire > RATE_11))
3002 MaxDesire = RATE_11;
3006 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
3007 pMinHtPhy->word = 0;
3008 pMaxHtPhy->word = 0;
3011 // Auto rate switching is enabled only if more than one DESIRED RATES are
3012 // specified; otherwise disabled
3015 *auto_rate_cur_p = FALSE;
3019 *auto_rate_cur_p = TRUE;
3023 if (HtMcs != MCS_AUTO)
3025 *auto_rate_cur_p = FALSE;
3029 *auto_rate_cur_p = TRUE;
3033 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3035 pSupRate = &pAd->StaActive.SupRate[0];
3036 pExtRate = &pAd->StaActive.ExtRate[0];
3037 SupRateLen = pAd->StaActive.SupRateLen;
3038 ExtRateLen = pAd->StaActive.ExtRateLen;
3042 pSupRate = &pAd->CommonCfg.SupRate[0];
3043 pExtRate = &pAd->CommonCfg.ExtRate[0];
3044 SupRateLen = pAd->CommonCfg.SupRateLen;
3045 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3048 // find max supported rate
3049 for (i=0; i<SupRateLen; i++)
3051 switch (pSupRate[i] & 0x7f)
3053 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3054 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3055 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3056 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3057 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3058 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3059 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3060 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3061 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3062 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3063 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3064 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3065 default: Rate = RATE_1; break;
3067 if (MaxSupport < Rate) MaxSupport = Rate;
3069 if (MinSupport > Rate) MinSupport = Rate;
3072 for (i=0; i<ExtRateLen; i++)
3074 switch (pExtRate[i] & 0x7f)
3076 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3077 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3078 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3079 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3080 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3081 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3082 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3083 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3084 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3085 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3086 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3087 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3088 default: Rate = RATE_1; break;
3090 if (MaxSupport < Rate) MaxSupport = Rate;
3092 if (MinSupport > Rate) MinSupport = Rate;
3095 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3097 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3098 // the DURATION field of outgoing uniicast DATA/MGMT frame
3099 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3101 if (BasicRateBitmap & (0x01 << i))
3102 CurrBasicRate = (UCHAR)i;
3103 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3106 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3107 // max tx rate = min {max desire rate, max supported rate}
3108 if (MaxSupport < MaxDesire)
3109 pAd->CommonCfg.MaxTxRate = MaxSupport;
3111 pAd->CommonCfg.MaxTxRate = MaxDesire;
3113 pAd->CommonCfg.MinTxRate = MinSupport;
3114 if (*auto_rate_cur_p)
3118 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3120 if (bLinkUp == TRUE)
3121 pAd->CommonCfg.TxRate = RATE_24;
3123 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3126 pAd->CommonCfg.TxRate = RATE_11;
3128 pAd->CommonCfg.TxRate = RATE_24;
3130 // should never exceed MaxTxRate (consider 11B-only mode)
3131 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3132 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3134 pAd->CommonCfg.TxRateIndex = 0;
3138 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3139 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3140 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3142 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3143 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3144 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3145 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3148 if (pAd->CommonCfg.TxRate <= RATE_11)
3150 pMaxHtPhy->field.MODE = MODE_CCK;
3151 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3152 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3156 pMaxHtPhy->field.MODE = MODE_OFDM;
3157 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3158 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3159 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3161 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3164 pHtPhy->word = (pMaxHtPhy->word);
3165 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3167 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3168 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3169 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3173 switch (pAd->CommonCfg.PhyMode)
3175 case PHY_11BG_MIXED:
3177 case PHY_11BGN_MIXED:
3178 pAd->CommonCfg.MlmeRate = RATE_1;
3179 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3180 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3181 pAd->CommonCfg.RtsRate = RATE_11;
3185 case PHY_11AGN_MIXED:
3186 case PHY_11GN_MIXED:
3188 case PHY_11AN_MIXED:
3190 pAd->CommonCfg.MlmeRate = RATE_6;
3191 pAd->CommonCfg.RtsRate = RATE_6;
3192 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3193 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3195 case PHY_11ABG_MIXED:
3196 case PHY_11ABGN_MIXED:
3197 if (pAd->CommonCfg.Channel <= 14)
3199 pAd->CommonCfg.MlmeRate = RATE_1;
3200 pAd->CommonCfg.RtsRate = RATE_1;
3201 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3202 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3206 pAd->CommonCfg.MlmeRate = RATE_6;
3207 pAd->CommonCfg.RtsRate = RATE_6;
3208 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3209 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3213 pAd->CommonCfg.MlmeRate = RATE_6;
3214 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3215 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3216 pAd->CommonCfg.RtsRate = RATE_1;
3220 // Keep Basic Mlme Rate.
3222 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3223 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3224 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3226 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3227 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3230 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3231 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3232 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3233 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3234 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3235 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3236 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 ));
3240 ==========================================================================
3242 This function update HT Rate setting.
3243 Input Wcid value is valid for 2 case :
3244 1. it's used for Station in infra mode that copy AP rate to Mactable.
3245 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3247 IRQL = DISPATCH_LEVEL
3249 ==========================================================================
3251 VOID MlmeUpdateHtTxRates(
3252 IN PRTMP_ADAPTER pAd,
3255 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3257 RT_HT_CAPABILITY *pRtHtCap = NULL;
3258 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3261 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3262 PHTTRANSMIT_SETTING pHtPhy = NULL;
3263 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3264 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3265 BOOLEAN *auto_rate_cur_p;
3267 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3269 auto_rate_cur_p = NULL;
3272 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3273 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3274 pHtPhy = &pAd->StaCfg.HTPhyMode;
3275 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3276 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3278 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3281 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3283 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3286 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3287 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3288 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3289 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3290 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3291 pMaxHtPhy->field.STBC = STBC_USE;
3293 pMaxHtPhy->field.STBC = STBC_NONE;
3297 if (pDesireHtPhy->bHtEnable == FALSE)
3300 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3301 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3302 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3303 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3304 pMaxHtPhy->field.STBC = STBC_USE;
3306 pMaxHtPhy->field.STBC = STBC_NONE;
3309 // Decide MAX ht rate.
3310 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3311 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3313 pMaxHtPhy->field.MODE = MODE_HTMIX;
3315 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3316 pMaxHtPhy->field.BW = BW_40;
3318 pMaxHtPhy->field.BW = BW_20;
3320 if (pMaxHtPhy->field.BW == BW_20)
3321 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3323 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3325 for (i=23; i>=0; i--) // 3*3
3328 bitmask = (1<<(i-(j*8)));
3330 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3332 pMaxHtPhy->field.MCS = i;
3340 // Copy MIN ht rate. rt2860???
3341 pMinHtPhy->field.BW = BW_20;
3342 pMinHtPhy->field.MCS = 0;
3343 pMinHtPhy->field.STBC = 0;
3344 pMinHtPhy->field.ShortGI = 0;
3345 //If STA assigns fixed rate. update to fixed here.
3346 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3348 if (pDesireHtPhy->MCSSet[4] != 0)
3350 pMaxHtPhy->field.MCS = 32;
3351 pMinHtPhy->field.MCS = 32;
3352 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3355 for (i=23; (CHAR)i >= 0; i--) // 3*3
3358 bitmask = (1<<(i-(j*8)));
3359 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3361 pMaxHtPhy->field.MCS = i;
3362 pMinHtPhy->field.MCS = i;
3371 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3372 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3373 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3374 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3375 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3377 // use default now. rt2860
3378 if (pDesireHtPhy->MCSSet[0] != 0xff)
3379 *auto_rate_cur_p = FALSE;
3381 *auto_rate_cur_p = TRUE;
3383 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3384 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3385 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3386 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3389 // IRQL = DISPATCH_LEVEL
3391 IN PRTMP_ADAPTER pAd)
3393 RT28XX_MLME_RADIO_OFF(pAd);
3396 // IRQL = DISPATCH_LEVEL
3398 IN PRTMP_ADAPTER pAd)
3400 RT28XX_MLME_RADIO_ON(pAd);
3403 // ===========================================================================================
3405 // ===========================================================================================
3408 /*! \brief initialize BSS table
3409 * \param p_tab pointer to the table
3414 IRQL = PASSIVE_LEVEL
3415 IRQL = DISPATCH_LEVEL
3424 Tab->BssOverlapNr = 0;
3425 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3427 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3428 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3433 IN PRTMP_ADAPTER pAd,
3438 Tab->numAsOriginator = 0;
3439 Tab->numAsRecipient = 0;
3440 NdisAllocateSpinLock(&pAd->BATabLock);
3441 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3443 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3444 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3446 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3448 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3452 /*! \brief search the BSS table by SSID
3453 * \param p_tab pointer to the bss table
3454 * \param ssid SSID string
3455 * \return index of the table, BSS_NOT_FOUND if not in the table
3458 * \note search by sequential search
3460 IRQL = DISPATCH_LEVEL
3463 ULONG BssTableSearch(
3470 for (i = 0; i < Tab->BssNr; i++)
3473 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3474 // We should distinguish this case.
3476 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3477 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3478 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3483 return (ULONG)BSS_NOT_FOUND;
3486 ULONG BssSsidTableSearch(
3495 for (i = 0; i < Tab->BssNr; i++)
3498 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3499 // We should distinguish this case.
3501 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3502 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3503 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3504 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3509 return (ULONG)BSS_NOT_FOUND;
3512 ULONG BssTableSearchWithSSID(
3521 for (i = 0; i < Tab->BssNr; i++)
3523 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3524 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3525 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3526 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3527 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3528 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3533 return (ULONG)BSS_NOT_FOUND;
3536 // IRQL = DISPATCH_LEVEL
3537 VOID BssTableDeleteEntry(
3538 IN OUT BSS_TABLE *Tab,
3544 for (i = 0; i < Tab->BssNr; i++)
3546 if ((Tab->BssEntry[i].Channel == Channel) &&
3547 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3549 for (j = i; j < Tab->BssNr - 1; j++)
3551 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3553 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3561 ========================================================================
3562 Routine Description:
3563 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3566 // IRQL = DISPATCH_LEVEL
3567 ========================================================================
3569 VOID BATableDeleteORIEntry(
3570 IN OUT PRTMP_ADAPTER pAd,
3571 IN BA_ORI_ENTRY *pBAORIEntry)
3574 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3576 NdisAcquireSpinLock(&pAd->BATabLock);
3577 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3579 pAd->BATable.numAsOriginator -= 1;
3580 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3581 // Erase Bitmap flag.
3583 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3584 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3585 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3586 pBAORIEntry->Token = 1;
3587 // Not clear Sequence here.
3588 NdisReleaseSpinLock(&pAd->BATabLock);
3598 IRQL = DISPATCH_LEVEL
3602 IN PRTMP_ADAPTER pAd,
3603 OUT BSS_ENTRY *pBss,
3608 IN USHORT BeaconPeriod,
3609 IN PCF_PARM pCfParm,
3611 IN USHORT CapabilityInfo,
3613 IN UCHAR SupRateLen,
3615 IN UCHAR ExtRateLen,
3616 IN HT_CAPABILITY_IE *pHtCapability,
3617 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3618 IN UCHAR HtCapabilityLen,
3619 IN UCHAR AddHtInfoLen,
3620 IN UCHAR NewExtChanOffset,
3623 IN LARGE_INTEGER TimeStamp,
3625 IN PEDCA_PARM pEdcaParm,
3626 IN PQOS_CAPABILITY_PARM pQosCapability,
3627 IN PQBSS_LOAD_PARM pQbssLoad,
3628 IN USHORT LengthVIE,
3629 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3631 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3632 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3636 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3637 // Or send beacon /probe response with SSID len matching real SSID length,
3638 // but SSID is all zero. such as "00-00-00-00" with length 4.
3639 // We have to prevent this case overwrite correct table
3640 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3642 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3643 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3644 pBss->SsidLen = SsidLen;
3650 pBss->BssType = BssType;
3651 pBss->BeaconPeriod = BeaconPeriod;
3652 if (BssType == BSS_INFRA)
3654 if (pCfParm->bValid)
3656 pBss->CfpCount = pCfParm->CfpCount;
3657 pBss->CfpPeriod = pCfParm->CfpPeriod;
3658 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3659 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3664 pBss->AtimWin = AtimWin;
3667 pBss->CapabilityInfo = CapabilityInfo;
3668 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3669 // Combine with AuthMode, they will decide the connection methods.
3670 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3671 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3672 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3673 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3675 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3676 pBss->SupRateLen = SupRateLen;
3677 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3678 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3679 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3680 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3681 pBss->NewExtChanOffset = NewExtChanOffset;
3682 pBss->ExtRateLen = ExtRateLen;
3683 pBss->Channel = Channel;
3684 pBss->CentralChannel = Channel;
3686 // Update CkipFlag. if not exists, the value is 0x0
3687 pBss->CkipFlag = CkipFlag;
3689 // New for microsoft Fixed IEs
3690 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3691 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3692 pBss->FixIEs.Capabilities = CapabilityInfo;
3694 // New for microsoft Variable IEs
3697 pBss->VarIELen = LengthVIE;
3698 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3705 pBss->AddHtInfoLen = 0;
3706 pBss->HtCapabilityLen = 0;
3708 if (HtCapabilityLen> 0)
3710 pBss->HtCapabilityLen = HtCapabilityLen;
3711 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3712 if (AddHtInfoLen > 0)
3714 pBss->AddHtInfoLen = AddHtInfoLen;
3715 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3717 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3719 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3721 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3723 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3728 BssCipherParse(pBss);
3732 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3734 pBss->EdcaParm.bValid = FALSE;
3736 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3738 pBss->QosCapability.bValid = FALSE;
3740 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3742 pBss->QbssLoad.bValid = FALSE;
3749 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3750 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3752 pEid = (PEID_STRUCT) pVIE;
3754 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3759 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3761 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3763 pBss->WpaIE.IELen = 0;
3766 pBss->WpaIE.IELen = pEid->Len + 2;
3767 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3771 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3773 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3775 pBss->RsnIE.IELen = 0;
3778 pBss->RsnIE.IELen = pEid->Len + 2;
3779 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3783 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3784 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3790 * \brief insert an entry into the bss table
3791 * \param p_tab The BSS table
3792 * \param Bssid BSSID
3794 * \param ssid_len Length of SSID
3796 * \param beacon_period
3803 * \param channel_idx
3807 * \note If SSID is identical, the old entry will be replaced by the new one
3809 IRQL = DISPATCH_LEVEL
3812 ULONG BssTableSetEntry(
3813 IN PRTMP_ADAPTER pAd,
3819 IN USHORT BeaconPeriod,
3822 IN USHORT CapabilityInfo,
3824 IN UCHAR SupRateLen,
3826 IN UCHAR ExtRateLen,
3827 IN HT_CAPABILITY_IE *pHtCapability,
3828 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3829 IN UCHAR HtCapabilityLen,
3830 IN UCHAR AddHtInfoLen,
3831 IN UCHAR NewExtChanOffset,
3834 IN LARGE_INTEGER TimeStamp,
3836 IN PEDCA_PARM pEdcaParm,
3837 IN PQOS_CAPABILITY_PARM pQosCapability,
3838 IN PQBSS_LOAD_PARM pQbssLoad,
3839 IN USHORT LengthVIE,
3840 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3844 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3845 if (Idx == BSS_NOT_FOUND)
3847 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3850 // It may happen when BSS Table was full.
3851 // The desired AP will not be added into BSS Table
3852 // In this case, if we found the desired AP then overwrite BSS Table.
3854 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3856 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3857 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3859 Idx = Tab->BssOverlapNr;
3860 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3861 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3862 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3863 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3869 return BSS_NOT_FOUND;
3873 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3874 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3875 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3881 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3882 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3883 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3886 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3887 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3888 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3897 // IRQL = DISPATCH_LEVEL
3898 VOID BssTableSsidSort(
3899 IN PRTMP_ADAPTER pAd,
3900 OUT BSS_TABLE *OutTab,
3905 BssTableInit(OutTab);
3907 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3909 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3910 BOOLEAN bIsHiddenApIncluded = FALSE;
3912 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3913 (pAd->MlmeAux.Channel > 14) &&
3914 RadarChannelCheck(pAd, pInBss->Channel))
3918 bIsHiddenApIncluded = TRUE;
3921 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3922 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3924 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3926 // 2.4G/5G N only mode
3927 if ((pInBss->HtCapabilityLen == 0) &&
3928 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3930 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3935 // Check the Authmode first
3936 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3938 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3939 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3943 // Check cipher suite, AP must have more secured cipher than station setting
3944 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3946 // If it's not mixed mode, we should only let BSS pass with the same encryption
3947 if (pInBss->WPA.bMixMode == FALSE)
3948 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3951 // check group cipher
3953 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3954 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3955 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3958 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3962 // check pairwise cipher, skip if none matched
3963 // If profile set to AES, let it pass without question.
3964 // If profile set to TKIP, we must find one mateched
3965 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3966 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3967 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3970 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3972 // If it's not mixed mode, we should only let BSS pass with the same encryption
3973 if (pInBss->WPA2.bMixMode == FALSE)
3974 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3977 // check group cipher
3979 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3980 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3981 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3984 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3988 // check pairwise cipher, skip if none matched
3989 // If profile set to AES, let it pass without question.
3990 // If profile set to TKIP, we must find one mateched
3991 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3992 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3993 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3997 // Bss Type matched, SSID matched.
3998 // We will check wepstatus for qualification Bss
3999 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4001 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4003 // For the SESv2 case, we will not qualify WepStatus.
4009 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4010 // It definitely will fail. So, skip it.
4011 // CCX also require not even try to connect it!!
4015 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4016 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4017 if ((pInBss->CentralChannel != pInBss->Channel) &&
4018 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4020 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4022 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4024 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4028 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4035 // copy matching BSS from InTab to OutTab
4036 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4040 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4042 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4044 // 2.4G/5G N only mode
4045 if ((pInBss->HtCapabilityLen == 0) &&
4046 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4048 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4053 // Check the Authmode first
4054 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4056 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4057 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4061 // Check cipher suite, AP must have more secured cipher than station setting
4062 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4064 // If it's not mixed mode, we should only let BSS pass with the same encryption
4065 if (pInBss->WPA.bMixMode == FALSE)
4066 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4069 // check group cipher
4070 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4073 // check pairwise cipher, skip if none matched
4074 // If profile set to AES, let it pass without question.
4075 // If profile set to TKIP, we must find one mateched
4076 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4077 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4078 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4081 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4083 // If it's not mixed mode, we should only let BSS pass with the same encryption
4084 if (pInBss->WPA2.bMixMode == FALSE)
4085 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4088 // check group cipher
4089 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4092 // check pairwise cipher, skip if none matched
4093 // If profile set to AES, let it pass without question.
4094 // If profile set to TKIP, we must find one mateched
4095 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4096 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4097 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4101 // Bss Type matched, SSID matched.
4102 // We will check wepstatus for qualification Bss
4103 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4106 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4107 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4108 if ((pInBss->CentralChannel != pInBss->Channel) &&
4109 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4111 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4113 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4115 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4119 // copy matching BSS from InTab to OutTab
4120 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4125 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4129 BssTableSortByRssi(OutTab);
4133 // IRQL = DISPATCH_LEVEL
4134 VOID BssTableSortByRssi(
4135 IN OUT BSS_TABLE *OutTab)
4140 for (i = 0; i < OutTab->BssNr - 1; i++)
4142 for (j = i+1; j < OutTab->BssNr; j++)
4144 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4146 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4147 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4148 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4154 VOID BssCipherParse(
4155 IN OUT PBSS_ENTRY pBss)
4159 PRSN_IE_HEADER_STRUCT pRsnHeader;
4160 PCIPHER_SUITE_STRUCT pCipher;
4161 PAKM_SUITE_STRUCT pAKM;
4164 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4167 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4171 pBss->WepStatus = Ndis802_11WEPEnabled;
4175 pBss->WepStatus = Ndis802_11WEPDisabled;
4177 // Set default to disable & open authentication before parsing variable IE
4178 pBss->AuthMode = Ndis802_11AuthModeOpen;
4179 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4182 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4183 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4184 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4185 pBss->WPA.RsnCapability = 0;
4186 pBss->WPA.bMixMode = FALSE;
4188 // Init WPA2 setting
4189 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4190 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4191 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4192 pBss->WPA2.RsnCapability = 0;
4193 pBss->WPA2.bMixMode = FALSE;
4196 Length = (INT) pBss->VarIELen;
4200 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4201 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4202 pEid = (PEID_STRUCT) pTmp;
4206 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4207 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4213 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4214 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4215 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4216 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4219 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4220 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4221 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4224 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4225 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4226 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4232 // if Cisco IE_WPA, break
4235 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4240 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4242 // if unsupported vendor specific IE
4245 // Skip OUI, version, and multicast suite
4246 // This part should be improved in the future when AP supported multiple cipher suite.
4247 // For now, it's OK since almost all APs have fixed cipher suite supported.
4248 // pTmp = (PUCHAR) pEid->Octet;
4251 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4259 // Parse group cipher
4264 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4267 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4270 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4271 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4275 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4278 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4283 // number of unicast suite
4286 // skip all unicast cipher suites
4287 //Count = *(PUSHORT) pTmp;
4288 Count = (pTmp[1]<<8) + pTmp[0];
4289 pTmp += sizeof(USHORT);
4291 // Parsing all unicast cipher suite
4296 TmpCipher = Ndis802_11WEPDisabled;
4300 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4301 TmpCipher = Ndis802_11Encryption1Enabled;
4304 TmpCipher = Ndis802_11Encryption2Enabled;
4307 TmpCipher = Ndis802_11Encryption3Enabled;
4312 if (TmpCipher > pBss->WPA.PairCipher)
4314 // Move the lower cipher suite to PairCipherAux
4315 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4316 pBss->WPA.PairCipher = TmpCipher;
4320 pBss->WPA.PairCipherAux = TmpCipher;
4326 // 4. get AKM suite counts
4327 //Count = *(PUSHORT) pTmp;
4328 Count = (pTmp[1]<<8) + pTmp[0];
4329 pTmp += sizeof(USHORT);
4335 // Set AP support WPA mode
4336 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4337 pBss->AuthMode = Ndis802_11AuthModeWPA;
4339 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4342 // Set AP support WPA mode
4343 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4344 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4346 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4353 // Fixed for WPA-None
4354 if (pBss->BssType == BSS_ADHOC)
4356 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4357 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4358 pBss->WepStatus = pBss->WPA.GroupCipher;
4359 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4360 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4363 pBss->WepStatus = pBss->WPA.PairCipher;
4365 // Check the Pair & Group, if different, turn on mixed mode flag
4366 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4367 pBss->WPA.bMixMode = TRUE;
4372 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4374 // 0. Version must be 1
4375 if (le2cpu16(pRsnHeader->Version) != 1)
4377 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4379 // 1. Check group cipher
4380 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4381 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4384 // Parse group cipher
4385 switch (pCipher->Type)
4389 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4392 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4395 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4396 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4400 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4403 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4408 // set to correct offset for next parsing
4409 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4411 // 2. Get pairwise cipher counts
4412 //Count = *(PUSHORT) pTmp;
4413 Count = (pTmp[1]<<8) + pTmp[0];
4414 pTmp += sizeof(USHORT);
4416 // 3. Get pairwise cipher
4417 // Parsing all unicast cipher suite
4421 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4422 TmpCipher = Ndis802_11WEPDisabled;
4423 switch (pCipher->Type)
4426 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4427 TmpCipher = Ndis802_11Encryption1Enabled;
4430 TmpCipher = Ndis802_11Encryption2Enabled;
4433 TmpCipher = Ndis802_11Encryption3Enabled;
4438 if (TmpCipher > pBss->WPA2.PairCipher)
4440 // Move the lower cipher suite to PairCipherAux
4441 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4442 pBss->WPA2.PairCipher = TmpCipher;
4446 pBss->WPA2.PairCipherAux = TmpCipher;
4448 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4452 // 4. get AKM suite counts
4453 //Count = *(PUSHORT) pTmp;
4454 Count = (pTmp[1]<<8) + pTmp[0];
4455 pTmp += sizeof(USHORT);
4457 // 5. Get AKM ciphers
4458 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4459 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4465 // Set AP support WPA mode
4466 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4467 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4469 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4472 // Set AP support WPA mode
4473 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4474 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4476 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4481 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4483 // Fixed for WPA-None
4484 if (pBss->BssType == BSS_ADHOC)
4486 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4487 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4488 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4489 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4490 pBss->WepStatus = pBss->WPA.GroupCipher;
4491 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4492 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4494 pBss->WepStatus = pBss->WPA2.PairCipher;
4496 // 6. Get RSN capability
4497 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4498 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4499 pTmp += sizeof(USHORT);
4501 // Check the Pair & Group, if different, turn on mixed mode flag
4502 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4503 pBss->WPA2.bMixMode = TRUE;
4509 Length -= (pEid->Len + 2);
4513 // ===========================================================================================
4515 // ===========================================================================================
4517 /*! \brief generates a random mac address value for IBSS BSSID
4518 * \param Addr the bssid location
4523 VOID MacAddrRandomBssid(
4524 IN PRTMP_ADAPTER pAd,
4529 for (i = 0; i < MAC_ADDR_LEN; i++)
4531 pAddr[i] = RandomByte(pAd);
4534 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4537 /*! \brief init the management mac frame header
4538 * \param p_hdr mac header
4539 * \param subtype subtype of the frame
4540 * \param p_ds destination address, don't care if it is a broadcast address
4542 * \pre the station has the following information in the pAd->StaCfg
4546 * \note this function initializes the following field
4548 IRQL = PASSIVE_LEVEL
4549 IRQL = DISPATCH_LEVEL
4552 VOID MgtMacHeaderInit(
4553 IN PRTMP_ADAPTER pAd,
4554 IN OUT PHEADER_802_11 pHdr80211,
4560 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4562 pHdr80211->FC.Type = BTYPE_MGMT;
4563 pHdr80211->FC.SubType = SubType;
4564 pHdr80211->FC.ToDs = ToDs;
4565 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4567 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4569 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4572 // ===========================================================================================
4574 // ===========================================================================================
4576 /*!***************************************************************************
4577 * This routine build an outgoing frame, and fill all information specified
4578 * in argument list to the frame body. The actual frame size is the summation
4581 * Buffer - pointer to a pre-allocated memory segment
4582 * args - a list of <int arg_size, arg> pairs.
4583 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4584 * function will FAIL!!!
4586 * Size of the buffer
4588 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4590 IRQL = PASSIVE_LEVEL
4591 IRQL = DISPATCH_LEVEL
4593 ****************************************************************************/
4594 ULONG MakeOutgoingFrame(
4596 OUT ULONG *FrameLen, ...)
4603 // calculates the total length
4605 va_start(Args, FrameLen);
4608 leng = va_arg(Args, int);
4609 if (leng == END_OF_ARGS)
4613 p = va_arg(Args, PVOID);
4614 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4615 TotLeng = TotLeng + leng;
4618 va_end(Args); /* clean up */
4619 *FrameLen = TotLeng;
4623 // ===========================================================================================
4625 // ===========================================================================================
4627 /*! \brief Initialize The MLME Queue, used by MLME Functions
4628 * \param *Queue The MLME Queue
4629 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4632 * \note Because this is done only once (at the init stage), no need to be locked
4634 IRQL = PASSIVE_LEVEL
4637 NDIS_STATUS MlmeQueueInit(
4638 IN MLME_QUEUE *Queue)
4642 NdisAllocateSpinLock(&Queue->Lock);
4648 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4650 Queue->Entry[i].Occupied = FALSE;
4651 Queue->Entry[i].MsgLen = 0;
4652 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4655 return NDIS_STATUS_SUCCESS;
4658 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4659 * \param *Queue The MLME Queue
4660 * \param Machine The State Machine Id
4661 * \param MsgType The Message Type
4662 * \param MsgLen The Message length
4663 * \param *Msg The message pointer
4664 * \return TRUE if enqueue is successful, FALSE if the queue is full
4667 * \note The message has to be initialized
4669 IRQL = PASSIVE_LEVEL
4670 IRQL = DISPATCH_LEVEL
4673 BOOLEAN MlmeEnqueue(
4674 IN PRTMP_ADAPTER pAd,
4681 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4683 // Do nothing if the driver is starting halt state.
4684 // This might happen when timer already been fired before cancel timer with mlmehalt
4685 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4688 // First check the size, it MUST not exceed the mlme queue size
4689 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4691 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4695 if (MlmeQueueFull(Queue))
4700 NdisAcquireSpinLock(&(Queue->Lock));
4704 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4709 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4710 Queue->Entry[Tail].Occupied = TRUE;
4711 Queue->Entry[Tail].Machine = Machine;
4712 Queue->Entry[Tail].MsgType = MsgType;
4713 Queue->Entry[Tail].MsgLen = MsgLen;
4717 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4720 NdisReleaseSpinLock(&(Queue->Lock));
4724 /*! \brief This function is used when Recv gets a MLME message
4725 * \param *Queue The MLME Queue
4726 * \param TimeStampHigh The upper 32 bit of timestamp
4727 * \param TimeStampLow The lower 32 bit of timestamp
4728 * \param Rssi The receiving RSSI strength
4729 * \param MsgLen The length of the message
4730 * \param *Msg The message pointer
4731 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4735 IRQL = DISPATCH_LEVEL
4738 BOOLEAN MlmeEnqueueForRecv(
4739 IN PRTMP_ADAPTER pAd,
4741 IN ULONG TimeStampHigh,
4742 IN ULONG TimeStampLow,
4751 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4753 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4755 // Do nothing if the driver is starting halt state.
4756 // This might happen when timer already been fired before cancel timer with mlmehalt
4757 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4759 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4763 // First check the size, it MUST not exceed the mlme queue size
4764 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4766 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4770 if (MlmeQueueFull(Queue))
4776 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4778 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4783 // OK, we got all the informations, it is time to put things into queue
4784 NdisAcquireSpinLock(&(Queue->Lock));
4788 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4792 Queue->Entry[Tail].Occupied = TRUE;
4793 Queue->Entry[Tail].Machine = Machine;
4794 Queue->Entry[Tail].MsgType = MsgType;
4795 Queue->Entry[Tail].MsgLen = MsgLen;
4796 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4797 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4798 Queue->Entry[Tail].Rssi0 = Rssi0;
4799 Queue->Entry[Tail].Rssi1 = Rssi1;
4800 Queue->Entry[Tail].Rssi2 = Rssi2;
4801 Queue->Entry[Tail].Signal = Signal;
4802 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4804 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4808 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4811 NdisReleaseSpinLock(&(Queue->Lock));
4813 RT28XX_MLME_HANDLER(pAd);
4819 /*! \brief Dequeue a message from the MLME Queue
4820 * \param *Queue The MLME Queue
4821 * \param *Elem The message dequeued from MLME Queue
4822 * \return TRUE if the Elem contains something, FALSE otherwise
4826 IRQL = DISPATCH_LEVEL
4829 BOOLEAN MlmeDequeue(
4830 IN MLME_QUEUE *Queue,
4831 OUT MLME_QUEUE_ELEM **Elem)
4833 NdisAcquireSpinLock(&(Queue->Lock));
4834 *Elem = &(Queue->Entry[Queue->Head]);
4837 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4841 NdisReleaseSpinLock(&(Queue->Lock));
4845 // IRQL = DISPATCH_LEVEL
4846 VOID MlmeRestartStateMachine(
4847 IN PRTMP_ADAPTER pAd)
4850 MLME_QUEUE_ELEM *Elem = NULL;
4854 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4857 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4858 if(pAd->Mlme.bRunning)
4860 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4865 pAd->Mlme.bRunning = TRUE;
4867 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4869 // Remove all Mlme queues elements
4870 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4872 //From message type, determine which state machine I should drive
4873 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4875 // free MLME element
4876 Elem->Occupied = FALSE;
4881 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4887 // Cancel all timer events
4888 // Be careful to cancel new added timer
4889 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4890 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4891 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4892 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4893 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4894 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4897 // Change back to original channel in case of doing scan
4898 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4899 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4901 // Resume MSDU which is turned off durning scan
4902 RTMPResumeMsduTransmission(pAd);
4905 // Set all state machines back IDLE
4906 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4907 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4908 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4909 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4910 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4911 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4915 // Remove running state
4916 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4917 pAd->Mlme.bRunning = FALSE;
4918 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4922 /*! \brief test if the MLME Queue is empty
4923 * \param *Queue The MLME Queue
4924 * \return TRUE if the Queue is empty, FALSE otherwise
4928 IRQL = DISPATCH_LEVEL
4931 BOOLEAN MlmeQueueEmpty(
4932 IN MLME_QUEUE *Queue)
4936 NdisAcquireSpinLock(&(Queue->Lock));
4937 Ans = (Queue->Num == 0);
4938 NdisReleaseSpinLock(&(Queue->Lock));
4943 /*! \brief test if the MLME Queue is full
4944 * \param *Queue The MLME Queue
4945 * \return TRUE if the Queue is empty, FALSE otherwise
4949 IRQL = PASSIVE_LEVEL
4950 IRQL = DISPATCH_LEVEL
4953 BOOLEAN MlmeQueueFull(
4954 IN MLME_QUEUE *Queue)
4958 NdisAcquireSpinLock(&(Queue->Lock));
4959 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4960 NdisReleaseSpinLock(&(Queue->Lock));
4965 /*! \brief The destructor of MLME Queue
4970 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4972 IRQL = PASSIVE_LEVEL
4975 VOID MlmeQueueDestroy(
4976 IN MLME_QUEUE *pQueue)
4978 NdisAcquireSpinLock(&(pQueue->Lock));
4982 NdisReleaseSpinLock(&(pQueue->Lock));
4983 NdisFreeSpinLock(&(pQueue->Lock));
4986 /*! \brief To substitute the message type if the message is coming from external
4987 * \param pFrame The frame received
4988 * \param *Machine The state machine
4989 * \param *MsgType the message type for the state machine
4990 * \return TRUE if the substitution is successful, FALSE otherwise
4994 IRQL = DISPATCH_LEVEL
4997 BOOLEAN MsgTypeSubst(
4998 IN PRTMP_ADAPTER pAd,
4999 IN PFRAME_802_11 pFrame,
5007 // Pointer to start of data frames including SNAP header
5008 pData = (PUCHAR) pFrame + LENGTH_802_11;
5010 // The only data type will pass to this function is EAPOL frame
5011 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5013 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5015 // Cisco Aironet SNAP header
5016 *Machine = AIRONET_STATE_MACHINE;
5017 *MsgType = MT2_AIRONET_MSG;
5021 *Machine = WPA_PSK_STATE_MACHINE;
5022 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5023 return(WpaMsgTypeSubst(EAPType, MsgType));
5027 switch (pFrame->Hdr.FC.SubType)
5029 case SUBTYPE_ASSOC_REQ:
5030 *Machine = ASSOC_STATE_MACHINE;
5031 *MsgType = MT2_PEER_ASSOC_REQ;
5033 case SUBTYPE_ASSOC_RSP:
5034 *Machine = ASSOC_STATE_MACHINE;
5035 *MsgType = MT2_PEER_ASSOC_RSP;
5037 case SUBTYPE_REASSOC_REQ:
5038 *Machine = ASSOC_STATE_MACHINE;
5039 *MsgType = MT2_PEER_REASSOC_REQ;
5041 case SUBTYPE_REASSOC_RSP:
5042 *Machine = ASSOC_STATE_MACHINE;
5043 *MsgType = MT2_PEER_REASSOC_RSP;
5045 case SUBTYPE_PROBE_REQ:
5046 *Machine = SYNC_STATE_MACHINE;
5047 *MsgType = MT2_PEER_PROBE_REQ;
5049 case SUBTYPE_PROBE_RSP:
5050 *Machine = SYNC_STATE_MACHINE;
5051 *MsgType = MT2_PEER_PROBE_RSP;
5053 case SUBTYPE_BEACON:
5054 *Machine = SYNC_STATE_MACHINE;
5055 *MsgType = MT2_PEER_BEACON;
5058 *Machine = SYNC_STATE_MACHINE;
5059 *MsgType = MT2_PEER_ATIM;
5061 case SUBTYPE_DISASSOC:
5062 *Machine = ASSOC_STATE_MACHINE;
5063 *MsgType = MT2_PEER_DISASSOC_REQ;
5066 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5067 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5068 if (Seq == 1 || Seq == 3)
5070 *Machine = AUTH_RSP_STATE_MACHINE;
5071 *MsgType = MT2_PEER_AUTH_ODD;
5073 else if (Seq == 2 || Seq == 4)
5075 *Machine = AUTH_STATE_MACHINE;
5076 *MsgType = MT2_PEER_AUTH_EVEN;
5083 case SUBTYPE_DEAUTH:
5084 *Machine = AUTH_RSP_STATE_MACHINE;
5085 *MsgType = MT2_PEER_DEAUTH;
5087 case SUBTYPE_ACTION:
5088 *Machine = ACTION_STATE_MACHINE;
5089 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5090 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5092 *MsgType = MT2_ACT_INVALID;
5096 *MsgType = (pFrame->Octet[0]&0x7F);
5107 // ===========================================================================================
5109 // ===========================================================================================
5111 /*! \brief Initialize the state machine.
5112 * \param *S pointer to the state machine
5113 * \param Trans State machine transition function
5114 * \param StNr number of states
5115 * \param MsgNr number of messages
5116 * \param DefFunc default function, when there is invalid state/message combination
5117 * \param InitState initial state of the state machine
5118 * \param Base StateMachine base, internal use only
5119 * \pre p_sm should be a legal pointer
5122 IRQL = PASSIVE_LEVEL
5125 VOID StateMachineInit(
5126 IN STATE_MACHINE *S,
5127 IN STATE_MACHINE_FUNC Trans[],
5130 IN STATE_MACHINE_FUNC DefFunc,
5136 // set number of states and messages
5141 S->TransFunc = Trans;
5143 // init all state transition to default function
5144 for (i = 0; i < StNr; i++)
5146 for (j = 0; j < MsgNr; j++)
5148 S->TransFunc[i * MsgNr + j] = DefFunc;
5152 // set the starting state
5153 S->CurrState = InitState;
5156 /*! \brief This function fills in the function pointer into the cell in the state machine
5157 * \param *S pointer to the state machine
5159 * \param Msg incoming message
5160 * \param f the function to be executed when (state, message) combination occurs at the state machine
5161 * \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
5164 IRQL = PASSIVE_LEVEL
5167 VOID StateMachineSetAction(
5168 IN STATE_MACHINE *S,
5171 IN STATE_MACHINE_FUNC Func)
5175 MsgIdx = Msg - S->Base;
5177 if (St < S->NrState && MsgIdx < S->NrMsg)
5179 // boundary checking before setting the action
5180 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5184 /*! \brief This function does the state transition
5185 * \param *Adapter the NIC adapter pointer
5186 * \param *S the state machine
5187 * \param *Elem the message to be executed
5190 IRQL = DISPATCH_LEVEL
5193 VOID StateMachinePerformAction(
5194 IN PRTMP_ADAPTER pAd,
5195 IN STATE_MACHINE *S,
5196 IN MLME_QUEUE_ELEM *Elem)
5198 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5202 ==========================================================================
5204 The drop function, when machine executes this, the message is simply
5205 ignored. This function does nothing, the message is freed in
5206 StateMachinePerformAction()
5207 ==========================================================================
5210 IN PRTMP_ADAPTER pAd,
5211 IN MLME_QUEUE_ELEM *Elem)
5215 // ===========================================================================================
5217 // ===========================================================================================
5220 ==========================================================================
5223 IRQL = PASSIVE_LEVEL
5225 ==========================================================================
5228 IN PRTMP_ADAPTER pAd,
5232 pAd->Mlme.ShiftReg = 1;
5234 pAd->Mlme.ShiftReg = Seed;
5238 ==========================================================================
5240 ==========================================================================
5243 IN PRTMP_ADAPTER pAd)
5250 if (pAd->Mlme.ShiftReg == 0)
5251 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5253 for (i = 0; i < 8; i++)
5255 if (pAd->Mlme.ShiftReg & 0x00000001)
5257 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5262 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5265 R = (R << 1) | Result;
5271 VOID AsicUpdateAutoFallBackTable(
5272 IN PRTMP_ADAPTER pAd,
5273 IN PUCHAR pRateTable)
5276 HT_FBK_CFG0_STRUC HtCfg0;
5277 HT_FBK_CFG1_STRUC HtCfg1;
5278 LG_FBK_CFG0_STRUC LgCfg0;
5279 LG_FBK_CFG1_STRUC LgCfg1;
5280 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5282 // set to initial value
5283 HtCfg0.word = 0x65432100;
5284 HtCfg1.word = 0xedcba988;
5285 LgCfg0.word = 0xedcba988;
5286 LgCfg1.word = 0x00002100;
5288 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5289 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5291 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5292 switch (pCurrTxRate->Mode)
5298 switch(pCurrTxRate->CurrMCS)
5301 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5304 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5307 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5310 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5313 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5316 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5319 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5322 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5330 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5332 switch(pCurrTxRate->CurrMCS)
5335 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5338 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5341 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5344 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5347 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5350 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5353 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5356 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5359 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5362 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5365 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5368 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5371 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5374 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5377 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5380 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5383 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5390 pNextTxRate = pCurrTxRate;
5393 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5394 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5395 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5396 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5400 ========================================================================
5402 Routine Description:
5403 Set MAC register value according operation mode.
5404 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5405 If MM or GF mask is not set, those passing argument doesn't not take effect.
5407 Operation mode meaning:
5408 = 0 : Pure HT, no preotection.
5409 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5410 = 0x10: No Transmission in 40M is protected.
5411 = 0x11: Transmission in both 40M and 20M shall be protected
5413 we should choose not to use GF. But still set correct ASIC registers.
5414 ========================================================================
5416 VOID AsicUpdateProtect(
5417 IN PRTMP_ADAPTER pAd,
5418 IN USHORT OperationMode,
5420 IN BOOLEAN bDisableBGProtect,
5421 IN BOOLEAN bNonGFExist)
5423 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5429 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5434 if (pAd->BATable.numAsOriginator)
5437 // enable the RTS/CTS to avoid channel collision
5439 SetMask = ALLN_SETPROTECT;
5443 // Config ASIC RTS threshold register
5444 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5445 MacReg &= 0xFF0000FF;
5447 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5449 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5450 (pAd->CommonCfg.bAggregationCapable == TRUE))
5451 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5453 MacReg |= (0x1000 << 8);
5457 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5460 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5462 // Initial common protection settings
5463 RTMPZeroMemory(Protect, sizeof(Protect));
5466 ProtCfg.field.TxopAllowGF40 = 1;
5467 ProtCfg.field.TxopAllowGF20 = 1;
5468 ProtCfg.field.TxopAllowMM40 = 1;
5469 ProtCfg.field.TxopAllowMM20 = 1;
5470 ProtCfg.field.TxopAllowOfdm = 1;
5471 ProtCfg.field.TxopAllowCck = 1;
5472 ProtCfg.field.RTSThEn = 1;
5473 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5475 // update PHY mode and rate
5476 if (pAd->CommonCfg.Channel > 14)
5477 ProtCfg.field.ProtectRate = 0x4000;
5478 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5480 // Handle legacy(B/G) protection
5481 if (bDisableBGProtect)
5483 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5484 ProtCfg.field.ProtectCtrl = 0;
5485 Protect[0] = ProtCfg.word;
5486 Protect[1] = ProtCfg.word;
5490 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5491 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5492 Protect[0] = ProtCfg.word;
5493 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5494 Protect[1] = ProtCfg.word;
5497 // Decide HT frame protection.
5498 if ((SetMask & ALLN_SETPROTECT) != 0)
5500 switch(OperationMode)
5504 // 1.All STAs in the BSS are 20/40 MHz HT
5505 // 2. in ai 20/40MHz BSS
5506 // 3. all STAs are 20MHz in a 20MHz BSS
5507 // Pure HT. no protection.
5511 // PROT_TXOP(25:20) -- 010111
5512 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5513 // PROT_CTRL(17:16) -- 00 (None)
5514 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5515 Protect[2] = 0x01744004;
5519 // PROT_TXOP(25:20) -- 111111
5520 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5521 // PROT_CTRL(17:16) -- 00 (None)
5522 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5523 Protect[3] = 0x03f44084;
5527 // PROT_TXOP(25:20) -- 010111
5528 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5529 // PROT_CTRL(17:16) -- 00 (None)
5530 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5531 Protect[4] = 0x01744004;
5535 // PROT_TXOP(25:20) -- 111111
5536 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5537 // PROT_CTRL(17:16) -- 00 (None)
5538 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5539 Protect[5] = 0x03f44084;
5543 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5544 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5545 Protect[4] = 0x01754004;
5546 Protect[5] = 0x03f54084;
5548 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5552 // This is "HT non-member protection mode."
5553 // If there may be non-HT STAs my BSS
5554 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5555 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5556 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5558 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5559 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5561 //Assign Protection method for 20&40 MHz packets
5562 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5563 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5564 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5565 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5566 Protect[2] = ProtCfg.word;
5567 Protect[3] = ProtCfg4.word;
5568 Protect[4] = ProtCfg.word;
5569 Protect[5] = ProtCfg4.word;
5570 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5574 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5575 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5576 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5578 //Assign Protection method for 40MHz packets
5579 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5580 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5581 Protect[2] = ProtCfg.word;
5582 Protect[3] = ProtCfg4.word;
5585 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5586 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5588 Protect[4] = ProtCfg.word;
5589 Protect[5] = ProtCfg4.word;
5591 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5595 // HT mixed mode. PROTECT ALL!
5597 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5598 ProtCfg4.word = 0x03f44084;
5599 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5600 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5602 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5603 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5605 //Assign Protection method for 20&40 MHz packets
5606 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5607 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5608 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5609 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5610 Protect[2] = ProtCfg.word;
5611 Protect[3] = ProtCfg4.word;
5612 Protect[4] = ProtCfg.word;
5613 Protect[5] = ProtCfg4.word;
5614 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5618 // Special on for Atheros problem n chip.
5619 Protect[2] = 0x01754004;
5620 Protect[3] = 0x03f54084;
5621 Protect[4] = 0x01754004;
5622 Protect[5] = 0x03f54084;
5623 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5628 offset = CCK_PROT_CFG;
5629 for (i = 0;i < 6;i++)
5631 if ((SetMask & (1<< i)))
5633 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5639 // add by johnli, RF power sequence setup
5641 ==========================================================================
5644 Load RF normal operation-mode setup
5646 ==========================================================================
5648 VOID RT30xxLoadRFNormalModeSetup(
5649 IN PRTMP_ADAPTER pAd)
5653 // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5654 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5655 RFValue = (RFValue & (~0x0C)) | 0x31;
5656 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5658 // TX_LO2_en, RF R15 register Bit 3 to 0
5659 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5661 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5663 // TX_LO1_en, RF R17 register Bit 3 to 0
5664 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5666 // to fix rx long range issue
5667 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5671 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5673 // RX_LO1_en, RF R20 register Bit 3 to 0
5674 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5676 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5678 // RX_LO2_en, RF R21 register Bit 3 to 0
5679 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5681 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5683 // LDORF_VC, RF R27 register Bit 2 to 0
5684 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5685 if ((pAd->MACVersion & 0xffff) < 0x0211)
5686 RFValue = (RFValue & (~0x77)) | 0x3;
5688 RFValue = (RFValue & (~0x77));
5689 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5694 ==========================================================================
5697 Load RF sleep-mode setup
5699 ==========================================================================
5701 VOID RT30xxLoadRFSleepModeSetup(
5702 IN PRTMP_ADAPTER pAd)
5707 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5708 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5710 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5712 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5713 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5715 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5717 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5718 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5720 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5722 // RX_CTB_en, RF R21 register Bit 7 to 0
5723 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5725 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5727 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5728 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5730 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5732 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5733 MACValue |= 0x1D000000;
5734 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5738 ==========================================================================
5741 Reverse RF sleep-mode setup
5743 ==========================================================================
5745 VOID RT30xxReverseRFSleepModeSetup(
5746 IN PRTMP_ADAPTER pAd)
5751 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5752 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5754 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5756 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5757 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5759 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5761 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5762 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5764 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5766 // RX_CTB_en, RF R21 register Bit 7 to 1
5767 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5769 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5771 // LDORF_VC, RF R27 register Bit 2 to 0
5772 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5773 if ((pAd->MACVersion & 0xffff) < 0x0211)
5774 RFValue = (RFValue & (~0x77)) | 0x3;
5776 RFValue = (RFValue & (~0x77));
5777 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5779 // RT3071 version E has fixed this issue
5780 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5782 // patch tx EVM issue temporarily
5783 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5784 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5785 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5789 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5790 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5791 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5798 ==========================================================================
5801 IRQL = PASSIVE_LEVEL
5802 IRQL = DISPATCH_LEVEL
5804 ==========================================================================
5806 VOID AsicSwitchChannel(
5807 IN PRTMP_ADAPTER pAd,
5811 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5812 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5814 UINT32 Value = 0; //BbpReg, Value;
5815 RTMP_RF_REGS *RFRegTable;
5817 // Search Tx power value
5819 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5820 // in ChannelList, so use TxPower array instead.
5822 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5824 if (Channel == pAd->TxPower[index].Channel)
5826 TxPwer = pAd->TxPower[index].Power;
5827 TxPwer2 = pAd->TxPower[index].Power2;
5833 for (index = 0; index < pAd->ChannelListNum; index++)
5835 if (Channel == pAd->ChannelList[index].Channel)
5837 TxPwer = pAd->ChannelList[index].Power;
5838 TxPwer2 = pAd->ChannelList[index].Power2;
5844 if (index == MAX_NUM_OF_CHANNELS)
5847 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5850 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5855 // The RF programming sequence is difference between 3xxx and 2xxx
5857 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5858 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5861 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5864 /* modify by WY for Read RF Reg. error */
5867 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5869 if (Channel == FreqItems3020[index].Channel)
5871 // Programming channel parameters
5872 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5873 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5876 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5877 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5878 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5881 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5882 RFValue = (RFValue & 0xE0) | TxPwer;
5883 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5886 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5887 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5888 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5891 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5892 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5893 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5896 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5897 RFValue = (RFValue & 0xE0) | TxPwer;
5898 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5901 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5902 RFValue = (RFValue & 0xE0) | TxPwer2;
5903 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5905 // Tx/Rx Stream setting
5906 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5907 //if (IS_RT3090(pAd))
5908 // RFValue |= 0x01; // Enable RF block.
5909 RFValue &= 0x03; //clear bit[7~2]
5910 if (pAd->Antenna.field.TxPath == 1)
5912 else if (pAd->Antenna.field.TxPath == 2)
5914 if (pAd->Antenna.field.RxPath == 1)
5916 else if (pAd->Antenna.field.RxPath == 2)
5918 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5921 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5922 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5923 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5927 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5929 RFValue = pAd->Mlme.CaliBW40RfR24;
5930 //DISABLE_11N_CHECK(pAd);
5934 RFValue = pAd->Mlme.CaliBW20RfR24;
5937 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5940 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5941 RFValue = RFValue | 0x1;
5942 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5944 // latch channel for future usage.
5945 pAd->LatchRfRegs.Channel = Channel;
5948 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5949 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5952 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5953 RFValue = RFValue | 0x1;
5954 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5956 // latch channel for future usage.
5957 pAd->LatchRfRegs.Channel = Channel;
5959 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5964 pAd->Antenna.field.TxPath,
5965 FreqItems3020[index].N,
5966 FreqItems3020[index].K,
5967 FreqItems3020[index].R));
5975 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5980 pAd->Antenna.field.TxPath,
5981 FreqItems3020[index].N,
5982 FreqItems3020[index].K,
5983 FreqItems3020[index].R));
5989 RFRegTable = RF2850RegTable;
5991 switch (pAd->RfIcType)
5998 for (index = 0; index < NUM_OF_2850_CHNL; index++)
6000 if (Channel == RFRegTable[index].Channel)
6002 R2 = RFRegTable[index].R2;
6003 if (pAd->Antenna.field.TxPath == 1)
6005 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
6008 if (pAd->Antenna.field.RxPath == 2)
6010 R2 |= 0x40; // write 1 to off Rxpath.
6012 else if (pAd->Antenna.field.RxPath == 1)
6014 R2 |= 0x20040; // write 1 to off RxPath
6019 // initialize R3, R4
6020 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
6021 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
6023 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
6025 if ((TxPwer >= -7) && (TxPwer < 0))
6027 TxPwer = (7+TxPwer);
6028 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6029 R3 |= (TxPwer << 10);
6030 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
6034 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6035 R3 |= (TxPwer << 10) | (1 << 9);
6039 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
6041 TxPwer2 = (7+TxPwer2);
6042 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6043 R4 |= (TxPwer2 << 7);
6044 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
6048 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6049 R4 |= (TxPwer2 << 7) | (1 << 6);
6054 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6055 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6058 // Based on BBP current mode before changing RF channel.
6059 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6065 pAd->LatchRfRegs.Channel = Channel;
6066 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6067 pAd->LatchRfRegs.R2 = R2;
6068 pAd->LatchRfRegs.R3 = R3;
6069 pAd->LatchRfRegs.R4 = R4;
6071 // Set RF value 1's set R3[bit2] = [0]
6072 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6073 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6074 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6075 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6079 // Set RF value 2's set R3[bit2] = [1]
6080 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6081 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6082 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6083 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6087 // Set RF value 3's set R3[bit2] = [0]
6088 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6089 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6090 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6091 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6103 // Change BBP setting during siwtch from a->g, g->a
6106 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6108 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6109 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6110 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6111 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.
6112 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6114 // Rx High power VGA offset for LNA select
6115 if (pAd->NicConfig2.field.ExternalLNAForG)
6117 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6118 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6122 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6123 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6126 // 5G band selection PIN, bit1 and bit2 are complement
6127 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6130 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6132 // Turn off unused PA or LNA when only 1T or 1R
6133 if (pAd->Antenna.field.TxPath == 1)
6135 TxPinCfg &= 0xFFFFFFF3;
6137 if (pAd->Antenna.field.RxPath == 1)
6139 TxPinCfg &= 0xFFFFF3FF;
6142 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6146 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6148 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6149 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6150 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6151 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.
6152 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6154 // Rx High power VGA offset for LNA select
6155 if (pAd->NicConfig2.field.ExternalLNAForA)
6157 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6161 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6164 // 5G band selection PIN, bit1 and bit2 are complement
6165 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6168 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6170 // Turn off unused PA or LNA when only 1T or 1R
6171 if (pAd->Antenna.field.TxPath == 1)
6173 TxPinCfg &= 0xFFFFFFF3;
6175 if (pAd->Antenna.field.RxPath == 1)
6177 TxPinCfg &= 0xFFFFF3FF;
6180 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6183 // R66 should be set according to Channel and use 20MHz when scanning
6184 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6186 RTMPSetAGCInitValue(pAd, BW_20);
6188 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6191 // On 11A, We should delay and wait RF/BBP to be stable
6192 // and the appropriate time should be 1000 micro seconds
6193 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6195 RTMPusecDelay(1000);
6197 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",
6200 (R3 & 0x00003e00) >> 9,
6201 (R4 & 0x000007c0) >> 6,
6202 pAd->Antenna.field.TxPath,
6203 pAd->LatchRfRegs.R1,
6204 pAd->LatchRfRegs.R2,
6205 pAd->LatchRfRegs.R3,
6206 pAd->LatchRfRegs.R4));
6210 ==========================================================================
6212 This function is required for 2421 only, and should not be used during
6213 site survey. It's only required after NIC decided to stay at a channel
6214 for a longer period.
6215 When this function is called, it's always after AsicSwitchChannel().
6217 IRQL = PASSIVE_LEVEL
6218 IRQL = DISPATCH_LEVEL
6220 ==========================================================================
6222 VOID AsicLockChannel(
6223 IN PRTMP_ADAPTER pAd,
6229 ==========================================================================
6232 IRQL = PASSIVE_LEVEL
6233 IRQL = DISPATCH_LEVEL
6235 ==========================================================================
6237 VOID AsicAntennaSelect(
6238 IN PRTMP_ADAPTER pAd,
6242 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6244 // patch for AsicSetRxAnt failed
6245 pAd->RxAnt.EvaluatePeriod = 0;
6247 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6248 // valid indication of the distance between this AP and its clients.
6249 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6253 // if no traffic then reset average rssi to trigger evaluation
6254 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6256 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6257 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6258 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6261 pAd->StaCfg.NumOfAvgRssiSample = 0;
6262 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6264 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6266 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6267 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6269 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6270 AsicEvaluateRxAnt(pAd);
6275 // if not connected, always switch antenna to try to connect
6278 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6279 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6280 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6282 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6284 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6291 ========================================================================
6293 Routine Description:
6294 Antenna miscellaneous setting.
6297 pAd Pointer to our adapter
6298 BandState Indicate current Band State.
6303 IRQL <= DISPATCH_LEVEL
6306 1.) Frame End type control
6307 only valid for G only (RF_2527 & RF_2529)
6308 0: means DPDT, set BBP R4 bit 5 to 1
6309 1: means SPDT, set BBP R4 bit 5 to 0
6312 ========================================================================
6314 VOID AsicAntennaSetting(
6315 IN PRTMP_ADAPTER pAd,
6316 IN ABGBAND_STATE BandState)
6320 VOID AsicRfTuningExec(
6321 IN PVOID SystemSpecific1,
6322 IN PVOID FunctionContext,
6323 IN PVOID SystemSpecific2,
6324 IN PVOID SystemSpecific3)
6329 ==========================================================================
6331 Gives CCK TX rate 2 more dB TX power.
6332 This routine works only in LINK UP in INFRASTRUCTURE mode.
6334 calculate desired Tx power in RF R3.Tx0~5, should consider -
6335 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6336 1. TxPowerPercentage
6337 2. auto calibration based on TSSI feedback
6338 3. extra 2 db for CCK
6339 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6341 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6342 it should be called AFTER MlmeDynamicTxRatSwitching()
6343 ==========================================================================
6345 VOID AsicAdjustTxPower(
6346 IN PRTMP_ADAPTER pAd)
6350 BOOLEAN bAutoTxAgc = FALSE;
6351 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6352 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6353 PCHAR pTxAgcCompensate;
6358 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6359 || (pAd->bPCIclkOff == TRUE)
6360 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6361 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6365 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6367 if (pAd->CommonCfg.CentralChannel > 14)
6369 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6370 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6371 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6372 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6373 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6377 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6378 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6379 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6380 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6381 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6386 if (pAd->CommonCfg.Channel > 14)
6388 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6389 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6390 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6391 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6392 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6396 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6397 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6398 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6399 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6400 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6404 // TX power compensation for temperature variation based on TSSI. try every 4 second
6405 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6407 if (pAd->CommonCfg.Channel <= 14)
6410 bAutoTxAgc = pAd->bAutoTxAgcG;
6411 TssiRef = pAd->TssiRefG;
6412 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6413 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6414 TxAgcStep = pAd->TxAgcStepG;
6415 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6420 bAutoTxAgc = pAd->bAutoTxAgcA;
6421 TssiRef = pAd->TssiRefA;
6422 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6423 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6424 TxAgcStep = pAd->TxAgcStepA;
6425 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6430 /* BbpR1 is unsigned char */
6431 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6433 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6434 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6435 /* step value is defined in pAd->TxAgcStepG for tx power value */
6437 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6438 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6439 above value are examined in mass factory production */
6440 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6442 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6443 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6444 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6446 if (BbpR49 > pTssiMinusBoundary[1])
6448 // Reading is larger than the reference value
6449 // check for how large we need to decrease the Tx power
6450 for (idx = 1; idx < 5; idx++)
6452 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6455 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6456 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6458 DeltaPwr += (*pTxAgcCompensate);
6459 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6460 BbpR49, TssiRef, TxAgcStep, idx-1));
6462 else if (BbpR49 < pTssiPlusBoundary[1])
6464 // Reading is smaller than the reference value
6465 // check for how large we need to increase the Tx power
6466 for (idx = 1; idx < 5; idx++)
6468 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6471 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6472 *pTxAgcCompensate = TxAgcStep * (idx-1);
6473 DeltaPwr += (*pTxAgcCompensate);
6474 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6475 BbpR49, TssiRef, TxAgcStep, idx-1));
6479 *pTxAgcCompensate = 0;
6480 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6481 BbpR49, TssiRef, TxAgcStep, 0));
6487 if (pAd->CommonCfg.Channel <= 14)
6489 bAutoTxAgc = pAd->bAutoTxAgcG;
6490 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6494 bAutoTxAgc = pAd->bAutoTxAgcA;
6495 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6499 DeltaPwr += (*pTxAgcCompensate);
6502 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6505 /* calculate delta power based on the percentage specified from UI */
6506 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6507 // We lower TX power here according to the percentage specified from UI
6508 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6510 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6512 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6516 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6520 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6524 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6529 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6534 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6536 /* reset different new tx power for different TX rate */
6539 if (TxPwr[i] != 0xffffffff)
6543 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6545 if ((Value + DeltaPwr) < 0)
6547 Value = 0; /* min */
6549 else if ((Value + DeltaPwr) > 0xF)
6551 Value = 0xF; /* max */
6555 Value += DeltaPwr; /* temperature compensation */
6558 /* fill new value to CSR offset */
6559 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6562 /* write tx power value to CSR */
6563 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6564 TX power for OFDM 6M/9M
6565 TX power for CCK5.5M/11M
6566 TX power for CCK1M/2M */
6567 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6568 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6575 ==========================================================================
6577 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6578 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6579 the wakeup timer timeout. Driver has to issue a separate command to wake
6582 IRQL = DISPATCH_LEVEL
6584 ==========================================================================
6586 VOID AsicSleepThenAutoWakeup(
6587 IN PRTMP_ADAPTER pAd,
6588 IN USHORT TbttNumToNextWakeUp)
6590 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6594 ==========================================================================
6596 AsicForceWakeup() is used whenever manual wakeup is required
6597 AsicForceSleep() should only be used when not in INFRA BSS. When
6598 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6599 ==========================================================================
6601 VOID AsicForceSleep(
6602 IN PRTMP_ADAPTER pAd)
6608 ==========================================================================
6610 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6613 IRQL = PASSIVE_LEVEL
6614 IRQL = DISPATCH_LEVEL
6615 ==========================================================================
6617 VOID AsicForceWakeup(
6618 IN PRTMP_ADAPTER pAd,
6626 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6628 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6631 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6636 ==========================================================================
6640 IRQL = DISPATCH_LEVEL
6642 ==========================================================================
6645 IN PRTMP_ADAPTER pAd,
6649 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6650 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6652 Addr4 = (ULONG)(pBssid[0]) |
6653 (ULONG)(pBssid[1] << 8) |
6654 (ULONG)(pBssid[2] << 16) |
6655 (ULONG)(pBssid[3] << 24);
6656 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6659 // always one BSSID in STA mode
6660 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6662 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6665 VOID AsicSetMcastWC(
6666 IN PRTMP_ADAPTER pAd)
6668 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6671 pEntry->Sst = SST_ASSOC;
6672 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6673 pEntry->PsMode = PWR_ACTIVE;
6674 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6675 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6679 ==========================================================================
6682 IRQL = DISPATCH_LEVEL
6684 ==========================================================================
6686 VOID AsicDelWcidTab(
6687 IN PRTMP_ADAPTER pAd,
6690 ULONG Addr0 = 0x0, Addr1 = 0x0;
6693 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6694 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6695 RTMP_IO_WRITE32(pAd, offset, Addr0);
6697 RTMP_IO_WRITE32(pAd, offset, Addr1);
6701 ==========================================================================
6704 IRQL = DISPATCH_LEVEL
6706 ==========================================================================
6709 IN PRTMP_ADAPTER pAd)
6711 TX_LINK_CFG_STRUC TxLinkCfg;
6714 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6715 TxLinkCfg.field.TxRDGEn = 1;
6716 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6718 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6721 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6723 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6727 ==========================================================================
6730 IRQL = DISPATCH_LEVEL
6732 ==========================================================================
6734 VOID AsicDisableRDG(
6735 IN PRTMP_ADAPTER pAd)
6737 TX_LINK_CFG_STRUC TxLinkCfg;
6741 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6742 TxLinkCfg.field.TxRDGEn = 0;
6743 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6745 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6748 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6749 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6752 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6753 if (pAd->CommonCfg.bEnableTxBurst)
6756 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6760 ==========================================================================
6763 IRQL = PASSIVE_LEVEL
6764 IRQL = DISPATCH_LEVEL
6766 ==========================================================================
6768 VOID AsicDisableSync(
6769 IN PRTMP_ADAPTER pAd)
6771 BCN_TIME_CFG_STRUC csr;
6773 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6775 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6776 // that NIC will never wakes up because TSF stops and no more
6778 pAd->TbttTickCount = 0;
6779 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6780 csr.field.bBeaconGen = 0;
6781 csr.field.bTBTTEnable = 0;
6782 csr.field.TsfSyncMode = 0;
6783 csr.field.bTsfTicking = 0;
6784 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6789 ==========================================================================
6792 IRQL = DISPATCH_LEVEL
6794 ==========================================================================
6796 VOID AsicEnableBssSync(
6797 IN PRTMP_ADAPTER pAd)
6799 BCN_TIME_CFG_STRUC csr;
6801 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6803 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6806 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6807 csr.field.bTsfTicking = 1;
6808 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6809 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6810 csr.field.bTBTTEnable = 1;
6813 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6817 ==========================================================================
6820 BEACON frame in shared memory should be built ok before this routine
6821 can be called. Otherwise, a garbage frame maybe transmitted out every
6824 IRQL = DISPATCH_LEVEL
6826 ==========================================================================
6828 VOID AsicEnableIbssSync(
6829 IN PRTMP_ADAPTER pAd)
6831 BCN_TIME_CFG_STRUC csr9;
6835 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6837 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6838 csr9.field.bBeaconGen = 0;
6839 csr9.field.bTBTTEnable = 0;
6840 csr9.field.bTsfTicking = 0;
6841 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6844 // move BEACON TXD and frame content to on-chip memory
6845 ptr = (PUCHAR)&pAd->BeaconTxWI;
6846 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6848 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6849 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6853 // start right after the 16-byte TXWI field
6854 ptr = pAd->BeaconBuf;
6855 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6857 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6858 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6863 // move BEACON TXD and frame content to on-chip memory
6864 ptr = (PUCHAR)&pAd->BeaconTxWI;
6865 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6867 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6871 // start right after the 16-byte TXWI field
6872 ptr = pAd->BeaconBuf;
6873 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6875 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6880 // start sending BEACON
6881 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6882 csr9.field.bTsfTicking = 1;
6883 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6884 csr9.field.bTBTTEnable = 1;
6885 csr9.field.bBeaconGen = 1;
6886 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6890 ==========================================================================
6893 IRQL = PASSIVE_LEVEL
6894 IRQL = DISPATCH_LEVEL
6896 ==========================================================================
6898 VOID AsicSetEdcaParm(
6899 IN PRTMP_ADAPTER pAd,
6900 IN PEDCA_PARM pEdcaParm)
6902 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6903 AC_TXOP_CSR0_STRUC csr0;
6904 AC_TXOP_CSR1_STRUC csr1;
6905 AIFSN_CSR_STRUC AifsnCsr;
6906 CWMIN_CSR_STRUC CwminCsr;
6907 CWMAX_CSR_STRUC CwmaxCsr;
6914 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6916 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6917 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6918 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6920 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6921 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6924 //========================================================
6925 // MAC Register has a copy .
6926 //========================================================
6927 if( pAd->CommonCfg.bEnableTxBurst )
6929 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6930 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6933 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6934 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6935 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6936 Ac0Cfg.field.Aifsn = 2;
6937 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6939 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6940 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6941 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6942 Ac1Cfg.field.Aifsn = 2;
6943 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6945 if (pAd->CommonCfg.PhyMode == PHY_11B)
6947 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6948 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6952 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6953 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6955 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6956 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6957 Ac2Cfg.field.Aifsn = 2;
6958 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6959 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6960 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6961 Ac3Cfg.field.Aifsn = 2;
6962 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6964 //========================================================
6965 // DMA Register has a copy too.
6966 //========================================================
6967 csr0.field.Ac0Txop = 0; // QID_AC_BE
6968 csr0.field.Ac1Txop = 0; // QID_AC_BK
6969 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6970 if (pAd->CommonCfg.PhyMode == PHY_11B)
6972 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6973 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6977 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6978 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6980 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6983 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6984 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6985 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6986 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6987 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6990 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6991 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6992 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6993 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6994 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6996 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6998 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
7002 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
7003 //========================================================
7004 // MAC Register has a copy.
7005 //========================================================
7007 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
7008 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
7010 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
7012 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
7013 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
7014 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
7015 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
7017 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7018 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
7019 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
7020 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
7022 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
7023 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
7024 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
7025 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
7028 // Tuning for Wi-Fi WMM S06
7029 if (pAd->CommonCfg.bWiFiTest &&
7030 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7031 Ac2Cfg.field.Aifsn -= 1;
7033 // Tuning for TGn Wi-Fi 5.2.32
7034 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7035 if (STA_TGN_WIFI_ON(pAd) &&
7036 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7038 Ac0Cfg.field.Aifsn = 3;
7039 Ac2Cfg.field.AcTxop = 5;
7043 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7045 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
7046 Ac2Cfg.field.Aifsn = 5;
7051 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7052 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7053 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7054 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7057 if (pAd->CommonCfg.bWiFiTest)
7059 if (Ac3Cfg.field.AcTxop == 102)
7061 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7062 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7063 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7064 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7065 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7068 //#endif // WIFI_TEST //
7070 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7071 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7072 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7073 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7076 //========================================================
7077 // DMA Register has a copy too.
7078 //========================================================
7079 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7080 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7081 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7083 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7084 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7085 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7088 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7089 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7090 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7092 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7094 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7097 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7098 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7099 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7100 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7101 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7104 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7105 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7106 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7109 // Tuning for Wi-Fi WMM S06
7110 if (pAd->CommonCfg.bWiFiTest &&
7111 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7112 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7114 // Tuning for TGn Wi-Fi 5.2.32
7115 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7116 if (STA_TGN_WIFI_ON(pAd) &&
7117 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7119 AifsnCsr.field.Aifsn0 = 3;
7120 AifsnCsr.field.Aifsn2 = 7;
7124 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7128 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7130 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7131 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7134 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7136 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7139 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7140 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7141 pEdcaParm->Aifsn[0],
7142 pEdcaParm->Cwmin[0],
7143 pEdcaParm->Cwmax[0],
7144 pEdcaParm->Txop[0]<<5,
7145 pEdcaParm->bACM[0]));
7146 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7147 pEdcaParm->Aifsn[1],
7148 pEdcaParm->Cwmin[1],
7149 pEdcaParm->Cwmax[1],
7150 pEdcaParm->Txop[1]<<5,
7151 pEdcaParm->bACM[1]));
7152 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7153 pEdcaParm->Aifsn[2],
7154 pEdcaParm->Cwmin[2],
7155 pEdcaParm->Cwmax[2],
7156 pEdcaParm->Txop[2]<<5,
7157 pEdcaParm->bACM[2]));
7158 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7159 pEdcaParm->Aifsn[3],
7160 pEdcaParm->Cwmin[3],
7161 pEdcaParm->Cwmax[3],
7162 pEdcaParm->Txop[3]<<5,
7163 pEdcaParm->bACM[3]));
7169 ==========================================================================
7172 IRQL = PASSIVE_LEVEL
7173 IRQL = DISPATCH_LEVEL
7175 ==========================================================================
7177 VOID AsicSetSlotTime(
7178 IN PRTMP_ADAPTER pAd,
7179 IN BOOLEAN bUseShortSlotTime)
7182 UINT32 RegValue = 0;
7184 if (pAd->CommonCfg.Channel > 14)
7185 bUseShortSlotTime = TRUE;
7187 if (bUseShortSlotTime)
7188 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7190 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7192 SlotTime = (bUseShortSlotTime)? 9 : 20;
7196 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7197 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7198 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7201 // In this case, we will think it is doing Wi-Fi test
7202 // And we will not set to short slot when bEnableTxBurst is TRUE.
7204 else if (pAd->CommonCfg.bEnableTxBurst)
7207 if (pAd->CommonCfg.bEnableTxBurst)
7213 // For some reasons, always set it to short slot time.
7215 // ToDo: Should consider capability with 11B
7217 if (pAd->StaCfg.BssType == BSS_ADHOC)
7220 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7221 RegValue = RegValue & 0xFFFFFF00;
7223 RegValue |= SlotTime;
7225 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7229 ========================================================================
7231 Add Shared key information into ASIC.
7232 Update shared key, TxMic and RxMic to Asic Shared key table
7233 Update its cipherAlg to Asic Shared key Mode.
7236 ========================================================================
7238 VOID AsicAddSharedKeyEntry(
7239 IN PRTMP_ADAPTER pAd,
7247 ULONG offset; //, csr0;
7248 SHAREDKEY_MODE_STRUC csr1;
7253 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7254 //============================================================================================
7256 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7257 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7258 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]));
7261 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7262 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7266 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7267 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7269 //============================================================================================
7271 // fill key material - key + TX MIC + RX MIC
7274 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7276 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7278 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7282 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7284 offset += MAX_LEN_OF_SHARE_KEY;
7290 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7294 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7304 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7308 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7314 // Update cipher algorithm. WSTA always use BSS0
7316 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7317 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7318 if ((BssIndex%2) == 0)
7321 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7322 else if (KeyIdx == 1)
7323 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7324 else if (KeyIdx == 2)
7325 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7327 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7332 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7333 else if (KeyIdx == 1)
7334 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7335 else if (KeyIdx == 2)
7336 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7338 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7340 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7341 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7345 // IRQL = DISPATCH_LEVEL
7346 VOID AsicRemoveSharedKeyEntry(
7347 IN PRTMP_ADAPTER pAd,
7352 SHAREDKEY_MODE_STRUC csr1;
7354 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7356 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7357 if ((BssIndex%2) == 0)
7360 csr1.field.Bss0Key0CipherAlg = 0;
7361 else if (KeyIdx == 1)
7362 csr1.field.Bss0Key1CipherAlg = 0;
7363 else if (KeyIdx == 2)
7364 csr1.field.Bss0Key2CipherAlg = 0;
7366 csr1.field.Bss0Key3CipherAlg = 0;
7371 csr1.field.Bss1Key0CipherAlg = 0;
7372 else if (KeyIdx == 1)
7373 csr1.field.Bss1Key1CipherAlg = 0;
7374 else if (KeyIdx == 2)
7375 csr1.field.Bss1Key2CipherAlg = 0;
7377 csr1.field.Bss1Key3CipherAlg = 0;
7379 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7380 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7381 ASSERT(BssIndex < 4);
7387 VOID AsicUpdateWCIDAttribute(
7388 IN PRTMP_ADAPTER pAd,
7392 IN BOOLEAN bUsePairewiseKeyTable)
7394 ULONG WCIDAttri = 0, offset;
7397 // Update WCID attribute.
7398 // Only TxKey could update WCID attribute.
7400 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7401 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7402 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7405 VOID AsicUpdateWCIDIVEIV(
7406 IN PRTMP_ADAPTER pAd,
7413 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7415 RTMP_IO_WRITE32(pAd, offset, uIV);
7416 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7419 VOID AsicUpdateRxWCIDTable(
7420 IN PRTMP_ADAPTER pAd,
7427 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7428 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7429 RTMP_IO_WRITE32(pAd, offset, Addr);
7430 Addr = pAddr[4] + (pAddr[5] << 8);
7431 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7436 ========================================================================
7438 Routine Description:
7439 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7442 pAd Pointer to our adapter
7443 WCID WCID Entry number.
7444 BssIndex BSSID index, station or none multiple BSSID support
7445 this value should be 0.
7446 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7447 pCipherKey Pointer to Cipher Key.
7448 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7449 otherwise PairewiseKey table
7450 bTxKey This is the transmit key if enabled.
7456 This routine will set the relative key stuff to Asic including WCID attribute,
7457 Cipher Key, Cipher algorithm and IV/EIV.
7459 IV/EIV will be update if this CipherKey is the transmission key because
7460 ASIC will base on IV's KeyID value to select Cipher Key.
7462 If bTxKey sets to FALSE, this is not the TX key, but it could be
7465 For AP mode bTxKey must be always set to TRUE.
7466 ========================================================================
7468 VOID AsicAddKeyEntry(
7469 IN PRTMP_ADAPTER pAd,
7473 IN PCIPHER_KEY pCipherKey,
7474 IN BOOLEAN bUsePairewiseKeyTable,
7479 PUCHAR pKey = pCipherKey->Key;
7480 PUCHAR pTxMic = pCipherKey->TxMic;
7481 PUCHAR pRxMic = pCipherKey->RxMic;
7482 PUCHAR pTxtsc = pCipherKey->TxTsc;
7483 UCHAR CipherAlg = pCipherKey->CipherAlg;
7484 SHAREDKEY_MODE_STRUC csr1;
7489 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7491 // 1.) decide key table offset
7493 if (bUsePairewiseKeyTable)
7494 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7496 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7499 // 2.) Set Key to Asic
7501 //for (i = 0; i < KeyLen; i++)
7503 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7505 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7509 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7511 offset += MAX_LEN_OF_PEER_KEY;
7514 // 3.) Set MIC key if available
7519 for (i = 0; i < 8; i++)
7521 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7525 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7528 offset += LEN_TKIP_TXMICK;
7533 for (i = 0; i < 8; i++)
7535 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7539 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7545 // 4.) Modify IV/EIV if needs
7546 // This will force Asic to use this key ID by setting IV.
7551 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7555 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7556 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7557 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7559 IV4 = (KeyIdx << 6);
7560 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7561 IV4 |= 0x20; // turn on extension bit means EIV existence
7563 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7569 for (i = 0; i < 4; i++)
7571 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7581 IV4 = (KeyIdx << 6);
7582 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7583 IV4 |= 0x20; // turn on extension bit means EIV existence
7585 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7586 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7592 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7594 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7597 if (!bUsePairewiseKeyTable)
7600 // Only update the shared key security mode
7602 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7603 if ((BssIndex % 2) == 0)
7606 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7607 else if (KeyIdx == 1)
7608 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7609 else if (KeyIdx == 2)
7610 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7612 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7617 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7618 else if (KeyIdx == 1)
7619 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7620 else if (KeyIdx == 2)
7621 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7623 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7625 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7628 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7633 ========================================================================
7635 Add Pair-wise key material into ASIC.
7636 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7639 ========================================================================
7641 VOID AsicAddPairwiseKeyEntry(
7642 IN PRTMP_ADAPTER pAd,
7645 IN CIPHER_KEY *pCipherKey)
7649 PUCHAR pKey = pCipherKey->Key;
7650 PUCHAR pTxMic = pCipherKey->TxMic;
7651 PUCHAR pRxMic = pCipherKey->RxMic;
7653 UCHAR CipherAlg = pCipherKey->CipherAlg;
7657 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7659 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7661 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7665 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7667 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7670 RTMP_IO_READ32(pAd, offset + i, &Value);
7673 offset += MAX_LEN_OF_PEER_KEY;
7681 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7685 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7694 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7698 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7702 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7703 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7704 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]));
7707 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7708 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7712 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7713 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7717 ========================================================================
7719 Remove Pair-wise key material from ASIC.
7722 ========================================================================
7724 VOID AsicRemovePairwiseKeyEntry(
7725 IN PRTMP_ADAPTER pAd,
7732 // re-set the entry's WCID attribute as OPEN-NONE.
7733 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7734 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7735 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7738 BOOLEAN AsicSendCommandToMcu(
7739 IN PRTMP_ADAPTER pAd,
7745 HOST_CMD_CSR_STRUC H2MCmd;
7746 H2M_MAILBOX_STRUC H2MMailbox;
7751 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7752 if (H2MMailbox.field.Owner == 0)
7765 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7767 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7769 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7770 // Reset DMA/CPU ring index
7771 RTMPRingCleanUp(pAd, QID_AC_BK);
7772 RTMPRingCleanUp(pAd, QID_AC_BE);
7773 RTMPRingCleanUp(pAd, QID_AC_VI);
7774 RTMPRingCleanUp(pAd, QID_AC_VO);
7775 RTMPRingCleanUp(pAd, QID_HCCA);
7776 RTMPRingCleanUp(pAd, QID_MGMT);
7777 RTMPRingCleanUp(pAd, QID_RX);
7780 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7782 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7784 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7792 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7793 H2MMailbox.field.CmdToken = Token;
7794 H2MMailbox.field.HighByte = Arg1;
7795 H2MMailbox.field.LowByte = Arg0;
7796 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7799 H2MCmd.field.HostCommand = Command;
7800 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7802 if (Command != 0x80)
7810 BOOLEAN AsicCheckCommanOk(
7811 IN PRTMP_ADAPTER pAd,
7814 UINT32 CmdStatus = 0, CID = 0, i;
7815 UINT32 ThisCIDMask = 0;
7820 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7821 // Find where the command is. Because this is randomly specified by firmware.
7822 if ((CID & CID0MASK) == Command)
7824 ThisCIDMask = CID0MASK;
7827 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7829 ThisCIDMask = CID1MASK;
7832 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7834 ThisCIDMask = CID2MASK;
7837 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7839 ThisCIDMask = CID3MASK;
7847 // Get CommandStatus Value
7848 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7850 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7853 // If Status is 1, the comamnd is success.
7854 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7855 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7857 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7858 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7859 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7862 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7866 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7868 // Clear Command and Status.
7869 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7870 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7877 ========================================================================
7879 Routine Description:
7880 Verify the support rate for different PHY type
7883 pAd Pointer to our adapter
7888 IRQL = PASSIVE_LEVEL
7890 ========================================================================
7892 VOID RTMPCheckRates(
7893 IN PRTMP_ADAPTER pAd,
7894 IN OUT UCHAR SupRate[],
7895 IN OUT UCHAR *SupRateLen)
7897 UCHAR RateIdx, i, j;
7898 UCHAR NewRate[12], NewRateLen;
7902 if (pAd->CommonCfg.PhyMode == PHY_11B)
7907 // Check for support rates exclude basic rate bit
7908 for (i = 0; i < *SupRateLen; i++)
7909 for (j = 0; j < RateIdx; j++)
7910 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7911 NewRate[NewRateLen++] = SupRate[i];
7913 *SupRateLen = NewRateLen;
7914 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7917 BOOLEAN RTMPCheckChannel(
7918 IN PRTMP_ADAPTER pAd,
7919 IN UCHAR CentralChannel,
7923 UCHAR UpperChannel = 0, LowerChannel = 0;
7924 UCHAR NoEffectChannelinList = 0;
7926 // Find upper and lower channel according to 40MHz current operation.
7927 if (CentralChannel < Channel)
7929 UpperChannel = Channel;
7930 if (CentralChannel > 2)
7931 LowerChannel = CentralChannel - 2;
7935 else if (CentralChannel > Channel)
7937 UpperChannel = CentralChannel + 2;
7938 LowerChannel = Channel;
7941 for (k = 0;k < pAd->ChannelListNum;k++)
7943 if (pAd->ChannelList[k].Channel == UpperChannel)
7945 NoEffectChannelinList ++;
7947 if (pAd->ChannelList[k].Channel == LowerChannel)
7949 NoEffectChannelinList ++;
7953 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7954 if (NoEffectChannelinList == 2)
7961 ========================================================================
7963 Routine Description:
7964 Verify the support rate for HT phy type
7967 pAd Pointer to our adapter
7970 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7972 IRQL = PASSIVE_LEVEL
7974 ========================================================================
7976 BOOLEAN RTMPCheckHt(
7977 IN PRTMP_ADAPTER pAd,
7979 IN HT_CAPABILITY_IE *pHtCapability,
7980 IN ADD_HT_INFO_IE *pAddHtInfo)
7982 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7985 // If use AMSDU, set flag.
7986 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7987 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7988 // Save Peer Capability
7989 if (pHtCapability->HtCapInfo.ShortGIfor20)
7990 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7991 if (pHtCapability->HtCapInfo.ShortGIfor40)
7992 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7993 if (pHtCapability->HtCapInfo.TxSTBC)
7994 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7995 if (pHtCapability->HtCapInfo.RxSTBC)
7996 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7997 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7999 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
8002 if (Wcid < MAX_LEN_OF_MAC_TABLE)
8004 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
8007 // Will check ChannelWidth for MCSSet[4] below
8008 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
8009 switch (pAd->CommonCfg.RxStream)
8012 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8013 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
8014 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8015 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8018 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8019 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8020 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8021 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8024 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8025 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8026 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
8027 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8031 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
8033 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
8034 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
8035 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
8037 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
8039 // Send Assoc Req with my HT capability.
8040 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
8041 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
8042 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
8043 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
8044 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
8045 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
8046 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
8047 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
8048 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8049 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8050 if (pAd->CommonCfg.bRdg)
8052 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8053 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8056 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8057 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8059 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8064 ========================================================================
8066 Routine Description:
8067 Verify the support rate for different PHY type
8070 pAd Pointer to our adapter
8075 IRQL = PASSIVE_LEVEL
8077 ========================================================================
8079 VOID RTMPUpdateMlmeRate(
8080 IN PRTMP_ADAPTER pAd)
8083 UCHAR ProperMlmeRate; //= RATE_54;
8084 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8085 BOOLEAN bMatch = FALSE;
8087 switch (pAd->CommonCfg.PhyMode)
8090 ProperMlmeRate = RATE_11;
8091 MinimumRate = RATE_1;
8093 case PHY_11BG_MIXED:
8094 case PHY_11ABGN_MIXED:
8095 case PHY_11BGN_MIXED:
8096 if ((pAd->MlmeAux.SupRateLen == 4) &&
8097 (pAd->MlmeAux.ExtRateLen == 0))
8099 ProperMlmeRate = RATE_11;
8101 ProperMlmeRate = RATE_24;
8103 if (pAd->MlmeAux.Channel <= 14)
8104 MinimumRate = RATE_1;
8106 MinimumRate = RATE_6;
8109 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8110 case PHY_11GN_MIXED:
8111 case PHY_11AGN_MIXED:
8112 case PHY_11AN_MIXED:
8114 ProperMlmeRate = RATE_24;
8115 MinimumRate = RATE_6;
8117 case PHY_11ABG_MIXED:
8118 ProperMlmeRate = RATE_24;
8119 if (pAd->MlmeAux.Channel <= 14)
8120 MinimumRate = RATE_1;
8122 MinimumRate = RATE_6;
8125 ProperMlmeRate = RATE_1;
8126 MinimumRate = RATE_1;
8130 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8132 for (j = 0; j < RateIdx; j++)
8134 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8136 if (j == ProperMlmeRate)
8148 if (bMatch == FALSE)
8150 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8152 for (j = 0; j < RateIdx; j++)
8154 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8156 if (j == ProperMlmeRate)
8169 if (bMatch == FALSE)
8171 ProperMlmeRate = MinimumRate;
8174 pAd->CommonCfg.MlmeRate = MinimumRate;
8175 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8176 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8178 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8179 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8180 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8181 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8185 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8186 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8187 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8188 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8191 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8195 IN PRTMP_ADAPTER pAd,
8202 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8207 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8209 larger = max(Rssi0, Rssi1);
8212 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8214 larger = max(larger, Rssi2);
8224 // Antenna divesity use GPIO3 and EESK pin for control
8225 // Antenna and EEPROM access are both using EESK pin,
8226 // Therefor we should avoid accessing EESK at the same time
8227 // Then restore antenna after EEPROM access
8229 IN PRTMP_ADAPTER pAd,
8236 if ((pAd->EepromAccess) ||
8237 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8238 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8239 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8240 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8245 // the antenna selection is through firmware and MAC register(GPIO3)
8249 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8251 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8253 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8255 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8256 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8261 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8263 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8265 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8268 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8269 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8276 ========================================================================
8277 Routine Description:
8278 Periodic evaluate antenna link status
8281 pAd - Adapter pointer
8286 ========================================================================
8288 VOID AsicEvaluateRxAnt(
8289 IN PRTMP_ADAPTER pAd)
8295 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8296 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8297 fRTMP_ADAPTER_RADIO_OFF |
8298 fRTMP_ADAPTER_NIC_NOT_EXIST |
8299 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8302 if (pAd->StaCfg.Psm == PWR_SAVE)
8306 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8308 if(pAd->Antenna.field.RxPath == 3)
8312 else if(pAd->Antenna.field.RxPath == 2)
8316 else if(pAd->Antenna.field.RxPath == 1)
8320 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8323 pAd->StaCfg.BBPR3 = BBPR3;
8327 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8328 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8329 fRTMP_ADAPTER_RADIO_OFF |
8330 fRTMP_ADAPTER_NIC_NOT_EXIST |
8331 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
8332 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8334 || (pAd->EepromAccess)
8341 //if (pAd->StaCfg.Psm == PWR_SAVE)
8345 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8346 // one is antenna diversity:there is only one antenna can rx and tx
8347 // the other is failed antenna remove:two physical antenna can rx and tx
8348 if (pAd->NicConfig2.field.AntDiversity)
8350 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8351 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8353 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8355 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8356 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8357 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8359 // a one-shot timer to end the evalution
8360 // dynamic adjust antenna evaluation period according to the traffic
8361 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8362 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8364 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8368 if (pAd->StaCfg.Psm == PWR_SAVE)
8371 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8373 if(pAd->Antenna.field.RxPath == 3)
8377 else if(pAd->Antenna.field.RxPath == 2)
8381 else if(pAd->Antenna.field.RxPath == 1)
8385 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8389 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8392 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8393 pAd->RalinkCounters.OneSecTxRetryOkCount +
8394 pAd->RalinkCounters.OneSecTxFailCount;
8396 // dynamic adjust antenna evaluation period according to the traffic
8397 if (TxTotalCnt > 50)
8399 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8400 pAd->Mlme.bLowThroughput = FALSE;
8404 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8405 pAd->Mlme.bLowThroughput = TRUE;
8411 ========================================================================
8412 Routine Description:
8413 After evaluation, check antenna link status
8416 pAd - Adapter pointer
8421 ========================================================================
8423 VOID AsicRxAntEvalTimeout(
8424 IN PVOID SystemSpecific1,
8425 IN PVOID FunctionContext,
8426 IN PVOID SystemSpecific2,
8427 IN PVOID SystemSpecific3)
8429 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8431 CHAR larger = -127, rssi0, rssi1, rssi2;
8435 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8436 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8437 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8438 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8441 if (pAd->StaCfg.Psm == PWR_SAVE)
8445 // if the traffic is low, use average rssi as the criteria
8446 if (pAd->Mlme.bLowThroughput == TRUE)
8448 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8449 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8450 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8454 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8455 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8456 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8459 if(pAd->Antenna.field.RxPath == 3)
8461 larger = max(rssi0, rssi1);
8463 if (larger > (rssi2 + 20))
8464 pAd->Mlme.RealRxPath = 2;
8466 pAd->Mlme.RealRxPath = 3;
8468 else if(pAd->Antenna.field.RxPath == 2)
8470 if (rssi0 > (rssi1 + 20))
8471 pAd->Mlme.RealRxPath = 1;
8473 pAd->Mlme.RealRxPath = 2;
8476 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8478 if(pAd->Mlme.RealRxPath == 3)
8482 else if(pAd->Mlme.RealRxPath == 2)
8486 else if(pAd->Mlme.RealRxPath == 1)
8490 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8492 pAd->StaCfg.BBPR3 = BBPR3;
8497 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8498 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8499 fRTMP_ADAPTER_RADIO_OFF |
8500 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8501 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8503 || (pAd->EepromAccess)
8509 //if (pAd->StaCfg.Psm == PWR_SAVE)
8512 if (pAd->NicConfig2.field.AntDiversity)
8514 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8519 // select PrimaryRxAntPair
8520 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8521 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8523 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8524 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8525 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8527 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8528 pAd->RxAnt.EvaluateStableCnt = 0;
8532 // if the evaluated antenna is not better than original, switch back to original antenna
8533 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8534 pAd->RxAnt.EvaluateStableCnt ++;
8537 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8539 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8540 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8544 if (pAd->StaCfg.Psm == PWR_SAVE)
8547 // if the traffic is low, use average rssi as the criteria
8548 if (pAd->Mlme.bLowThroughput == TRUE)
8550 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8551 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8552 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8556 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8557 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8558 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8561 if(pAd->Antenna.field.RxPath == 3)
8563 larger = max(rssi0, rssi1);
8565 if (larger > (rssi2 + 20))
8566 pAd->Mlme.RealRxPath = 2;
8568 pAd->Mlme.RealRxPath = 3;
8570 else if(pAd->Antenna.field.RxPath == 2)
8572 if (rssi0 > (rssi1 + 20))
8573 pAd->Mlme.RealRxPath = 1;
8575 pAd->Mlme.RealRxPath = 2;
8578 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8580 if(pAd->Mlme.RealRxPath == 3)
8584 else if(pAd->Mlme.RealRxPath == 2)
8588 else if(pAd->Mlme.RealRxPath == 1)
8592 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8600 VOID APSDPeriodicExec(
8601 IN PVOID SystemSpecific1,
8602 IN PVOID FunctionContext,
8603 IN PVOID SystemSpecific2,
8604 IN PVOID SystemSpecific3)
8606 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8608 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8611 pAd->CommonCfg.TriggerTimerCount++;
8616 ========================================================================
8617 Routine Description:
8618 Set/reset MAC registers according to bPiggyBack parameter
8621 pAd - Adapter pointer
8622 bPiggyBack - Enable / Disable Piggy-Back
8627 ========================================================================
8629 VOID RTMPSetPiggyBack(
8630 IN PRTMP_ADAPTER pAd,
8631 IN BOOLEAN bPiggyBack)
8633 TX_LINK_CFG_STRUC TxLinkCfg;
8635 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8637 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8638 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8642 ========================================================================
8643 Routine Description:
8644 check if this entry need to switch rate automatically
8654 ========================================================================
8656 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8657 IN PRTMP_ADAPTER pAd,
8658 IN PMAC_TABLE_ENTRY pEntry)
8660 BOOLEAN result = TRUE;
8663 // only associated STA counts
8664 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8666 result = pAd->StaCfg.bAutoTxRateSwitch;
8676 BOOLEAN RTMPAutoRateSwitchCheck(
8677 IN PRTMP_ADAPTER pAd)
8679 if (pAd->StaCfg.bAutoTxRateSwitch)
8687 ========================================================================
8688 Routine Description:
8689 check if this entry need to fix tx legacy rate
8699 ========================================================================
8701 UCHAR RTMPStaFixedTxMode(
8702 IN PRTMP_ADAPTER pAd,
8703 IN PMAC_TABLE_ENTRY pEntry)
8705 UCHAR tx_mode = FIXED_TXMODE_HT;
8707 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8713 ========================================================================
8714 Routine Description:
8715 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8725 ========================================================================
8727 VOID RTMPUpdateLegacyTxSetting(
8728 UCHAR fixed_tx_mode,
8729 PMAC_TABLE_ENTRY pEntry)
8731 HTTRANSMIT_SETTING TransmitSetting;
8733 if (fixed_tx_mode == FIXED_TXMODE_HT)
8736 TransmitSetting.word = 0;
8738 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8739 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8741 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8743 TransmitSetting.field.MODE = MODE_CCK;
8744 // CCK mode allow MCS 0~3
8745 if (TransmitSetting.field.MCS > MCS_3)
8746 TransmitSetting.field.MCS = MCS_3;
8750 TransmitSetting.field.MODE = MODE_OFDM;
8751 // OFDM mode allow MCS 0~7
8752 if (TransmitSetting.field.MCS > MCS_7)
8753 TransmitSetting.field.MCS = MCS_7;
8756 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8758 pEntry->HTPhyMode.word = TransmitSetting.word;
8759 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8760 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8765 ==========================================================================
8767 dynamic tune BBP R66 to find a balance between sensibility and
8770 IRQL = DISPATCH_LEVEL
8772 ==========================================================================
8774 VOID AsicStaBbpTuning(
8775 IN PRTMP_ADAPTER pAd)
8777 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8780 // 2860C did not support Fase CCA, therefore can't tune
8781 if (pAd->MACVersion == 0x28600100)
8787 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8790 if ((pAd->OpMode == OPMODE_STA)
8791 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8793 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8795 && (pAd->bPCIclkOff == FALSE))
8801 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8804 if (pAd->Antenna.field.RxPath > 1)
8805 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8807 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8809 if (pAd->LatchRfRegs.Channel <= 14)
8812 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8813 // Otherwise, it will have some throughput side effect when low RSSI
8821 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8823 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8824 if (OrigR66Value != R66)
8827 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8830 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8836 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8837 if (OrigR66Value != R66)
8840 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8843 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8851 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8853 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8854 if (OrigR66Value != R66)
8856 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8861 R66 = 0x2E + GET_LNA_GAIN(pAd);
8862 if (OrigR66Value != R66)
8864 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8871 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8873 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8875 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8876 if (OrigR66Value != R66)
8878 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8883 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8884 if (OrigR66Value != R66)
8886 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8892 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8894 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8895 if (OrigR66Value != R66)
8897 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8902 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8903 if (OrigR66Value != R66)
8905 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8916 VOID AsicResetFromDMABusy(
8917 IN PRTMP_ADAPTER pAd)
8920 BOOLEAN bCtrl = FALSE;
8922 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8924 // Be sure restore link control value so we can write register.
8925 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8926 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8928 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8929 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8930 RTMPusecDelay(6000);
8931 pAd->bPCIclkOff = FALSE;
8935 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8937 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8939 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8940 // Reset DMA/CPU ring index
8941 RTMPRingCleanUp(pAd, QID_AC_BK);
8942 RTMPRingCleanUp(pAd, QID_AC_BE);
8943 RTMPRingCleanUp(pAd, QID_AC_VI);
8944 RTMPRingCleanUp(pAd, QID_AC_VO);
8945 RTMPRingCleanUp(pAd, QID_HCCA);
8946 RTMPRingCleanUp(pAd, QID_MGMT);
8947 RTMPRingCleanUp(pAd, QID_RX);
8950 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8952 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8954 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8955 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8956 RTMPPCIeLinkCtrlSetting(pAd, 3);
8958 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8959 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8960 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8964 IN PRTMP_ADAPTER pAd)
8966 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8968 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8969 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8970 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8972 // After hard-reset BBP, initialize all BBP values.
8973 NICRestoreBBPValue(pAd);
8974 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8978 IN PRTMP_ADAPTER pAd)
8982 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8983 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8985 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8987 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8989 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8993 IN PRTMP_ADAPTER pAd)
8995 ULONG Value1, Value2;
8998 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8999 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
9002 // sum should be equals to 0xff, which is the total buffer size.
9003 if ((Value1 + Value2) < 0xff)
9005 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
9006 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
9008 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9010 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9012 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
9017 VOID RTMPSetAGCInitValue(
9018 IN PRTMP_ADAPTER pAd,
9023 if (pAd->LatchRfRegs.Channel <= 14)
9025 R66 = 0x2E + GET_LNA_GAIN(pAd);
9026 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9030 if (BandWidth == BW_20)
9032 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
9033 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9037 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
9038 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9044 VOID AsicTurnOffRFClk(
9045 IN PRTMP_ADAPTER pAd,
9050 UINT32 R1 = 0, R2 = 0, R3 = 0;
9052 RTMP_RF_REGS *RFRegTable;
9055 // The RF programming sequence is difference between 3xxx and 2xxx
9058 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
9063 RFRegTable = RF2850RegTable;
9065 switch (pAd->RfIcType)
9072 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9074 if (Channel == RFRegTable[index].Channel)
9076 R1 = RFRegTable[index].R1 & 0xffffdfff;
9077 R2 = RFRegTable[index].R2 & 0xfffbffff;
9078 R3 = RFRegTable[index].R3 & 0xfff3ffff;
9080 RTMP_RF_IO_WRITE32(pAd, R1);
9081 RTMP_RF_IO_WRITE32(pAd, R2);
9083 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
9084 // Set RF R2 bit18=0, R3 bit[18:19]=0
9085 //if (pAd->StaCfg.bRadio == FALSE)
9088 RTMP_RF_IO_WRITE32(pAd, R3);
9090 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
9091 Channel, pAd->RfIcType, R2, R3));
9094 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
9095 Channel, pAd->RfIcType, R2));
9111 VOID AsicTurnOnRFClk(
9112 IN PRTMP_ADAPTER pAd,
9117 UINT32 R1 = 0, R2 = 0, R3 = 0;
9119 RTMP_RF_REGS *RFRegTable;
9122 // The RF programming sequence is difference between 3xxx and 2xxx
9129 RFRegTable = RF2850RegTable;
9131 switch (pAd->RfIcType)
9138 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9140 if (Channel == RFRegTable[index].Channel)
9142 R3 = pAd->LatchRfRegs.R3;
9145 RTMP_RF_IO_WRITE32(pAd, R3);
9147 R1 = RFRegTable[index].R1;
9148 RTMP_RF_IO_WRITE32(pAd, R1);
9150 R2 = RFRegTable[index].R2;
9151 if (pAd->Antenna.field.TxPath == 1)
9153 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
9156 if (pAd->Antenna.field.RxPath == 2)
9158 R2 |= 0x40; // write 1 to off Rxpath.
9160 else if (pAd->Antenna.field.RxPath == 1)
9162 R2 |= 0x20040; // write 1 to off RxPath
9164 RTMP_RF_IO_WRITE32(pAd, R2);
9176 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",