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]);
5640 ========================================================================
5642 Routine Description: Write RT30xx RF register through MAC
5652 ========================================================================
5654 NTSTATUS RT30xxWriteRFRegister(
5655 IN PRTMP_ADAPTER pAd,
5659 RF_CSR_CFG_STRUC rfcsr;
5664 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5666 if (!rfcsr.field.RF_CSR_KICK)
5670 while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
5672 if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
5674 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
5675 return STATUS_UNSUCCESSFUL;
5678 rfcsr.field.RF_CSR_WR = 1;
5679 rfcsr.field.RF_CSR_KICK = 1;
5680 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5681 rfcsr.field.RF_CSR_DATA = Value;
5683 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5685 return STATUS_SUCCESS;
5690 ========================================================================
5692 Routine Description: Read RT30xx RF register through MAC
5702 ========================================================================
5704 NTSTATUS RT30xxReadRFRegister(
5705 IN PRTMP_ADAPTER pAd,
5709 RF_CSR_CFG_STRUC rfcsr;
5712 for (i=0; i<MAX_BUSY_COUNT; i++)
5714 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5716 if (rfcsr.field.RF_CSR_KICK == BUSY)
5721 rfcsr.field.RF_CSR_WR = 0;
5722 rfcsr.field.RF_CSR_KICK = 1;
5723 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5724 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5725 for (k=0; k<MAX_BUSY_COUNT; k++)
5727 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5729 if (rfcsr.field.RF_CSR_KICK == IDLE)
5732 if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
5733 (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
5735 *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
5739 if (rfcsr.field.RF_CSR_KICK == BUSY)
5741 DBGPRINT_ERR(("RF read R%d=0x%x fail, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
5742 return STATUS_UNSUCCESSFUL;
5745 return STATUS_SUCCESS;
5750 // add by johnli, RF power sequence setup
5752 ==========================================================================
5755 Load RF normal operation-mode setup
5757 ==========================================================================
5759 VOID RT30xxLoadRFNormalModeSetup(
5760 IN PRTMP_ADAPTER pAd)
5764 // 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
5765 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5766 RFValue = (RFValue & (~0x0C)) | 0x31;
5767 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5769 // TX_LO2_en, RF R15 register Bit 3 to 0
5770 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5772 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5774 // TX_LO1_en, RF R17 register Bit 3 to 0
5775 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5777 // to fix rx long range issue
5778 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5782 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5784 // RX_LO1_en, RF R20 register Bit 3 to 0
5785 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5787 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5789 // RX_LO2_en, RF R21 register Bit 3 to 0
5790 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5792 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5794 // LDORF_VC, RF R27 register Bit 2 to 0
5795 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5796 if ((pAd->MACVersion & 0xffff) < 0x0211)
5797 RFValue = (RFValue & (~0x77)) | 0x3;
5799 RFValue = (RFValue & (~0x77));
5800 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5805 ==========================================================================
5808 Load RF sleep-mode setup
5810 ==========================================================================
5812 VOID RT30xxLoadRFSleepModeSetup(
5813 IN PRTMP_ADAPTER pAd)
5818 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5819 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5821 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5823 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5824 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5826 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5828 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5829 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5831 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5833 // RX_CTB_en, RF R21 register Bit 7 to 0
5834 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5836 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5838 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5839 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5841 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5843 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5844 MACValue |= 0x1D000000;
5845 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5849 ==========================================================================
5852 Reverse RF sleep-mode setup
5854 ==========================================================================
5856 VOID RT30xxReverseRFSleepModeSetup(
5857 IN PRTMP_ADAPTER pAd)
5862 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5863 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5865 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5867 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5868 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5870 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5872 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5873 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5875 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5877 // RX_CTB_en, RF R21 register Bit 7 to 1
5878 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5880 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5882 // LDORF_VC, RF R27 register Bit 2 to 0
5883 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5884 if ((pAd->MACVersion & 0xffff) < 0x0211)
5885 RFValue = (RFValue & (~0x77)) | 0x3;
5887 RFValue = (RFValue & (~0x77));
5888 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5890 // RT3071 version E has fixed this issue
5891 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5893 // patch tx EVM issue temporarily
5894 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5895 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5896 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5900 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5901 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5902 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5909 ==========================================================================
5912 IRQL = PASSIVE_LEVEL
5913 IRQL = DISPATCH_LEVEL
5915 ==========================================================================
5917 VOID AsicSwitchChannel(
5918 IN PRTMP_ADAPTER pAd,
5922 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5923 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5925 UINT32 Value = 0; //BbpReg, Value;
5926 RTMP_RF_REGS *RFRegTable;
5928 // Search Tx power value
5930 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5931 // in ChannelList, so use TxPower array instead.
5933 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5935 if (Channel == pAd->TxPower[index].Channel)
5937 TxPwer = pAd->TxPower[index].Power;
5938 TxPwer2 = pAd->TxPower[index].Power2;
5944 for (index = 0; index < pAd->ChannelListNum; index++)
5946 if (Channel == pAd->ChannelList[index].Channel)
5948 TxPwer = pAd->ChannelList[index].Power;
5949 TxPwer2 = pAd->ChannelList[index].Power2;
5955 if (index == MAX_NUM_OF_CHANNELS)
5958 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5961 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5966 // The RF programming sequence is difference between 3xxx and 2xxx
5968 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5969 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5972 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5975 /* modify by WY for Read RF Reg. error */
5978 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5980 if (Channel == FreqItems3020[index].Channel)
5982 // Programming channel parameters
5983 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5984 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5987 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5988 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5989 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5992 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5993 RFValue = (RFValue & 0xE0) | TxPwer;
5994 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5997 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5998 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5999 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
6002 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
6003 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
6004 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
6007 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
6008 RFValue = (RFValue & 0xE0) | TxPwer;
6009 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
6012 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
6013 RFValue = (RFValue & 0xE0) | TxPwer2;
6014 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
6016 // Tx/Rx Stream setting
6017 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
6018 //if (IS_RT3090(pAd))
6019 // RFValue |= 0x01; // Enable RF block.
6020 RFValue &= 0x03; //clear bit[7~2]
6021 if (pAd->Antenna.field.TxPath == 1)
6023 else if (pAd->Antenna.field.TxPath == 2)
6025 if (pAd->Antenna.field.RxPath == 1)
6027 else if (pAd->Antenna.field.RxPath == 2)
6029 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
6032 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
6033 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
6034 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
6038 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6040 RFValue = pAd->Mlme.CaliBW40RfR24;
6041 //DISABLE_11N_CHECK(pAd);
6045 RFValue = pAd->Mlme.CaliBW20RfR24;
6048 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
6051 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
6052 RFValue = RFValue | 0x1;
6053 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
6055 // latch channel for future usage.
6056 pAd->LatchRfRegs.Channel = Channel;
6059 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
6060 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
6063 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
6064 RFValue = RFValue | 0x1;
6065 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
6067 // latch channel for future usage.
6068 pAd->LatchRfRegs.Channel = Channel;
6070 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
6075 pAd->Antenna.field.TxPath,
6076 FreqItems3020[index].N,
6077 FreqItems3020[index].K,
6078 FreqItems3020[index].R));
6086 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
6091 pAd->Antenna.field.TxPath,
6092 FreqItems3020[index].N,
6093 FreqItems3020[index].K,
6094 FreqItems3020[index].R));
6100 RFRegTable = RF2850RegTable;
6102 switch (pAd->RfIcType)
6109 for (index = 0; index < NUM_OF_2850_CHNL; index++)
6111 if (Channel == RFRegTable[index].Channel)
6113 R2 = RFRegTable[index].R2;
6114 if (pAd->Antenna.field.TxPath == 1)
6116 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
6119 if (pAd->Antenna.field.RxPath == 2)
6121 R2 |= 0x40; // write 1 to off Rxpath.
6123 else if (pAd->Antenna.field.RxPath == 1)
6125 R2 |= 0x20040; // write 1 to off RxPath
6130 // initialize R3, R4
6131 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
6132 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
6134 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
6136 if ((TxPwer >= -7) && (TxPwer < 0))
6138 TxPwer = (7+TxPwer);
6139 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6140 R3 |= (TxPwer << 10);
6141 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
6145 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6146 R3 |= (TxPwer << 10) | (1 << 9);
6150 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
6152 TxPwer2 = (7+TxPwer2);
6153 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6154 R4 |= (TxPwer2 << 7);
6155 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
6159 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6160 R4 |= (TxPwer2 << 7) | (1 << 6);
6165 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6166 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6169 // Based on BBP current mode before changing RF channel.
6170 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6176 pAd->LatchRfRegs.Channel = Channel;
6177 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6178 pAd->LatchRfRegs.R2 = R2;
6179 pAd->LatchRfRegs.R3 = R3;
6180 pAd->LatchRfRegs.R4 = R4;
6182 // Set RF value 1's set R3[bit2] = [0]
6183 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6184 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6185 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6186 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6190 // Set RF value 2's set R3[bit2] = [1]
6191 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6192 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6193 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6194 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6198 // Set RF value 3's set R3[bit2] = [0]
6199 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6200 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6201 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6202 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6214 // Change BBP setting during siwtch from a->g, g->a
6217 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6219 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6220 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6221 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6222 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.
6223 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6225 // Rx High power VGA offset for LNA select
6226 if (pAd->NicConfig2.field.ExternalLNAForG)
6228 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6229 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6233 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6234 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6237 // 5G band selection PIN, bit1 and bit2 are complement
6238 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6241 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6243 // Turn off unused PA or LNA when only 1T or 1R
6244 if (pAd->Antenna.field.TxPath == 1)
6246 TxPinCfg &= 0xFFFFFFF3;
6248 if (pAd->Antenna.field.RxPath == 1)
6250 TxPinCfg &= 0xFFFFF3FF;
6253 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6257 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6259 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6260 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6261 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6262 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.
6263 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6265 // Rx High power VGA offset for LNA select
6266 if (pAd->NicConfig2.field.ExternalLNAForA)
6268 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6272 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6275 // 5G band selection PIN, bit1 and bit2 are complement
6276 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6279 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6281 // Turn off unused PA or LNA when only 1T or 1R
6282 if (pAd->Antenna.field.TxPath == 1)
6284 TxPinCfg &= 0xFFFFFFF3;
6286 if (pAd->Antenna.field.RxPath == 1)
6288 TxPinCfg &= 0xFFFFF3FF;
6291 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6294 // R66 should be set according to Channel and use 20MHz when scanning
6295 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6297 RTMPSetAGCInitValue(pAd, BW_20);
6299 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6302 // On 11A, We should delay and wait RF/BBP to be stable
6303 // and the appropriate time should be 1000 micro seconds
6304 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6306 RTMPusecDelay(1000);
6308 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",
6311 (R3 & 0x00003e00) >> 9,
6312 (R4 & 0x000007c0) >> 6,
6313 pAd->Antenna.field.TxPath,
6314 pAd->LatchRfRegs.R1,
6315 pAd->LatchRfRegs.R2,
6316 pAd->LatchRfRegs.R3,
6317 pAd->LatchRfRegs.R4));
6321 ==========================================================================
6323 This function is required for 2421 only, and should not be used during
6324 site survey. It's only required after NIC decided to stay at a channel
6325 for a longer period.
6326 When this function is called, it's always after AsicSwitchChannel().
6328 IRQL = PASSIVE_LEVEL
6329 IRQL = DISPATCH_LEVEL
6331 ==========================================================================
6333 VOID AsicLockChannel(
6334 IN PRTMP_ADAPTER pAd,
6340 ==========================================================================
6343 IRQL = PASSIVE_LEVEL
6344 IRQL = DISPATCH_LEVEL
6346 ==========================================================================
6348 VOID AsicAntennaSelect(
6349 IN PRTMP_ADAPTER pAd,
6353 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6355 // patch for AsicSetRxAnt failed
6356 pAd->RxAnt.EvaluatePeriod = 0;
6358 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6359 // valid indication of the distance between this AP and its clients.
6360 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6364 // if no traffic then reset average rssi to trigger evaluation
6365 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6367 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6368 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6369 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6372 pAd->StaCfg.NumOfAvgRssiSample = 0;
6373 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6375 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6377 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6378 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6380 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6381 AsicEvaluateRxAnt(pAd);
6386 // if not connected, always switch antenna to try to connect
6389 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6390 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6391 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6393 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6395 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6402 ========================================================================
6404 Routine Description:
6405 Antenna miscellaneous setting.
6408 pAd Pointer to our adapter
6409 BandState Indicate current Band State.
6414 IRQL <= DISPATCH_LEVEL
6417 1.) Frame End type control
6418 only valid for G only (RF_2527 & RF_2529)
6419 0: means DPDT, set BBP R4 bit 5 to 1
6420 1: means SPDT, set BBP R4 bit 5 to 0
6423 ========================================================================
6425 VOID AsicAntennaSetting(
6426 IN PRTMP_ADAPTER pAd,
6427 IN ABGBAND_STATE BandState)
6431 VOID AsicRfTuningExec(
6432 IN PVOID SystemSpecific1,
6433 IN PVOID FunctionContext,
6434 IN PVOID SystemSpecific2,
6435 IN PVOID SystemSpecific3)
6440 ==========================================================================
6442 Gives CCK TX rate 2 more dB TX power.
6443 This routine works only in LINK UP in INFRASTRUCTURE mode.
6445 calculate desired Tx power in RF R3.Tx0~5, should consider -
6446 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6447 1. TxPowerPercentage
6448 2. auto calibration based on TSSI feedback
6449 3. extra 2 db for CCK
6450 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6452 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6453 it should be called AFTER MlmeDynamicTxRatSwitching()
6454 ==========================================================================
6456 VOID AsicAdjustTxPower(
6457 IN PRTMP_ADAPTER pAd)
6461 BOOLEAN bAutoTxAgc = FALSE;
6462 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6463 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6464 PCHAR pTxAgcCompensate;
6469 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6470 || (pAd->bPCIclkOff == TRUE)
6471 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6472 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6476 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6478 if (pAd->CommonCfg.CentralChannel > 14)
6480 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6481 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6482 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6483 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6484 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6488 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6489 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6490 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6491 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6492 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6497 if (pAd->CommonCfg.Channel > 14)
6499 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6500 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6501 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6502 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6503 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6507 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6508 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6509 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6510 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6511 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6515 // TX power compensation for temperature variation based on TSSI. try every 4 second
6516 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6518 if (pAd->CommonCfg.Channel <= 14)
6521 bAutoTxAgc = pAd->bAutoTxAgcG;
6522 TssiRef = pAd->TssiRefG;
6523 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6524 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6525 TxAgcStep = pAd->TxAgcStepG;
6526 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6531 bAutoTxAgc = pAd->bAutoTxAgcA;
6532 TssiRef = pAd->TssiRefA;
6533 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6534 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6535 TxAgcStep = pAd->TxAgcStepA;
6536 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6541 /* BbpR1 is unsigned char */
6542 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6544 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6545 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6546 /* step value is defined in pAd->TxAgcStepG for tx power value */
6548 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6549 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6550 above value are examined in mass factory production */
6551 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6553 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6554 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6555 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6557 if (BbpR49 > pTssiMinusBoundary[1])
6559 // Reading is larger than the reference value
6560 // check for how large we need to decrease the Tx power
6561 for (idx = 1; idx < 5; idx++)
6563 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6566 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6567 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6569 DeltaPwr += (*pTxAgcCompensate);
6570 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6571 BbpR49, TssiRef, TxAgcStep, idx-1));
6573 else if (BbpR49 < pTssiPlusBoundary[1])
6575 // Reading is smaller than the reference value
6576 // check for how large we need to increase the Tx power
6577 for (idx = 1; idx < 5; idx++)
6579 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6582 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6583 *pTxAgcCompensate = TxAgcStep * (idx-1);
6584 DeltaPwr += (*pTxAgcCompensate);
6585 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6586 BbpR49, TssiRef, TxAgcStep, idx-1));
6590 *pTxAgcCompensate = 0;
6591 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6592 BbpR49, TssiRef, TxAgcStep, 0));
6598 if (pAd->CommonCfg.Channel <= 14)
6600 bAutoTxAgc = pAd->bAutoTxAgcG;
6601 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6605 bAutoTxAgc = pAd->bAutoTxAgcA;
6606 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6610 DeltaPwr += (*pTxAgcCompensate);
6613 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6616 /* calculate delta power based on the percentage specified from UI */
6617 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6618 // We lower TX power here according to the percentage specified from UI
6619 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6621 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6623 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6627 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6631 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6635 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6640 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6645 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6647 /* reset different new tx power for different TX rate */
6650 if (TxPwr[i] != 0xffffffff)
6654 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6656 if ((Value + DeltaPwr) < 0)
6658 Value = 0; /* min */
6660 else if ((Value + DeltaPwr) > 0xF)
6662 Value = 0xF; /* max */
6666 Value += DeltaPwr; /* temperature compensation */
6669 /* fill new value to CSR offset */
6670 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6673 /* write tx power value to CSR */
6674 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6675 TX power for OFDM 6M/9M
6676 TX power for CCK5.5M/11M
6677 TX power for CCK1M/2M */
6678 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6679 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6686 ==========================================================================
6688 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6689 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6690 the wakeup timer timeout. Driver has to issue a separate command to wake
6693 IRQL = DISPATCH_LEVEL
6695 ==========================================================================
6697 VOID AsicSleepThenAutoWakeup(
6698 IN PRTMP_ADAPTER pAd,
6699 IN USHORT TbttNumToNextWakeUp)
6701 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6705 ==========================================================================
6707 AsicForceWakeup() is used whenever manual wakeup is required
6708 AsicForceSleep() should only be used when not in INFRA BSS. When
6709 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6710 ==========================================================================
6712 VOID AsicForceSleep(
6713 IN PRTMP_ADAPTER pAd)
6719 ==========================================================================
6721 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6724 IRQL = PASSIVE_LEVEL
6725 IRQL = DISPATCH_LEVEL
6726 ==========================================================================
6728 VOID AsicForceWakeup(
6729 IN PRTMP_ADAPTER pAd,
6737 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6739 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6742 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6747 ==========================================================================
6751 IRQL = DISPATCH_LEVEL
6753 ==========================================================================
6756 IN PRTMP_ADAPTER pAd,
6760 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6761 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6763 Addr4 = (ULONG)(pBssid[0]) |
6764 (ULONG)(pBssid[1] << 8) |
6765 (ULONG)(pBssid[2] << 16) |
6766 (ULONG)(pBssid[3] << 24);
6767 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6770 // always one BSSID in STA mode
6771 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6773 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6776 VOID AsicSetMcastWC(
6777 IN PRTMP_ADAPTER pAd)
6779 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6782 pEntry->Sst = SST_ASSOC;
6783 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6784 pEntry->PsMode = PWR_ACTIVE;
6785 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6786 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6790 ==========================================================================
6793 IRQL = DISPATCH_LEVEL
6795 ==========================================================================
6797 VOID AsicDelWcidTab(
6798 IN PRTMP_ADAPTER pAd,
6801 ULONG Addr0 = 0x0, Addr1 = 0x0;
6804 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6805 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6806 RTMP_IO_WRITE32(pAd, offset, Addr0);
6808 RTMP_IO_WRITE32(pAd, offset, Addr1);
6812 ==========================================================================
6815 IRQL = DISPATCH_LEVEL
6817 ==========================================================================
6820 IN PRTMP_ADAPTER pAd)
6822 TX_LINK_CFG_STRUC TxLinkCfg;
6825 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6826 TxLinkCfg.field.TxRDGEn = 1;
6827 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6829 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6832 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6834 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6838 ==========================================================================
6841 IRQL = DISPATCH_LEVEL
6843 ==========================================================================
6845 VOID AsicDisableRDG(
6846 IN PRTMP_ADAPTER pAd)
6848 TX_LINK_CFG_STRUC TxLinkCfg;
6852 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6853 TxLinkCfg.field.TxRDGEn = 0;
6854 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6856 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6859 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6860 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6863 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6864 if (pAd->CommonCfg.bEnableTxBurst)
6867 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6871 ==========================================================================
6874 IRQL = PASSIVE_LEVEL
6875 IRQL = DISPATCH_LEVEL
6877 ==========================================================================
6879 VOID AsicDisableSync(
6880 IN PRTMP_ADAPTER pAd)
6882 BCN_TIME_CFG_STRUC csr;
6884 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6886 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6887 // that NIC will never wakes up because TSF stops and no more
6889 pAd->TbttTickCount = 0;
6890 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6891 csr.field.bBeaconGen = 0;
6892 csr.field.bTBTTEnable = 0;
6893 csr.field.TsfSyncMode = 0;
6894 csr.field.bTsfTicking = 0;
6895 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6900 ==========================================================================
6903 IRQL = DISPATCH_LEVEL
6905 ==========================================================================
6907 VOID AsicEnableBssSync(
6908 IN PRTMP_ADAPTER pAd)
6910 BCN_TIME_CFG_STRUC csr;
6912 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6914 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6917 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6918 csr.field.bTsfTicking = 1;
6919 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6920 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6921 csr.field.bTBTTEnable = 1;
6924 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6928 ==========================================================================
6931 BEACON frame in shared memory should be built ok before this routine
6932 can be called. Otherwise, a garbage frame maybe transmitted out every
6935 IRQL = DISPATCH_LEVEL
6937 ==========================================================================
6939 VOID AsicEnableIbssSync(
6940 IN PRTMP_ADAPTER pAd)
6942 BCN_TIME_CFG_STRUC csr9;
6946 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6948 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6949 csr9.field.bBeaconGen = 0;
6950 csr9.field.bTBTTEnable = 0;
6951 csr9.field.bTsfTicking = 0;
6952 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6955 // move BEACON TXD and frame content to on-chip memory
6956 ptr = (PUCHAR)&pAd->BeaconTxWI;
6957 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6959 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6960 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6964 // start right after the 16-byte TXWI field
6965 ptr = pAd->BeaconBuf;
6966 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6968 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6969 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6974 // move BEACON TXD and frame content to on-chip memory
6975 ptr = (PUCHAR)&pAd->BeaconTxWI;
6976 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6978 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6982 // start right after the 16-byte TXWI field
6983 ptr = pAd->BeaconBuf;
6984 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6986 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6991 // start sending BEACON
6992 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6993 csr9.field.bTsfTicking = 1;
6994 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6995 csr9.field.bTBTTEnable = 1;
6996 csr9.field.bBeaconGen = 1;
6997 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
7001 ==========================================================================
7004 IRQL = PASSIVE_LEVEL
7005 IRQL = DISPATCH_LEVEL
7007 ==========================================================================
7009 VOID AsicSetEdcaParm(
7010 IN PRTMP_ADAPTER pAd,
7011 IN PEDCA_PARM pEdcaParm)
7013 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
7014 AC_TXOP_CSR0_STRUC csr0;
7015 AC_TXOP_CSR1_STRUC csr1;
7016 AIFSN_CSR_STRUC AifsnCsr;
7017 CWMIN_CSR_STRUC CwminCsr;
7018 CWMAX_CSR_STRUC CwmaxCsr;
7025 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
7027 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
7028 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
7029 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
7031 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
7032 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
7035 //========================================================
7036 // MAC Register has a copy .
7037 //========================================================
7038 if( pAd->CommonCfg.bEnableTxBurst )
7040 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
7041 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
7044 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
7045 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
7046 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
7047 Ac0Cfg.field.Aifsn = 2;
7048 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7050 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
7051 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
7052 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
7053 Ac1Cfg.field.Aifsn = 2;
7054 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7056 if (pAd->CommonCfg.PhyMode == PHY_11B)
7058 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
7059 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
7063 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
7064 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
7066 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
7067 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
7068 Ac2Cfg.field.Aifsn = 2;
7069 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7070 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
7071 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
7072 Ac3Cfg.field.Aifsn = 2;
7073 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7075 //========================================================
7076 // DMA Register has a copy too.
7077 //========================================================
7078 csr0.field.Ac0Txop = 0; // QID_AC_BE
7079 csr0.field.Ac1Txop = 0; // QID_AC_BK
7080 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7081 if (pAd->CommonCfg.PhyMode == PHY_11B)
7083 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
7084 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
7088 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
7089 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
7091 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7094 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
7095 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
7096 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
7097 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
7098 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7101 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
7102 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
7103 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
7104 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
7105 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7107 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
7109 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
7113 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
7114 //========================================================
7115 // MAC Register has a copy.
7116 //========================================================
7118 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
7119 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
7121 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
7123 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
7124 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
7125 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
7126 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
7128 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7129 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
7130 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
7131 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
7133 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
7134 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
7135 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
7136 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
7139 // Tuning for Wi-Fi WMM S06
7140 if (pAd->CommonCfg.bWiFiTest &&
7141 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7142 Ac2Cfg.field.Aifsn -= 1;
7144 // Tuning for TGn Wi-Fi 5.2.32
7145 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7146 if (STA_TGN_WIFI_ON(pAd) &&
7147 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7149 Ac0Cfg.field.Aifsn = 3;
7150 Ac2Cfg.field.AcTxop = 5;
7154 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7156 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
7157 Ac2Cfg.field.Aifsn = 5;
7162 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7163 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7164 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7165 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7168 if (pAd->CommonCfg.bWiFiTest)
7170 if (Ac3Cfg.field.AcTxop == 102)
7172 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7173 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7174 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7175 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7176 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7179 //#endif // WIFI_TEST //
7181 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7182 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7183 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7184 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7187 //========================================================
7188 // DMA Register has a copy too.
7189 //========================================================
7190 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7191 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7192 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7194 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7195 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7196 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7199 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7200 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7201 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7203 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7205 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7208 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7209 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7210 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7211 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7212 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7215 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7216 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7217 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7220 // Tuning for Wi-Fi WMM S06
7221 if (pAd->CommonCfg.bWiFiTest &&
7222 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7223 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7225 // Tuning for TGn Wi-Fi 5.2.32
7226 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7227 if (STA_TGN_WIFI_ON(pAd) &&
7228 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7230 AifsnCsr.field.Aifsn0 = 3;
7231 AifsnCsr.field.Aifsn2 = 7;
7235 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7239 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7241 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7242 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7245 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7247 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7250 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7251 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7252 pEdcaParm->Aifsn[0],
7253 pEdcaParm->Cwmin[0],
7254 pEdcaParm->Cwmax[0],
7255 pEdcaParm->Txop[0]<<5,
7256 pEdcaParm->bACM[0]));
7257 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7258 pEdcaParm->Aifsn[1],
7259 pEdcaParm->Cwmin[1],
7260 pEdcaParm->Cwmax[1],
7261 pEdcaParm->Txop[1]<<5,
7262 pEdcaParm->bACM[1]));
7263 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7264 pEdcaParm->Aifsn[2],
7265 pEdcaParm->Cwmin[2],
7266 pEdcaParm->Cwmax[2],
7267 pEdcaParm->Txop[2]<<5,
7268 pEdcaParm->bACM[2]));
7269 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7270 pEdcaParm->Aifsn[3],
7271 pEdcaParm->Cwmin[3],
7272 pEdcaParm->Cwmax[3],
7273 pEdcaParm->Txop[3]<<5,
7274 pEdcaParm->bACM[3]));
7280 ==========================================================================
7283 IRQL = PASSIVE_LEVEL
7284 IRQL = DISPATCH_LEVEL
7286 ==========================================================================
7288 VOID AsicSetSlotTime(
7289 IN PRTMP_ADAPTER pAd,
7290 IN BOOLEAN bUseShortSlotTime)
7293 UINT32 RegValue = 0;
7295 if (pAd->CommonCfg.Channel > 14)
7296 bUseShortSlotTime = TRUE;
7298 if (bUseShortSlotTime)
7299 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7301 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7303 SlotTime = (bUseShortSlotTime)? 9 : 20;
7307 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7308 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7309 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7312 // In this case, we will think it is doing Wi-Fi test
7313 // And we will not set to short slot when bEnableTxBurst is TRUE.
7315 else if (pAd->CommonCfg.bEnableTxBurst)
7318 if (pAd->CommonCfg.bEnableTxBurst)
7324 // For some reasons, always set it to short slot time.
7326 // ToDo: Should consider capability with 11B
7328 if (pAd->StaCfg.BssType == BSS_ADHOC)
7331 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7332 RegValue = RegValue & 0xFFFFFF00;
7334 RegValue |= SlotTime;
7336 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7340 ========================================================================
7342 Add Shared key information into ASIC.
7343 Update shared key, TxMic and RxMic to Asic Shared key table
7344 Update its cipherAlg to Asic Shared key Mode.
7347 ========================================================================
7349 VOID AsicAddSharedKeyEntry(
7350 IN PRTMP_ADAPTER pAd,
7358 ULONG offset; //, csr0;
7359 SHAREDKEY_MODE_STRUC csr1;
7364 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7365 //============================================================================================
7367 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7368 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7369 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]));
7372 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7373 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7377 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7378 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7380 //============================================================================================
7382 // fill key material - key + TX MIC + RX MIC
7385 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7387 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7389 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7393 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7395 offset += MAX_LEN_OF_SHARE_KEY;
7401 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7405 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7415 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7419 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7425 // Update cipher algorithm. WSTA always use BSS0
7427 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7428 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7429 if ((BssIndex%2) == 0)
7432 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7433 else if (KeyIdx == 1)
7434 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7435 else if (KeyIdx == 2)
7436 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7438 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7443 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7444 else if (KeyIdx == 1)
7445 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7446 else if (KeyIdx == 2)
7447 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7449 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7451 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7452 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7456 // IRQL = DISPATCH_LEVEL
7457 VOID AsicRemoveSharedKeyEntry(
7458 IN PRTMP_ADAPTER pAd,
7463 SHAREDKEY_MODE_STRUC csr1;
7465 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7467 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7468 if ((BssIndex%2) == 0)
7471 csr1.field.Bss0Key0CipherAlg = 0;
7472 else if (KeyIdx == 1)
7473 csr1.field.Bss0Key1CipherAlg = 0;
7474 else if (KeyIdx == 2)
7475 csr1.field.Bss0Key2CipherAlg = 0;
7477 csr1.field.Bss0Key3CipherAlg = 0;
7482 csr1.field.Bss1Key0CipherAlg = 0;
7483 else if (KeyIdx == 1)
7484 csr1.field.Bss1Key1CipherAlg = 0;
7485 else if (KeyIdx == 2)
7486 csr1.field.Bss1Key2CipherAlg = 0;
7488 csr1.field.Bss1Key3CipherAlg = 0;
7490 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7491 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7492 ASSERT(BssIndex < 4);
7498 VOID AsicUpdateWCIDAttribute(
7499 IN PRTMP_ADAPTER pAd,
7503 IN BOOLEAN bUsePairewiseKeyTable)
7505 ULONG WCIDAttri = 0, offset;
7508 // Update WCID attribute.
7509 // Only TxKey could update WCID attribute.
7511 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7512 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7513 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7516 VOID AsicUpdateWCIDIVEIV(
7517 IN PRTMP_ADAPTER pAd,
7524 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7526 RTMP_IO_WRITE32(pAd, offset, uIV);
7527 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7530 VOID AsicUpdateRxWCIDTable(
7531 IN PRTMP_ADAPTER pAd,
7538 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7539 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7540 RTMP_IO_WRITE32(pAd, offset, Addr);
7541 Addr = pAddr[4] + (pAddr[5] << 8);
7542 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7547 ========================================================================
7549 Routine Description:
7550 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7553 pAd Pointer to our adapter
7554 WCID WCID Entry number.
7555 BssIndex BSSID index, station or none multiple BSSID support
7556 this value should be 0.
7557 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7558 pCipherKey Pointer to Cipher Key.
7559 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7560 otherwise PairewiseKey table
7561 bTxKey This is the transmit key if enabled.
7567 This routine will set the relative key stuff to Asic including WCID attribute,
7568 Cipher Key, Cipher algorithm and IV/EIV.
7570 IV/EIV will be update if this CipherKey is the transmission key because
7571 ASIC will base on IV's KeyID value to select Cipher Key.
7573 If bTxKey sets to FALSE, this is not the TX key, but it could be
7576 For AP mode bTxKey must be always set to TRUE.
7577 ========================================================================
7579 VOID AsicAddKeyEntry(
7580 IN PRTMP_ADAPTER pAd,
7584 IN PCIPHER_KEY pCipherKey,
7585 IN BOOLEAN bUsePairewiseKeyTable,
7590 PUCHAR pKey = pCipherKey->Key;
7591 PUCHAR pTxMic = pCipherKey->TxMic;
7592 PUCHAR pRxMic = pCipherKey->RxMic;
7593 PUCHAR pTxtsc = pCipherKey->TxTsc;
7594 UCHAR CipherAlg = pCipherKey->CipherAlg;
7595 SHAREDKEY_MODE_STRUC csr1;
7600 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7602 // 1.) decide key table offset
7604 if (bUsePairewiseKeyTable)
7605 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7607 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7610 // 2.) Set Key to Asic
7612 //for (i = 0; i < KeyLen; i++)
7614 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7616 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7620 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7622 offset += MAX_LEN_OF_PEER_KEY;
7625 // 3.) Set MIC key if available
7630 for (i = 0; i < 8; i++)
7632 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7636 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7639 offset += LEN_TKIP_TXMICK;
7644 for (i = 0; i < 8; i++)
7646 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7650 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7656 // 4.) Modify IV/EIV if needs
7657 // This will force Asic to use this key ID by setting IV.
7662 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7666 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7667 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7668 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7670 IV4 = (KeyIdx << 6);
7671 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7672 IV4 |= 0x20; // turn on extension bit means EIV existence
7674 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7680 for (i = 0; i < 4; i++)
7682 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7692 IV4 = (KeyIdx << 6);
7693 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7694 IV4 |= 0x20; // turn on extension bit means EIV existence
7696 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7697 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7703 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7705 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7708 if (!bUsePairewiseKeyTable)
7711 // Only update the shared key security mode
7713 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7714 if ((BssIndex % 2) == 0)
7717 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7718 else if (KeyIdx == 1)
7719 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7720 else if (KeyIdx == 2)
7721 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7723 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7728 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7729 else if (KeyIdx == 1)
7730 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7731 else if (KeyIdx == 2)
7732 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7734 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7736 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7739 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7744 ========================================================================
7746 Add Pair-wise key material into ASIC.
7747 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7750 ========================================================================
7752 VOID AsicAddPairwiseKeyEntry(
7753 IN PRTMP_ADAPTER pAd,
7756 IN CIPHER_KEY *pCipherKey)
7760 PUCHAR pKey = pCipherKey->Key;
7761 PUCHAR pTxMic = pCipherKey->TxMic;
7762 PUCHAR pRxMic = pCipherKey->RxMic;
7764 UCHAR CipherAlg = pCipherKey->CipherAlg;
7768 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7770 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7772 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7776 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7778 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7781 RTMP_IO_READ32(pAd, offset + i, &Value);
7784 offset += MAX_LEN_OF_PEER_KEY;
7792 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7796 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7805 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7809 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7813 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7814 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7815 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]));
7818 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7819 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7823 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7824 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7828 ========================================================================
7830 Remove Pair-wise key material from ASIC.
7833 ========================================================================
7835 VOID AsicRemovePairwiseKeyEntry(
7836 IN PRTMP_ADAPTER pAd,
7843 // re-set the entry's WCID attribute as OPEN-NONE.
7844 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7845 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7846 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7849 BOOLEAN AsicSendCommandToMcu(
7850 IN PRTMP_ADAPTER pAd,
7856 HOST_CMD_CSR_STRUC H2MCmd;
7857 H2M_MAILBOX_STRUC H2MMailbox;
7862 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7863 if (H2MMailbox.field.Owner == 0)
7876 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7878 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7880 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7881 // Reset DMA/CPU ring index
7882 RTMPRingCleanUp(pAd, QID_AC_BK);
7883 RTMPRingCleanUp(pAd, QID_AC_BE);
7884 RTMPRingCleanUp(pAd, QID_AC_VI);
7885 RTMPRingCleanUp(pAd, QID_AC_VO);
7886 RTMPRingCleanUp(pAd, QID_HCCA);
7887 RTMPRingCleanUp(pAd, QID_MGMT);
7888 RTMPRingCleanUp(pAd, QID_RX);
7891 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7893 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7895 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7903 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7904 H2MMailbox.field.CmdToken = Token;
7905 H2MMailbox.field.HighByte = Arg1;
7906 H2MMailbox.field.LowByte = Arg0;
7907 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7910 H2MCmd.field.HostCommand = Command;
7911 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7913 if (Command != 0x80)
7921 BOOLEAN AsicCheckCommanOk(
7922 IN PRTMP_ADAPTER pAd,
7925 UINT32 CmdStatus = 0, CID = 0, i;
7926 UINT32 ThisCIDMask = 0;
7931 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7932 // Find where the command is. Because this is randomly specified by firmware.
7933 if ((CID & CID0MASK) == Command)
7935 ThisCIDMask = CID0MASK;
7938 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7940 ThisCIDMask = CID1MASK;
7943 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7945 ThisCIDMask = CID2MASK;
7948 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7950 ThisCIDMask = CID3MASK;
7958 // Get CommandStatus Value
7959 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7961 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7964 // If Status is 1, the comamnd is success.
7965 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7966 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7968 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7969 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7970 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7973 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7977 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7979 // Clear Command and Status.
7980 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7981 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7988 ========================================================================
7990 Routine Description:
7991 Verify the support rate for different PHY type
7994 pAd Pointer to our adapter
7999 IRQL = PASSIVE_LEVEL
8001 ========================================================================
8003 VOID RTMPCheckRates(
8004 IN PRTMP_ADAPTER pAd,
8005 IN OUT UCHAR SupRate[],
8006 IN OUT UCHAR *SupRateLen)
8008 UCHAR RateIdx, i, j;
8009 UCHAR NewRate[12], NewRateLen;
8013 if (pAd->CommonCfg.PhyMode == PHY_11B)
8018 // Check for support rates exclude basic rate bit
8019 for (i = 0; i < *SupRateLen; i++)
8020 for (j = 0; j < RateIdx; j++)
8021 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8022 NewRate[NewRateLen++] = SupRate[i];
8024 *SupRateLen = NewRateLen;
8025 NdisMoveMemory(SupRate, NewRate, NewRateLen);
8028 BOOLEAN RTMPCheckChannel(
8029 IN PRTMP_ADAPTER pAd,
8030 IN UCHAR CentralChannel,
8034 UCHAR UpperChannel = 0, LowerChannel = 0;
8035 UCHAR NoEffectChannelinList = 0;
8037 // Find upper and lower channel according to 40MHz current operation.
8038 if (CentralChannel < Channel)
8040 UpperChannel = Channel;
8041 if (CentralChannel > 2)
8042 LowerChannel = CentralChannel - 2;
8046 else if (CentralChannel > Channel)
8048 UpperChannel = CentralChannel + 2;
8049 LowerChannel = Channel;
8052 for (k = 0;k < pAd->ChannelListNum;k++)
8054 if (pAd->ChannelList[k].Channel == UpperChannel)
8056 NoEffectChannelinList ++;
8058 if (pAd->ChannelList[k].Channel == LowerChannel)
8060 NoEffectChannelinList ++;
8064 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
8065 if (NoEffectChannelinList == 2)
8072 ========================================================================
8074 Routine Description:
8075 Verify the support rate for HT phy type
8078 pAd Pointer to our adapter
8081 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
8083 IRQL = PASSIVE_LEVEL
8085 ========================================================================
8087 BOOLEAN RTMPCheckHt(
8088 IN PRTMP_ADAPTER pAd,
8090 IN HT_CAPABILITY_IE *pHtCapability,
8091 IN ADD_HT_INFO_IE *pAddHtInfo)
8093 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
8096 // If use AMSDU, set flag.
8097 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
8098 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
8099 // Save Peer Capability
8100 if (pHtCapability->HtCapInfo.ShortGIfor20)
8101 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
8102 if (pHtCapability->HtCapInfo.ShortGIfor40)
8103 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
8104 if (pHtCapability->HtCapInfo.TxSTBC)
8105 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
8106 if (pHtCapability->HtCapInfo.RxSTBC)
8107 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
8108 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
8110 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
8113 if (Wcid < MAX_LEN_OF_MAC_TABLE)
8115 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
8118 // Will check ChannelWidth for MCSSet[4] below
8119 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
8120 switch (pAd->CommonCfg.RxStream)
8123 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8124 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
8125 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8126 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8129 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8130 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8131 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8132 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8135 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8136 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8137 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
8138 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8142 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
8144 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
8145 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
8146 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
8148 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
8150 // Send Assoc Req with my HT capability.
8151 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
8152 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
8153 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
8154 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
8155 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
8156 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
8157 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
8158 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
8159 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8160 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8161 if (pAd->CommonCfg.bRdg)
8163 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8164 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8167 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8168 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8170 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8175 ========================================================================
8177 Routine Description:
8178 Verify the support rate for different PHY type
8181 pAd Pointer to our adapter
8186 IRQL = PASSIVE_LEVEL
8188 ========================================================================
8190 VOID RTMPUpdateMlmeRate(
8191 IN PRTMP_ADAPTER pAd)
8194 UCHAR ProperMlmeRate; //= RATE_54;
8195 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8196 BOOLEAN bMatch = FALSE;
8198 switch (pAd->CommonCfg.PhyMode)
8201 ProperMlmeRate = RATE_11;
8202 MinimumRate = RATE_1;
8204 case PHY_11BG_MIXED:
8205 case PHY_11ABGN_MIXED:
8206 case PHY_11BGN_MIXED:
8207 if ((pAd->MlmeAux.SupRateLen == 4) &&
8208 (pAd->MlmeAux.ExtRateLen == 0))
8210 ProperMlmeRate = RATE_11;
8212 ProperMlmeRate = RATE_24;
8214 if (pAd->MlmeAux.Channel <= 14)
8215 MinimumRate = RATE_1;
8217 MinimumRate = RATE_6;
8220 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8221 case PHY_11GN_MIXED:
8222 case PHY_11AGN_MIXED:
8223 case PHY_11AN_MIXED:
8225 ProperMlmeRate = RATE_24;
8226 MinimumRate = RATE_6;
8228 case PHY_11ABG_MIXED:
8229 ProperMlmeRate = RATE_24;
8230 if (pAd->MlmeAux.Channel <= 14)
8231 MinimumRate = RATE_1;
8233 MinimumRate = RATE_6;
8236 ProperMlmeRate = RATE_1;
8237 MinimumRate = RATE_1;
8241 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8243 for (j = 0; j < RateIdx; j++)
8245 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8247 if (j == ProperMlmeRate)
8259 if (bMatch == FALSE)
8261 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8263 for (j = 0; j < RateIdx; j++)
8265 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8267 if (j == ProperMlmeRate)
8280 if (bMatch == FALSE)
8282 ProperMlmeRate = MinimumRate;
8285 pAd->CommonCfg.MlmeRate = MinimumRate;
8286 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8287 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8289 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8290 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8291 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8292 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8296 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8297 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8298 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8299 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8302 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8306 IN PRTMP_ADAPTER pAd,
8313 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8318 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8320 larger = max(Rssi0, Rssi1);
8323 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8325 larger = max(larger, Rssi2);
8335 // Antenna divesity use GPIO3 and EESK pin for control
8336 // Antenna and EEPROM access are both using EESK pin,
8337 // Therefor we should avoid accessing EESK at the same time
8338 // Then restore antenna after EEPROM access
8340 IN PRTMP_ADAPTER pAd,
8347 if ((pAd->EepromAccess) ||
8348 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8349 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8350 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8351 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8356 // the antenna selection is through firmware and MAC register(GPIO3)
8360 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8362 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8364 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8366 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8367 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8372 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8374 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8376 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8379 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8380 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8387 ========================================================================
8388 Routine Description:
8389 Periodic evaluate antenna link status
8392 pAd - Adapter pointer
8397 ========================================================================
8399 VOID AsicEvaluateRxAnt(
8400 IN PRTMP_ADAPTER pAd)
8406 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8407 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8408 fRTMP_ADAPTER_RADIO_OFF |
8409 fRTMP_ADAPTER_NIC_NOT_EXIST |
8410 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8413 if (pAd->StaCfg.Psm == PWR_SAVE)
8417 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8419 if(pAd->Antenna.field.RxPath == 3)
8423 else if(pAd->Antenna.field.RxPath == 2)
8427 else if(pAd->Antenna.field.RxPath == 1)
8431 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8434 pAd->StaCfg.BBPR3 = BBPR3;
8437 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8440 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8441 pAd->RalinkCounters.OneSecTxRetryOkCount +
8442 pAd->RalinkCounters.OneSecTxFailCount;
8444 if (TxTotalCnt > 50)
8446 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8447 pAd->Mlme.bLowThroughput = FALSE;
8451 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8452 pAd->Mlme.bLowThroughput = TRUE;
8458 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8459 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8460 fRTMP_ADAPTER_RADIO_OFF |
8461 fRTMP_ADAPTER_NIC_NOT_EXIST |
8462 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
8463 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8465 || (pAd->EepromAccess)
8472 //if (pAd->StaCfg.Psm == PWR_SAVE)
8476 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8477 // one is antenna diversity:there is only one antenna can rx and tx
8478 // the other is failed antenna remove:two physical antenna can rx and tx
8479 if (pAd->NicConfig2.field.AntDiversity)
8481 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8482 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8484 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8486 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8487 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8488 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8490 // a one-shot timer to end the evalution
8491 // dynamic adjust antenna evaluation period according to the traffic
8492 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8493 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8495 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8499 if (pAd->StaCfg.Psm == PWR_SAVE)
8502 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8504 if(pAd->Antenna.field.RxPath == 3)
8508 else if(pAd->Antenna.field.RxPath == 2)
8512 else if(pAd->Antenna.field.RxPath == 1)
8516 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8520 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8523 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8524 pAd->RalinkCounters.OneSecTxRetryOkCount +
8525 pAd->RalinkCounters.OneSecTxFailCount;
8527 // dynamic adjust antenna evaluation period according to the traffic
8528 if (TxTotalCnt > 50)
8530 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8531 pAd->Mlme.bLowThroughput = FALSE;
8535 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8536 pAd->Mlme.bLowThroughput = TRUE;
8542 ========================================================================
8543 Routine Description:
8544 After evaluation, check antenna link status
8547 pAd - Adapter pointer
8552 ========================================================================
8554 VOID AsicRxAntEvalTimeout(
8555 IN PVOID SystemSpecific1,
8556 IN PVOID FunctionContext,
8557 IN PVOID SystemSpecific2,
8558 IN PVOID SystemSpecific3)
8560 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8562 CHAR larger = -127, rssi0, rssi1, rssi2;
8566 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8567 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8568 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8569 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8572 if (pAd->StaCfg.Psm == PWR_SAVE)
8576 // if the traffic is low, use average rssi as the criteria
8577 if (pAd->Mlme.bLowThroughput == TRUE)
8579 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8580 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8581 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8585 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8586 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8587 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8590 if(pAd->Antenna.field.RxPath == 3)
8592 larger = max(rssi0, rssi1);
8594 if (larger > (rssi2 + 20))
8595 pAd->Mlme.RealRxPath = 2;
8597 pAd->Mlme.RealRxPath = 3;
8599 else if(pAd->Antenna.field.RxPath == 2)
8601 if (rssi0 > (rssi1 + 20))
8602 pAd->Mlme.RealRxPath = 1;
8604 pAd->Mlme.RealRxPath = 2;
8607 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8609 if(pAd->Mlme.RealRxPath == 3)
8613 else if(pAd->Mlme.RealRxPath == 2)
8617 else if(pAd->Mlme.RealRxPath == 1)
8621 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8623 pAd->StaCfg.BBPR3 = BBPR3;
8628 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8629 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8630 fRTMP_ADAPTER_RADIO_OFF |
8631 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8632 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8634 || (pAd->EepromAccess)
8640 //if (pAd->StaCfg.Psm == PWR_SAVE)
8643 if (pAd->NicConfig2.field.AntDiversity)
8645 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8650 // select PrimaryRxAntPair
8651 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8652 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8654 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8655 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8656 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8658 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8659 pAd->RxAnt.EvaluateStableCnt = 0;
8663 // if the evaluated antenna is not better than original, switch back to original antenna
8664 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8665 pAd->RxAnt.EvaluateStableCnt ++;
8668 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8670 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8671 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8675 if (pAd->StaCfg.Psm == PWR_SAVE)
8678 // if the traffic is low, use average rssi as the criteria
8679 if (pAd->Mlme.bLowThroughput == TRUE)
8681 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8682 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8683 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8687 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8688 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8689 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8692 if(pAd->Antenna.field.RxPath == 3)
8694 larger = max(rssi0, rssi1);
8696 if (larger > (rssi2 + 20))
8697 pAd->Mlme.RealRxPath = 2;
8699 pAd->Mlme.RealRxPath = 3;
8701 else if(pAd->Antenna.field.RxPath == 2)
8703 if (rssi0 > (rssi1 + 20))
8704 pAd->Mlme.RealRxPath = 1;
8706 pAd->Mlme.RealRxPath = 2;
8709 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8711 if(pAd->Mlme.RealRxPath == 3)
8715 else if(pAd->Mlme.RealRxPath == 2)
8719 else if(pAd->Mlme.RealRxPath == 1)
8723 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8731 VOID APSDPeriodicExec(
8732 IN PVOID SystemSpecific1,
8733 IN PVOID FunctionContext,
8734 IN PVOID SystemSpecific2,
8735 IN PVOID SystemSpecific3)
8737 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8739 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8742 pAd->CommonCfg.TriggerTimerCount++;
8747 ========================================================================
8748 Routine Description:
8749 Set/reset MAC registers according to bPiggyBack parameter
8752 pAd - Adapter pointer
8753 bPiggyBack - Enable / Disable Piggy-Back
8758 ========================================================================
8760 VOID RTMPSetPiggyBack(
8761 IN PRTMP_ADAPTER pAd,
8762 IN BOOLEAN bPiggyBack)
8764 TX_LINK_CFG_STRUC TxLinkCfg;
8766 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8768 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8769 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8773 ========================================================================
8774 Routine Description:
8775 check if this entry need to switch rate automatically
8785 ========================================================================
8787 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8788 IN PRTMP_ADAPTER pAd,
8789 IN PMAC_TABLE_ENTRY pEntry)
8791 BOOLEAN result = TRUE;
8794 // only associated STA counts
8795 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8797 result = pAd->StaCfg.bAutoTxRateSwitch;
8807 BOOLEAN RTMPAutoRateSwitchCheck(
8808 IN PRTMP_ADAPTER pAd)
8810 if (pAd->StaCfg.bAutoTxRateSwitch)
8818 ========================================================================
8819 Routine Description:
8820 check if this entry need to fix tx legacy rate
8830 ========================================================================
8832 UCHAR RTMPStaFixedTxMode(
8833 IN PRTMP_ADAPTER pAd,
8834 IN PMAC_TABLE_ENTRY pEntry)
8836 UCHAR tx_mode = FIXED_TXMODE_HT;
8838 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8844 ========================================================================
8845 Routine Description:
8846 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8856 ========================================================================
8858 VOID RTMPUpdateLegacyTxSetting(
8859 UCHAR fixed_tx_mode,
8860 PMAC_TABLE_ENTRY pEntry)
8862 HTTRANSMIT_SETTING TransmitSetting;
8864 if (fixed_tx_mode == FIXED_TXMODE_HT)
8867 TransmitSetting.word = 0;
8869 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8870 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8872 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8874 TransmitSetting.field.MODE = MODE_CCK;
8875 // CCK mode allow MCS 0~3
8876 if (TransmitSetting.field.MCS > MCS_3)
8877 TransmitSetting.field.MCS = MCS_3;
8881 TransmitSetting.field.MODE = MODE_OFDM;
8882 // OFDM mode allow MCS 0~7
8883 if (TransmitSetting.field.MCS > MCS_7)
8884 TransmitSetting.field.MCS = MCS_7;
8887 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8889 pEntry->HTPhyMode.word = TransmitSetting.word;
8890 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8891 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8896 ==========================================================================
8898 dynamic tune BBP R66 to find a balance between sensibility and
8901 IRQL = DISPATCH_LEVEL
8903 ==========================================================================
8905 VOID AsicStaBbpTuning(
8906 IN PRTMP_ADAPTER pAd)
8908 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8911 // 2860C did not support Fase CCA, therefore can't tune
8912 if (pAd->MACVersion == 0x28600100)
8918 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8921 if ((pAd->OpMode == OPMODE_STA)
8922 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8924 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8926 && (pAd->bPCIclkOff == FALSE))
8932 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8935 if (pAd->Antenna.field.RxPath > 1)
8936 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8938 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8940 if (pAd->LatchRfRegs.Channel <= 14)
8943 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8944 // Otherwise, it will have some throughput side effect when low RSSI
8952 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8954 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8955 if (OrigR66Value != R66)
8958 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8961 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8967 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8968 if (OrigR66Value != R66)
8971 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8974 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8982 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8984 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8985 if (OrigR66Value != R66)
8987 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8992 R66 = 0x2E + GET_LNA_GAIN(pAd);
8993 if (OrigR66Value != R66)
8995 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9002 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
9004 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
9006 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
9007 if (OrigR66Value != R66)
9009 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9014 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
9015 if (OrigR66Value != R66)
9017 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9023 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
9025 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
9026 if (OrigR66Value != R66)
9028 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9033 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
9034 if (OrigR66Value != R66)
9036 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9047 VOID AsicResetFromDMABusy(
9048 IN PRTMP_ADAPTER pAd)
9051 BOOLEAN bCtrl = FALSE;
9053 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
9055 // Be sure restore link control value so we can write register.
9056 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
9057 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
9059 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
9060 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
9061 RTMPusecDelay(6000);
9062 pAd->bPCIclkOff = FALSE;
9066 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
9068 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9070 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
9071 // Reset DMA/CPU ring index
9072 RTMPRingCleanUp(pAd, QID_AC_BK);
9073 RTMPRingCleanUp(pAd, QID_AC_BE);
9074 RTMPRingCleanUp(pAd, QID_AC_VI);
9075 RTMPRingCleanUp(pAd, QID_AC_VO);
9076 RTMPRingCleanUp(pAd, QID_HCCA);
9077 RTMPRingCleanUp(pAd, QID_MGMT);
9078 RTMPRingCleanUp(pAd, QID_RX);
9081 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
9083 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9085 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
9086 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
9087 RTMPPCIeLinkCtrlSetting(pAd, 3);
9089 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
9090 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
9091 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
9095 IN PRTMP_ADAPTER pAd)
9097 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
9099 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
9100 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
9101 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
9103 // After hard-reset BBP, initialize all BBP values.
9104 NICRestoreBBPValue(pAd);
9105 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
9109 IN PRTMP_ADAPTER pAd)
9113 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
9114 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
9116 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9118 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9120 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
9124 IN PRTMP_ADAPTER pAd)
9126 ULONG Value1, Value2;
9129 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
9130 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
9133 // sum should be equals to 0xff, which is the total buffer size.
9134 if ((Value1 + Value2) < 0xff)
9136 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
9137 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
9139 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9141 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
9143 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
9148 VOID RTMPSetAGCInitValue(
9149 IN PRTMP_ADAPTER pAd,
9154 if (pAd->LatchRfRegs.Channel <= 14)
9156 R66 = 0x2E + GET_LNA_GAIN(pAd);
9157 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9161 if (BandWidth == BW_20)
9163 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
9164 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9168 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
9169 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9175 VOID AsicTurnOffRFClk(
9176 IN PRTMP_ADAPTER pAd,
9181 UINT32 R1 = 0, R2 = 0, R3 = 0;
9183 RTMP_RF_REGS *RFRegTable;
9186 // The RF programming sequence is difference between 3xxx and 2xxx
9189 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
9194 RFRegTable = RF2850RegTable;
9196 switch (pAd->RfIcType)
9203 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9205 if (Channel == RFRegTable[index].Channel)
9207 R1 = RFRegTable[index].R1 & 0xffffdfff;
9208 R2 = RFRegTable[index].R2 & 0xfffbffff;
9209 R3 = RFRegTable[index].R3 & 0xfff3ffff;
9211 RTMP_RF_IO_WRITE32(pAd, R1);
9212 RTMP_RF_IO_WRITE32(pAd, R2);
9214 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
9215 // Set RF R2 bit18=0, R3 bit[18:19]=0
9216 //if (pAd->StaCfg.bRadio == FALSE)
9219 RTMP_RF_IO_WRITE32(pAd, R3);
9221 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
9222 Channel, pAd->RfIcType, R2, R3));
9225 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
9226 Channel, pAd->RfIcType, R2));
9242 VOID AsicTurnOnRFClk(
9243 IN PRTMP_ADAPTER pAd,
9248 UINT32 R1 = 0, R2 = 0, R3 = 0;
9250 RTMP_RF_REGS *RFRegTable;
9253 // The RF programming sequence is difference between 3xxx and 2xxx
9260 RFRegTable = RF2850RegTable;
9262 switch (pAd->RfIcType)
9269 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9271 if (Channel == RFRegTable[index].Channel)
9273 R3 = pAd->LatchRfRegs.R3;
9276 RTMP_RF_IO_WRITE32(pAd, R3);
9278 R1 = RFRegTable[index].R1;
9279 RTMP_RF_IO_WRITE32(pAd, R1);
9281 R2 = RFRegTable[index].R2;
9282 if (pAd->Antenna.field.TxPath == 1)
9284 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
9287 if (pAd->Antenna.field.RxPath == 2)
9289 R2 |= 0x40; // write 1 to off Rxpath.
9291 else if (pAd->Antenna.field.RxPath == 1)
9293 R2 |= 0x20040; // write 1 to off RxPath
9295 RTMP_RF_IO_WRITE32(pAd, R2);
9307 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",