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-----------
452 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
455 ==========================================================================
457 initialize the MLME task and its data structure (queue, spinlock,
458 timer, state machines).
463 always return NDIS_STATUS_SUCCESS
465 ==========================================================================
467 NDIS_STATUS MlmeInit(
468 IN PRTMP_ADAPTER pAd)
470 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
472 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
476 Status = MlmeQueueInit(&pAd->Mlme.Queue);
477 if(Status != NDIS_STATUS_SUCCESS)
480 pAd->Mlme.bRunning = FALSE;
481 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
484 BssTableInit(&pAd->ScanTab);
486 // init STA state machines
487 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
488 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
489 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
490 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
491 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
492 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
494 // Since we are using switch/case to implement it, the init is different from the above
495 // state machine init
496 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
499 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
501 // Init mlme periodic timer
502 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
504 // Set mlme periodic timer
505 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
507 // software-based RX Antenna diversity
508 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
512 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
514 // only PCIe cards need these two timers
515 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
516 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
522 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
528 ==========================================================================
530 main loop of the MLME
532 Mlme has to be initialized, and there are something inside the queue
534 This function is invoked from MPSetInformation and MPReceive;
535 This task guarantee only one MlmeHandler will run.
537 IRQL = DISPATCH_LEVEL
539 ==========================================================================
542 IN PRTMP_ADAPTER pAd)
544 MLME_QUEUE_ELEM *Elem = NULL;
546 // Only accept MLME and Frame from peer side, no other (control/data) frame should
547 // get into this state machine
549 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
550 if(pAd->Mlme.bRunning)
552 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
557 pAd->Mlme.bRunning = TRUE;
559 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
561 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
563 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
564 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
565 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
567 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
571 //From message type, determine which state machine I should drive
572 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
575 if (Elem->MsgType == MT2_RESET_CONF)
577 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
578 MlmeRestartStateMachine(pAd);
579 Elem->Occupied = FALSE;
585 // if dequeue success
586 switch (Elem->Machine)
588 // STA state machines
589 case ASSOC_STATE_MACHINE:
590 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
592 case AUTH_STATE_MACHINE:
593 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
595 case AUTH_RSP_STATE_MACHINE:
596 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
598 case SYNC_STATE_MACHINE:
599 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
601 case MLME_CNTL_STATE_MACHINE:
602 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
604 case WPA_PSK_STATE_MACHINE:
605 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
607 case AIRONET_STATE_MACHINE:
608 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
610 case ACTION_STATE_MACHINE:
611 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
618 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
623 Elem->Occupied = FALSE;
628 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
632 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
633 pAd->Mlme.bRunning = FALSE;
634 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
638 ==========================================================================
640 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
642 Adapter - NIC Adapter pointer
644 The MLME task will no longer work properly
648 ==========================================================================
651 IN PRTMP_ADAPTER pAd)
655 UINT32 TxPinCfg = 0x00050F0F;
658 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
660 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
662 // disable BEACON generation and other BEACON related hardware timers
663 AsicDisableSync(pAd);
667 // Cancel pending timers
668 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
669 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
670 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
671 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
672 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
673 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
675 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
677 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
678 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
683 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
684 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
688 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
691 RTMPSetLED(pAd, LED_HALT);
692 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
695 LED_CFG_STRUC LedCfg;
696 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
697 LedCfg.field.LedPolar = 0;
698 LedCfg.field.RLedMode = 0;
699 LedCfg.field.GLedMode = 0;
700 LedCfg.field.YLedMode = 0;
701 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
708 if (IS_RT3070(pAd) || IS_RT3071(pAd))
710 TxPinCfg &= 0xFFFFF0F0;
711 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
716 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
718 MlmeQueueDestroy(&pAd->Mlme.Queue);
719 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
721 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
724 VOID MlmeResetRalinkCounters(
725 IN PRTMP_ADAPTER pAd)
727 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
728 // clear all OneSecxxx counters.
729 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
730 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
731 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
732 pAd->RalinkCounters.OneSecRxOkCnt = 0;
733 pAd->RalinkCounters.OneSecTxFailCount = 0;
734 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
735 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
736 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
738 // TODO: for debug only. to be removed
739 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
740 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
741 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
742 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
743 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
744 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
745 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
746 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
747 pAd->RalinkCounters.OneSecTxDoneCount = 0;
748 pAd->RalinkCounters.OneSecRxCount = 0;
749 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
750 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
755 unsigned long rx_AMSDU;
756 unsigned long rx_Total;
759 ==========================================================================
761 This routine is executed periodically to -
762 1. Decide if it's a right time to turn on PwrMgmt bit of all
764 2. Calculate ChannelQuality based on statistics of the last
765 period, so that TX rate won't toggling very frequently between a
766 successful TX and a failed TX.
767 3. If the calculated ChannelQuality indicated current connection not
768 healthy, then a ROAMing attempt is tried here.
770 IRQL = DISPATCH_LEVEL
772 ==========================================================================
774 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
775 VOID MlmePeriodicExec(
776 IN PVOID SystemSpecific1,
777 IN PVOID FunctionContext,
778 IN PVOID SystemSpecific2,
779 IN PVOID SystemSpecific3)
782 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
786 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
787 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
788 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
789 if(pAd->StaCfg.WepStatus<2)
791 pAd->StaCfg.WpaSupplicantUP = 0;
795 pAd->StaCfg.WpaSupplicantUP = 1;
799 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
800 // Move code to here, because following code will return when radio is off
801 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
802 (pAd->StaCfg.bHardwareRadio == TRUE) &&
803 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
804 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
805 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
809 // Read GPIO pin2 as Hardware controlled radio state
810 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
813 pAd->StaCfg.bHwRadio = TRUE;
817 pAd->StaCfg.bHwRadio = FALSE;
819 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
821 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
822 if (pAd->StaCfg.bRadio == TRUE)
825 // Update extra information
826 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
831 // Update extra information
832 pAd->ExtraInfo = HW_RADIO_OFF;
839 // Do nothing if the driver is starting halt state.
840 // This might happen when timer already been fired before cancel timer with mlmehalt
841 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
842 fRTMP_ADAPTER_RADIO_OFF |
843 fRTMP_ADAPTER_RADIO_MEASUREMENT |
844 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
849 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
851 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
852 pAd->SameRxByteCount++;
855 pAd->SameRxByteCount = 0;
857 // If after BBP, still not work...need to check to reset PBF&MAC.
858 if (pAd->SameRxByteCount == 702)
860 pAd->SameRxByteCount = 0;
865 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
866 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
868 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
870 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
871 pAd->SameRxByteCount = 700;
876 // Update lastReceiveByteCount.
877 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
879 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
881 pAd->CheckDmaBusyCount = 0;
882 AsicResetFromDMABusy(pAd);
886 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
889 // Do nothing if monitor mode is on
893 if (pAd->Mlme.PeriodicRound & 0x1)
895 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
896 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
897 (STA_TGN_WIFI_ON(pAd)) &&
898 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
901 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
902 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
904 else if ((STA_TGN_WIFI_ON(pAd)) &&
905 ((pAd->MACVersion & 0xffff) == 0x0101))
907 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
908 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
913 pAd->bUpdateBcnCntDone = FALSE;
915 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
916 pAd->Mlme.PeriodicRound ++;
919 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
920 NICUpdateFifoStaCounters(pAd);
922 // execute every 500ms
923 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
925 // perform dynamic tx rate switching based on past TX history
927 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
929 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
930 MlmeDynamicTxRateSwitching(pAd);
934 // Normal 1 second Mlme PeriodicExec.
935 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
937 pAd->Mlme.OneSecPeriodicRound ++;
947 // Media status changed, report to NDIS
948 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
950 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
951 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
953 pAd->IndicateMediaState = NdisMediaStateConnected;
954 RTMP_IndicateMediaState(pAd);
959 pAd->IndicateMediaState = NdisMediaStateDisconnected;
960 RTMP_IndicateMediaState(pAd);
964 NdisGetSystemUpTime(&pAd->Mlme.Now32);
966 // add the most up-to-date h/w raw counters into software variable, so that
967 // the dynamic tuning mechanism below are based on most up-to-date information
968 NICUpdateRawCounters(pAd);
971 RT2870_WatchDog(pAd);
974 // Need statistics after read counter. So put after NICUpdateRawCounters
975 ORIBATimerTimeout(pAd);
977 // The time period for checking antenna is according to traffic
978 if (pAd->Mlme.bEnableAutoAntennaCheck)
980 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
981 pAd->RalinkCounters.OneSecTxRetryOkCount +
982 pAd->RalinkCounters.OneSecTxFailCount;
984 // dynamic adjust antenna evaluation period according to the traffic
987 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
989 AsicEvaluateRxAnt(pAd);
994 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
996 AsicEvaluateRxAnt(pAd);
1001 STAMlmePeriodicExec(pAd);
1003 MlmeResetRalinkCounters(pAd);
1007 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1010 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1011 // and sending CTS-to-self over and over.
1012 // Software Patch Solution:
1013 // 1. Polling debug state register 0x10F4 every one second.
1014 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1015 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1019 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1020 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1022 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1024 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1026 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1031 RT28XX_MLME_HANDLER(pAd);
1034 pAd->bUpdateBcnCntDone = FALSE;
1037 VOID STAMlmePeriodicExec(
1048 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1050 // WPA MIC error should block association attempt for 60 seconds
1051 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1052 pAd->StaCfg.bBlockAssoc = FALSE;
1057 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1058 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1059 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1060 if(pAd->StaCfg.WepStatus<2)
1062 pAd->StaCfg.WpaSupplicantUP = 0;
1066 pAd->StaCfg.WpaSupplicantUP = 1;
1070 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1072 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1074 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1076 pAd->PreMediaState = pAd->IndicateMediaState;
1080 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1081 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1082 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1083 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1084 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1085 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1087 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1093 AsicStaBbpTuning(pAd);
1095 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1096 pAd->RalinkCounters.OneSecTxRetryOkCount +
1097 pAd->RalinkCounters.OneSecTxFailCount;
1099 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1101 // update channel quality for Roaming and UI LinkQuality display
1102 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1105 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1106 // Radio is currently in noisy environment
1107 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1108 AsicAdjustTxPower(pAd);
1112 // Is PSM bit consistent with user power management policy?
1113 // This is the only place that will set PSM bit ON.
1114 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1115 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1117 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1119 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1120 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1121 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1123 RTMPSetAGCInitValue(pAd, BW_20);
1124 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1128 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1130 // When APSD is enabled, the period changes as 20 sec
1131 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1132 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1136 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1137 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1139 if (pAd->CommonCfg.bWmmCapable)
1140 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1142 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1147 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1149 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1150 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1151 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1153 // Lost AP, send disconnect & link down event
1154 LinkDown(pAd, FALSE);
1157 union iwreq_data wrqu;
1158 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1159 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1162 MlmeAutoReconnectLastSSID(pAd);
1164 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1166 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1167 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1168 MlmeAutoReconnectLastSSID(pAd);
1171 // Add auto seamless roaming
1172 if (pAd->StaCfg.bFastRoaming)
1174 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1176 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));
1178 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1180 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1184 else if (ADHOC_ON(pAd))
1187 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1188 // the "TX BEACON competition" for the entire past 1 sec.
1189 // So that even when ASIC's BEACONgen engine been blocked
1190 // by peer's BEACON due to slower system clock, this STA still can send out
1191 // minimum BEACON to tell the peer I'm alive.
1192 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1193 // EnqueueBeaconFrame(pAd); // software send BEACON
1195 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1196 // restore outgoing BEACON to support B/G-mixed mode
1197 if ((pAd->CommonCfg.Channel <= 14) &&
1198 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1199 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1200 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1202 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1203 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1204 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1205 MlmeUpdateTxRates(pAd, FALSE, 0);
1206 MakeIbssBeacon(pAd); // re-build BEACON frame
1207 AsicEnableIbssSync(pAd); // copy to on-chip memory
1208 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1211 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1213 if ((pAd->StaCfg.AdhocBGJoined) &&
1214 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1216 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1217 pAd->StaCfg.AdhocBGJoined = FALSE;
1220 if ((pAd->StaCfg.Adhoc20NJoined) &&
1221 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1223 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1224 pAd->StaCfg.Adhoc20NJoined = FALSE;
1230 if ((pAd->CommonCfg.Channel > 14)
1231 && (pAd->CommonCfg.bIEEE80211H == 1)
1232 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1234 RadarDetectPeriodic(pAd);
1237 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1238 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1240 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1241 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1243 MLME_START_REQ_STRUCT StartReq;
1245 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1246 LinkDown(pAd, FALSE);
1248 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1249 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1250 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1254 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1256 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1258 if (pEntry->ValidAsCLI == FALSE)
1261 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1262 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1266 else // no INFRA nor ADHOC connection
1269 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1270 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1271 goto SKIP_AUTO_SCAN_CONN;
1273 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1275 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1276 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1277 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1279 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1281 MLME_SCAN_REQ_STRUCT ScanReq;
1283 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1285 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1286 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1287 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1288 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1289 // Reset Missed scan number
1290 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1292 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1293 MlmeAutoReconnectLastSSID(pAd);
1295 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1297 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1300 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1304 MlmeAutoReconnectLastSSID(pAd);
1310 SKIP_AUTO_SCAN_CONN:
1312 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1314 pAd->MacTab.fAnyBASession = TRUE;
1315 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1317 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1319 pAd->MacTab.fAnyBASession = FALSE;
1320 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1328 IN PVOID SystemSpecific1,
1329 IN PVOID FunctionContext,
1330 IN PVOID SystemSpecific2,
1331 IN PVOID SystemSpecific3)
1334 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1336 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1337 RTMP_IndicateMediaState(pAd);
1338 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1341 // IRQL = DISPATCH_LEVEL
1343 IN PRTMP_ADAPTER pAd)
1345 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1346 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1348 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1350 MLME_CNTL_STATE_MACHINE,
1351 OID_802_11_BSSID_LIST_SCAN,
1354 RT28XX_MLME_HANDLER(pAd);
1358 // IRQL = DISPATCH_LEVEL
1359 VOID MlmeAutoReconnectLastSSID(
1360 IN PRTMP_ADAPTER pAd)
1364 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1365 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1366 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1368 NDIS_802_11_SSID OidSsid;
1369 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1370 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1372 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1374 MLME_CNTL_STATE_MACHINE,
1376 sizeof(NDIS_802_11_SSID),
1378 RT28XX_MLME_HANDLER(pAd);
1383 ==========================================================================
1384 Validate SSID for connection try and rescan purpose
1385 Valid SSID will have visible chars only.
1386 The valid length is from 0 to 32.
1387 IRQL = DISPATCH_LEVEL
1388 ==========================================================================
1390 BOOLEAN MlmeValidateSSID(
1396 if (SsidLen > MAX_LEN_OF_SSID)
1399 // Check each character value
1400 for (index = 0; index < SsidLen; index++)
1402 if (pSsid[index] < 0x20)
1410 VOID MlmeSelectTxRateTable(
1411 IN PRTMP_ADAPTER pAd,
1412 IN PMAC_TABLE_ENTRY pEntry,
1414 IN PUCHAR pTableSize,
1415 IN PUCHAR pInitTxRateIdx)
1419 // decide the rate table for tuning
1420 if (pAd->CommonCfg.TxRateTableSize > 0)
1422 *ppTable = RateSwitchTable;
1423 *pTableSize = RateSwitchTable[0];
1424 *pInitTxRateIdx = RateSwitchTable[1];
1429 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1431 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1433 !pAd->StaCfg.AdhocBOnlyJoined &&
1434 !pAd->StaCfg.AdhocBGJoined &&
1435 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1436 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1439 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1440 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1443 *ppTable = RateSwitchTable11N1S;
1444 *pTableSize = RateSwitchTable11N1S[0];
1445 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1448 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1450 !pAd->StaCfg.AdhocBOnlyJoined &&
1451 !pAd->StaCfg.AdhocBGJoined &&
1452 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1453 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1456 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1457 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1459 (pAd->Antenna.field.TxPath == 2))
1461 if (pAd->LatchRfRegs.Channel <= 14)
1463 *ppTable = RateSwitchTable11N2S;
1464 *pTableSize = RateSwitchTable11N2S[0];
1465 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1469 *ppTable = RateSwitchTable11N2SForABand;
1470 *pTableSize = RateSwitchTable11N2SForABand[0];
1471 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1477 if (pAd->CommonCfg.PhyMode == PHY_11B)
1479 *ppTable = RateSwitchTable11B;
1480 *pTableSize = RateSwitchTable11B[0];
1481 *pInitTxRateIdx = RateSwitchTable11B[1];
1484 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1487 if ((pEntry->RateLen == 4)
1488 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1492 // USe B Table when Only b-only Station in my IBSS .
1493 *ppTable = RateSwitchTable11B;
1494 *pTableSize = RateSwitchTable11B[0];
1495 *pInitTxRateIdx = RateSwitchTable11B[1];
1498 else if (pAd->LatchRfRegs.Channel <= 14)
1500 *ppTable = RateSwitchTable11BG;
1501 *pTableSize = RateSwitchTable11BG[0];
1502 *pInitTxRateIdx = RateSwitchTable11BG[1];
1507 *ppTable = RateSwitchTable11G;
1508 *pTableSize = RateSwitchTable11G[0];
1509 *pInitTxRateIdx = RateSwitchTable11G[1];
1515 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1516 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1518 *ppTable = RateSwitchTable11BGN1S;
1519 *pTableSize = RateSwitchTable11BGN1S[0];
1520 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1525 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1526 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1528 if (pAd->LatchRfRegs.Channel <= 14)
1530 *ppTable = RateSwitchTable11BGN2S;
1531 *pTableSize = RateSwitchTable11BGN2S[0];
1532 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1537 *ppTable = RateSwitchTable11BGN2SForABand;
1538 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1539 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1545 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1547 *ppTable = RateSwitchTable11N1S;
1548 *pTableSize = RateSwitchTable11N1S[0];
1549 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1554 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1556 if (pAd->LatchRfRegs.Channel <= 14)
1558 *ppTable = RateSwitchTable11N2S;
1559 *pTableSize = RateSwitchTable11N2S[0];
1560 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1564 *ppTable = RateSwitchTable11N2SForABand;
1565 *pTableSize = RateSwitchTable11N2SForABand[0];
1566 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1572 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1573 if ((pEntry->RateLen == 4)
1575 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1576 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1580 *ppTable = RateSwitchTable11B;
1581 *pTableSize = RateSwitchTable11B[0];
1582 *pInitTxRateIdx = RateSwitchTable11B[1];
1587 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1588 if ((pEntry->RateLen > 8)
1589 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1592 *ppTable = RateSwitchTable11BG;
1593 *pTableSize = RateSwitchTable11BG[0];
1594 *pInitTxRateIdx = RateSwitchTable11BG[1];
1599 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1600 if ((pEntry->RateLen == 8)
1601 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1604 *ppTable = RateSwitchTable11G;
1605 *pTableSize = RateSwitchTable11G[0];
1606 *pInitTxRateIdx = RateSwitchTable11G[1];
1612 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1613 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1615 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1617 *ppTable = RateSwitchTable11B;
1618 *pTableSize = RateSwitchTable11B[0];
1619 *pInitTxRateIdx = RateSwitchTable11B[1];
1621 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1623 *ppTable = RateSwitchTable11G;
1624 *pTableSize = RateSwitchTable11G[0];
1625 *pInitTxRateIdx = RateSwitchTable11G[1];
1630 *ppTable = RateSwitchTable11BG;
1631 *pTableSize = RateSwitchTable11BG[0];
1632 *pInitTxRateIdx = RateSwitchTable11BG[1];
1637 if (pAd->LatchRfRegs.Channel <= 14)
1639 if (pAd->CommonCfg.TxStream == 1)
1641 *ppTable = RateSwitchTable11N1S;
1642 *pTableSize = RateSwitchTable11N1S[0];
1643 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1644 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1648 *ppTable = RateSwitchTable11N2S;
1649 *pTableSize = RateSwitchTable11N2S[0];
1650 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1651 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1656 if (pAd->CommonCfg.TxStream == 1)
1658 *ppTable = RateSwitchTable11N1S;
1659 *pTableSize = RateSwitchTable11N1S[0];
1660 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1661 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1665 *ppTable = RateSwitchTable11N2SForABand;
1666 *pTableSize = RateSwitchTable11N2SForABand[0];
1667 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1668 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1672 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1673 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1679 ==========================================================================
1681 This routine checks if there're other APs out there capable for
1682 roaming. Caller should call this routine only when Link up in INFRA mode
1683 and channel quality is below CQI_GOOD_THRESHOLD.
1685 IRQL = DISPATCH_LEVEL
1688 ==========================================================================
1690 VOID MlmeCheckForRoaming(
1691 IN PRTMP_ADAPTER pAd,
1695 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1698 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1699 // put all roaming candidates into RoamTab, and sort in RSSI order
1700 BssTableInit(pRoamTab);
1701 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1703 pBss = &pAd->ScanTab.BssEntry[i];
1705 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1706 continue; // AP disappear
1707 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1708 continue; // RSSI too weak. forget it.
1709 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1710 continue; // skip current AP
1711 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1712 continue; // only AP with stronger RSSI is eligible for roaming
1714 // AP passing all above rules is put into roaming candidate table
1715 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1716 pRoamTab->BssNr += 1;
1719 if (pRoamTab->BssNr > 0)
1721 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1722 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1724 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1725 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1726 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1727 RT28XX_MLME_HANDLER(pAd);
1730 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1734 ==========================================================================
1736 This routine checks if there're other APs out there capable for
1737 roaming. Caller should call this routine only when link up in INFRA mode
1738 and channel quality is below CQI_GOOD_THRESHOLD.
1740 IRQL = DISPATCH_LEVEL
1743 ==========================================================================
1745 VOID MlmeCheckForFastRoaming(
1746 IN PRTMP_ADAPTER pAd,
1750 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1753 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1754 // put all roaming candidates into RoamTab, and sort in RSSI order
1755 BssTableInit(pRoamTab);
1756 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1758 pBss = &pAd->ScanTab.BssEntry[i];
1760 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1761 continue; // RSSI too weak. forget it.
1762 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1763 continue; // skip current AP
1764 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1765 continue; // skip different SSID
1766 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1767 continue; // skip AP without better RSSI
1769 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));
1770 // AP passing all above rules is put into roaming candidate table
1771 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1772 pRoamTab->BssNr += 1;
1775 if (pRoamTab->BssNr > 0)
1777 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1778 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1780 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1781 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1782 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1783 RT28XX_MLME_HANDLER(pAd);
1786 // Maybe site survey required
1789 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1791 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1792 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1793 pAd->StaCfg.ScanCnt = 2;
1794 pAd->StaCfg.LastScanTime = Now;
1799 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1803 ==========================================================================
1805 This routine calculates TxPER, RxPER of the past N-sec period. And
1806 according to the calculation result, ChannelQuality is calculated here
1807 to decide if current AP is still doing the job.
1809 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1811 StaCfg.ChannelQuality - 0..100
1813 IRQL = DISPATCH_LEVEL
1815 NOTE: This routine decide channle quality based on RX CRC error ratio.
1816 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1817 is performed right before this routine, so that this routine can decide
1818 channel quality based on the most up-to-date information
1819 ==========================================================================
1821 VOID MlmeCalculateChannelQuality(
1822 IN PRTMP_ADAPTER pAd,
1825 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1829 ULONG BeaconLostTime = BEACON_LOST_TIME;
1831 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1834 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1836 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1837 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1845 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1846 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1850 // calculate RX PER - don't take RxPER into consideration if too few sample
1852 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1856 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1859 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1861 if (INFRA_ON(pAd) &&
1862 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1863 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1865 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1866 pAd->Mlme.ChannelQuality = 0;
1873 else if (MaxRssi < -90)
1876 NorRssi = (MaxRssi + 90) * 2;
1878 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1879 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1880 TX_WEIGHTING * (100 - TxPRR) +
1881 RX_WEIGHTING* (100 - RxPER)) / 100;
1882 if (pAd->Mlme.ChannelQuality >= 100)
1883 pAd->Mlme.ChannelQuality = 100;
1889 IN PRTMP_ADAPTER pAd,
1890 IN PMAC_TABLE_ENTRY pEntry,
1891 IN PRTMP_TX_RATE_SWITCH pTxRate)
1893 UCHAR MaxMode = MODE_OFDM;
1895 MaxMode = MODE_HTGREENFIELD;
1897 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1898 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1900 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1902 if (pTxRate->CurrMCS < MCS_AUTO)
1903 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1905 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1906 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1910 // If peer adhoc is b-only mode, we can't send 11g rate.
1911 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1912 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1915 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1917 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1918 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1919 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1921 // Patch speed error in status page
1922 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1926 if (pTxRate->Mode <= MaxMode)
1927 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1929 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1930 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1932 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1934 // Reexam each bandwidth's SGI support.
1935 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1937 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1938 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1939 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1940 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1943 // Turn RTS/CTS rate to 6Mbps.
1944 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1946 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1947 if (pAd->MacTab.fAnyBASession)
1949 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1953 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1956 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1958 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1959 if (pAd->MacTab.fAnyBASession)
1961 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1965 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1968 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1970 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1973 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1975 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1978 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1979 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1980 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1981 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1983 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1984 pAd->WIFItestbed.bGreenField)
1985 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1988 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1992 ==========================================================================
1994 This routine calculates the acumulated TxPER of eaxh TxRate. And
1995 according to the calculation result, change CommonCfg.TxRate which
1996 is the stable TX Rate we expect the Radio situation could sustained.
1998 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2002 IRQL = DISPATCH_LEVEL
2005 call this routine every second
2006 ==========================================================================
2008 VOID MlmeDynamicTxRateSwitching(
2009 IN PRTMP_ADAPTER pAd)
2011 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2012 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2013 ULONG TxErrorRatio = 0;
2014 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2015 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2017 UCHAR TableSize = 0;
2018 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2019 CHAR Rssi, RssiOffset = 0;
2020 TX_STA_CNT1_STRUC StaTx1;
2021 TX_STA_CNT0_STRUC TxStaCnt0;
2022 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2023 MAC_TABLE_ENTRY *pEntry;
2026 // walk through MAC table, see if need to change AP's TX rate toward each entry
2028 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2030 pEntry = &pAd->MacTab.Content[i];
2032 // check if this entry need to switch rate automatically
2033 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2036 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2039 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2042 Rssi = RTMPMaxRssi(pAd,
2043 pAd->StaCfg.RssiSample.AvgRssi0,
2044 pAd->StaCfg.RssiSample.AvgRssi1,
2045 pAd->StaCfg.RssiSample.AvgRssi2);
2048 // Update statistic counter
2049 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2050 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2051 pAd->bUpdateBcnCntDone = TRUE;
2052 TxRetransmit = StaTx1.field.TxRetransmit;
2053 TxSuccess = StaTx1.field.TxSuccess;
2054 TxFailCount = TxStaCnt0.field.TxFailCount;
2055 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2057 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2058 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2059 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2060 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2061 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2062 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2064 // if no traffic in the past 1-sec period, don't change TX rate,
2065 // but clear all bad history. because the bad history may affect the next
2066 // Chariot throughput test
2067 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2068 pAd->RalinkCounters.OneSecTxRetryOkCount +
2069 pAd->RalinkCounters.OneSecTxFailCount;
2072 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2077 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2080 if (INFRA_ON(pAd) && (i == 1))
2081 Rssi = RTMPMaxRssi(pAd,
2082 pAd->StaCfg.RssiSample.AvgRssi0,
2083 pAd->StaCfg.RssiSample.AvgRssi1,
2084 pAd->StaCfg.RssiSample.AvgRssi2);
2086 Rssi = RTMPMaxRssi(pAd,
2087 pEntry->RssiSample.AvgRssi0,
2088 pEntry->RssiSample.AvgRssi1,
2089 pEntry->RssiSample.AvgRssi2);
2092 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2093 pEntry->OneSecTxRetryOkCount +
2094 pEntry->OneSecTxFailCount;
2097 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2100 CurrRateIdx = pEntry->CurrTxRateIndex;
2102 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2104 if (CurrRateIdx >= TableSize)
2106 CurrRateIdx = TableSize - 1;
2109 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2110 // So need to sync here.
2111 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2112 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2113 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2117 // Need to sync Real Tx rate and our record.
2118 // Then return for next DRS.
2119 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2120 pEntry->CurrTxRateIndex = InitTxRateIdx;
2121 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2123 // reset all OneSecTx counters
2124 RESET_ONE_SEC_TX_CNT(pEntry);
2128 // decide the next upgrade rate and downgrade rate, if any
2129 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2131 UpRateIdx = CurrRateIdx + 1;
2132 DownRateIdx = CurrRateIdx -1;
2134 else if (CurrRateIdx == 0)
2136 UpRateIdx = CurrRateIdx + 1;
2137 DownRateIdx = CurrRateIdx;
2139 else if (CurrRateIdx == (TableSize - 1))
2141 UpRateIdx = CurrRateIdx;
2142 DownRateIdx = CurrRateIdx - 1;
2145 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2147 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2149 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2150 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2154 TrainUp = pCurrTxRate->TrainUp;
2155 TrainDown = pCurrTxRate->TrainDown;
2158 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2161 // Keep the last time TxRateChangeAction status.
2163 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2168 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2169 // (criteria copied from RT2500 for Netopia case)
2171 if (TxTotalCnt <= 15)
2175 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2176 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2177 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2178 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2180 // check the existence and index of each needed MCS
2181 while (idx < pTable[0])
2183 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2185 if (pCurrTxRate->CurrMCS == MCS_0)
2189 else if (pCurrTxRate->CurrMCS == MCS_1)
2193 else if (pCurrTxRate->CurrMCS == MCS_2)
2197 else if (pCurrTxRate->CurrMCS == MCS_3)
2201 else if (pCurrTxRate->CurrMCS == MCS_4)
2205 else if (pCurrTxRate->CurrMCS == MCS_5)
2209 else if (pCurrTxRate->CurrMCS == MCS_6)
2213 //else if (pCurrTxRate->CurrMCS == MCS_7)
2214 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2218 else if (pCurrTxRate->CurrMCS == MCS_12)
2222 else if (pCurrTxRate->CurrMCS == MCS_13)
2226 else if (pCurrTxRate->CurrMCS == MCS_14)
2230 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
2234 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2238 else if (pCurrTxRate->CurrMCS == MCS_21)
2242 else if (pCurrTxRate->CurrMCS == MCS_22)
2246 else if (pCurrTxRate->CurrMCS == MCS_23)
2253 if (pAd->LatchRfRegs.Channel <= 14)
2255 if (pAd->NicConfig2.field.ExternalLNAForG)
2266 if (pAd->NicConfig2.field.ExternalLNAForA)
2277 if ((pTable == RateSwitchTable11BGN3S) ||
2278 (pTable == RateSwitchTable11N3S) ||
2279 (pTable == RateSwitchTable))
2280 {// N mode with 3 stream // 3*3
2281 if (MCS23 && (Rssi >= -70))
2283 else if (MCS22 && (Rssi >= -72))
2285 else if (MCS21 && (Rssi >= -76))
2287 else if (MCS20 && (Rssi >= -78))
2289 else if (MCS4 && (Rssi >= -82))
2291 else if (MCS3 && (Rssi >= -84))
2293 else if (MCS2 && (Rssi >= -86))
2295 else if (MCS1 && (Rssi >= -88))
2300 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2301 {// N mode with 2 stream
2302 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2304 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2306 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2308 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2310 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2312 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2314 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2316 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2321 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2322 {// N mode with 1 stream
2323 if (MCS7 && (Rssi > (-72+RssiOffset)))
2325 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2327 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2329 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2331 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2333 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2335 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2342 if (MCS7 && (Rssi > -70))
2344 else if (MCS6 && (Rssi > -74))
2346 else if (MCS5 && (Rssi > -78))
2348 else if (MCS4 && (Rssi > -82))
2350 else if (MCS4 == 0) // for B-only mode
2352 else if (MCS3 && (Rssi > -85))
2354 else if (MCS2 && (Rssi > -87))
2356 else if (MCS1 && (Rssi > -90))
2363 pEntry->CurrTxRateIndex = TxRateIdx;
2364 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2365 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2368 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2369 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2370 pEntry->fLastSecAccordingRSSI = TRUE;
2371 // reset all OneSecTx counters
2372 RESET_ONE_SEC_TX_CNT(pEntry);
2377 if (pEntry->fLastSecAccordingRSSI == TRUE)
2379 pEntry->fLastSecAccordingRSSI = FALSE;
2380 pEntry->LastSecTxRateChangeAction = 0;
2381 // reset all OneSecTx counters
2382 RESET_ONE_SEC_TX_CNT(pEntry);
2389 BOOLEAN bTrainUpDown = FALSE;
2391 pEntry->CurrTxRateStableTime ++;
2393 // downgrade TX quality if PER >= Rate-Down threshold
2394 if (TxErrorRatio >= TrainDown)
2396 bTrainUpDown = TRUE;
2397 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2399 // upgrade TX quality if PER <= Rate-Up threshold
2400 else if (TxErrorRatio <= TrainUp)
2402 bTrainUpDown = TRUE;
2403 bUpgradeQuality = TRUE;
2404 if (pEntry->TxQuality[CurrRateIdx])
2405 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2407 if (pEntry->TxRateUpPenalty)
2408 pEntry->TxRateUpPenalty --;
2409 else if (pEntry->TxQuality[UpRateIdx])
2410 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2413 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2417 // perform DRS - consider TxRate Down first, then rate up.
2418 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2420 pEntry->CurrTxRateIndex = DownRateIdx;
2422 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2424 pEntry->CurrTxRateIndex = UpRateIdx;
2429 // if rate-up happen, clear all bad history of all TX rates
2430 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2432 pEntry->CurrTxRateStableTime = 0;
2433 pEntry->TxRateUpPenalty = 0;
2434 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2435 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2436 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2439 // For TxRate fast train up
2441 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2443 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2445 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2447 bTxRateChanged = TRUE;
2449 // if rate-down happen, only clear DownRate's bad history
2450 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2452 pEntry->CurrTxRateStableTime = 0;
2453 pEntry->TxRateUpPenalty = 0; // no penalty
2454 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2455 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2456 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2459 // For TxRate fast train down
2461 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2463 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2465 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2467 bTxRateChanged = TRUE;
2471 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2472 bTxRateChanged = FALSE;
2475 pEntry->LastTxOkCount = TxSuccess;
2477 // reset all OneSecTx counters
2478 RESET_ONE_SEC_TX_CNT(pEntry);
2480 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2481 if (bTxRateChanged && pNextTxRate)
2483 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2489 ========================================================================
2490 Routine Description:
2491 Station side, Auto TxRate faster train up timer call back function.
2494 SystemSpecific1 - Not used.
2495 FunctionContext - Pointer to our Adapter context.
2496 SystemSpecific2 - Not used.
2497 SystemSpecific3 - Not used.
2502 ========================================================================
2504 VOID StaQuickResponeForRateUpExec(
2505 IN PVOID SystemSpecific1,
2506 IN PVOID FunctionContext,
2507 IN PVOID SystemSpecific2,
2508 IN PVOID SystemSpecific3)
2510 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2511 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2513 ULONG TxErrorRatio = 0;
2515 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2518 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2520 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2522 UCHAR TableSize = 0;
2523 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2524 TX_STA_CNT1_STRUC StaTx1;
2525 TX_STA_CNT0_STRUC TxStaCnt0;
2527 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2528 MAC_TABLE_ENTRY *pEntry;
2531 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2534 // walk through MAC table, see if need to change AP's TX rate toward each entry
2536 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2538 pEntry = &pAd->MacTab.Content[i];
2540 // check if this entry need to switch rate automatically
2541 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2545 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2546 if (pAd->Antenna.field.TxPath > 1)
2547 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2549 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2552 if (INFRA_ON(pAd) && (i == 1))
2553 Rssi = RTMPMaxRssi(pAd,
2554 pAd->StaCfg.RssiSample.AvgRssi0,
2555 pAd->StaCfg.RssiSample.AvgRssi1,
2556 pAd->StaCfg.RssiSample.AvgRssi2);
2558 Rssi = RTMPMaxRssi(pAd,
2559 pEntry->RssiSample.AvgRssi0,
2560 pEntry->RssiSample.AvgRssi1,
2561 pEntry->RssiSample.AvgRssi2);
2564 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2566 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2568 // decide the next upgrade rate and downgrade rate, if any
2569 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2571 UpRateIdx = CurrRateIdx + 1;
2572 DownRateIdx = CurrRateIdx -1;
2574 else if (CurrRateIdx == 0)
2576 UpRateIdx = CurrRateIdx + 1;
2577 DownRateIdx = CurrRateIdx;
2579 else if (CurrRateIdx == (TableSize - 1))
2581 UpRateIdx = CurrRateIdx;
2582 DownRateIdx = CurrRateIdx - 1;
2585 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2587 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2589 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2590 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2594 TrainUp = pCurrTxRate->TrainUp;
2595 TrainDown = pCurrTxRate->TrainDown;
2598 if (pAd->MacTab.Size == 1)
2600 // Update statistic counter
2601 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2602 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2604 TxRetransmit = StaTx1.field.TxRetransmit;
2605 TxSuccess = StaTx1.field.TxSuccess;
2606 TxFailCount = TxStaCnt0.field.TxFailCount;
2607 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2609 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2610 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2611 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2612 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2613 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2614 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2617 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2621 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2622 pEntry->OneSecTxRetryOkCount +
2623 pEntry->OneSecTxFailCount;
2626 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2631 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2632 // (criteria copied from RT2500 for Netopia case)
2634 if (TxTotalCnt <= 12)
2636 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2637 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2639 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2641 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2642 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2644 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2646 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2649 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2655 ULONG OneSecTxNoRetryOKRationCount;
2657 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2662 // downgrade TX quality if PER >= Rate-Down threshold
2663 if (TxErrorRatio >= TrainDown)
2665 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2668 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2670 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2672 // perform DRS - consider TxRate Down first, then rate up.
2673 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2675 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2677 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2678 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2683 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2685 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2689 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2691 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2696 // if rate-up happen, clear all bad history of all TX rates
2697 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2699 pAd->DrsCounters.TxRateUpPenalty = 0;
2700 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2701 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2703 bTxRateChanged = TRUE;
2706 // if rate-down happen, only clear DownRate's bad history
2707 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2709 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2711 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2712 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2713 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2715 bTxRateChanged = TRUE;
2720 bTxRateChanged = FALSE;
2723 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2724 if (bTxRateChanged && pNextTxRate)
2726 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2732 ==========================================================================
2734 This routine is executed periodically inside MlmePeriodicExec() after
2735 association with an AP.
2736 It checks if StaCfg.Psm is consistent with user policy (recorded in
2737 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2738 there're some conditions to consider:
2739 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2740 the time when Mibss==TRUE
2741 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2742 if outgoing traffic available in TxRing or MgmtRing.
2744 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2746 IRQL = DISPATCH_LEVEL
2748 ==========================================================================
2750 VOID MlmeCheckPsmChange(
2751 IN PRTMP_ADAPTER pAd,
2757 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2758 // 2. user wants either MAX_PSP or FAST_PSP
2759 // 3. but current psm is not in PWR_SAVE
2760 // 4. CNTL state machine is not doing SCANning
2761 // 5. no TX SUCCESS event for the past 1-sec period
2762 #ifdef NDIS51_MINIPORT
2763 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2764 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2767 PowerMode = pAd->StaCfg.WindowsPowerMode;
2769 if (INFRA_ON(pAd) &&
2770 (PowerMode != Ndis802_11PowerModeCAM) &&
2771 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2773 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2775 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2779 // add by johnli, use Rx OK data count per second to calculate throughput
2780 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2781 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2782 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2783 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2784 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2785 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2789 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2790 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2791 MlmeSetPsmBit(pAd, PWR_SAVE);
2792 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2794 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2798 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2804 // IRQL = PASSIVE_LEVEL
2805 // IRQL = DISPATCH_LEVEL
2807 IN PRTMP_ADAPTER pAd,
2810 AUTO_RSP_CFG_STRUC csr4;
2812 pAd->StaCfg.Psm = psm;
2813 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2814 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2815 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2817 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2820 // IRQL = DISPATCH_LEVEL
2821 VOID MlmeSetTxPreamble(
2822 IN PRTMP_ADAPTER pAd,
2823 IN USHORT TxPreamble)
2825 AUTO_RSP_CFG_STRUC csr4;
2828 // Always use Long preamble before verifiation short preamble functionality works well.
2829 // Todo: remove the following line if short preamble functionality works
2831 //TxPreamble = Rt802_11PreambleLong;
2833 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2834 if (TxPreamble == Rt802_11PreambleLong)
2836 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2837 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2838 csr4.field.AutoResponderPreamble = 0;
2842 // NOTE: 1Mbps should always use long preamble
2843 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2844 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2845 csr4.field.AutoResponderPreamble = 1;
2848 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2852 ==========================================================================
2854 Update basic rate bitmap
2855 ==========================================================================
2858 VOID UpdateBasicRateBitmap(
2859 IN PRTMP_ADAPTER pAdapter)
2862 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2863 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2864 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2865 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2866 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2869 /* if A mode, always use fix BasicRateBitMap */
2870 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2871 if (pAdapter->CommonCfg.Channel > 14)
2872 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2875 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2877 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2881 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2887 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2889 if (bitmap & (1 << i))
2891 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2893 if (sup_p[j] == rate[i])
2898 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2900 if (ext_p[j] == rate[i])
2906 } /* End of UpdateBasicRateBitmap */
2908 // IRQL = PASSIVE_LEVEL
2909 // IRQL = DISPATCH_LEVEL
2910 // bLinkUp is to identify the inital link speed.
2911 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2912 VOID MlmeUpdateTxRates(
2913 IN PRTMP_ADAPTER pAd,
2918 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2919 UCHAR MinSupport = RATE_54;
2920 ULONG BasicRateBitmap = 0;
2921 UCHAR CurrBasicRate = RATE_1;
2922 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2923 PHTTRANSMIT_SETTING pHtPhy = NULL;
2924 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2925 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2926 BOOLEAN *auto_rate_cur_p;
2927 UCHAR HtMcs = MCS_AUTO;
2929 // find max desired rate
2930 UpdateBasicRateBitmap(pAd);
2933 auto_rate_cur_p = NULL;
2934 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2936 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2938 case 2: Rate = RATE_1; num++; break;
2939 case 4: Rate = RATE_2; num++; break;
2940 case 11: Rate = RATE_5_5; num++; break;
2941 case 22: Rate = RATE_11; num++; break;
2942 case 12: Rate = RATE_6; num++; break;
2943 case 18: Rate = RATE_9; num++; break;
2944 case 24: Rate = RATE_12; num++; break;
2945 case 36: Rate = RATE_18; num++; break;
2946 case 48: Rate = RATE_24; num++; break;
2947 case 72: Rate = RATE_36; num++; break;
2948 case 96: Rate = RATE_48; num++; break;
2949 case 108: Rate = RATE_54; num++; break;
2950 //default: Rate = RATE_1; break;
2952 if (MaxDesire < Rate) MaxDesire = Rate;
2955 //===========================================================================
2956 //===========================================================================
2958 pHtPhy = &pAd->StaCfg.HTPhyMode;
2959 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2960 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2962 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2963 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2965 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2966 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2967 (MaxDesire > RATE_11))
2969 MaxDesire = RATE_11;
2973 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2974 pMinHtPhy->word = 0;
2975 pMaxHtPhy->word = 0;
2978 // Auto rate switching is enabled only if more than one DESIRED RATES are
2979 // specified; otherwise disabled
2982 *auto_rate_cur_p = FALSE;
2986 *auto_rate_cur_p = TRUE;
2990 if (HtMcs != MCS_AUTO)
2992 *auto_rate_cur_p = FALSE;
2996 *auto_rate_cur_p = TRUE;
3000 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3002 pSupRate = &pAd->StaActive.SupRate[0];
3003 pExtRate = &pAd->StaActive.ExtRate[0];
3004 SupRateLen = pAd->StaActive.SupRateLen;
3005 ExtRateLen = pAd->StaActive.ExtRateLen;
3009 pSupRate = &pAd->CommonCfg.SupRate[0];
3010 pExtRate = &pAd->CommonCfg.ExtRate[0];
3011 SupRateLen = pAd->CommonCfg.SupRateLen;
3012 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3015 // find max supported rate
3016 for (i=0; i<SupRateLen; i++)
3018 switch (pSupRate[i] & 0x7f)
3020 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3021 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3022 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3023 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3024 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3025 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3026 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3027 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3028 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3029 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3030 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3031 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3032 default: Rate = RATE_1; break;
3034 if (MaxSupport < Rate) MaxSupport = Rate;
3036 if (MinSupport > Rate) MinSupport = Rate;
3039 for (i=0; i<ExtRateLen; i++)
3041 switch (pExtRate[i] & 0x7f)
3043 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3044 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3045 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3046 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3047 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3048 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3049 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3050 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3051 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3052 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3053 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3054 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3055 default: Rate = RATE_1; break;
3057 if (MaxSupport < Rate) MaxSupport = Rate;
3059 if (MinSupport > Rate) MinSupport = Rate;
3062 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3064 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3065 // the DURATION field of outgoing uniicast DATA/MGMT frame
3066 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3068 if (BasicRateBitmap & (0x01 << i))
3069 CurrBasicRate = (UCHAR)i;
3070 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3073 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3074 // max tx rate = min {max desire rate, max supported rate}
3075 if (MaxSupport < MaxDesire)
3076 pAd->CommonCfg.MaxTxRate = MaxSupport;
3078 pAd->CommonCfg.MaxTxRate = MaxDesire;
3080 pAd->CommonCfg.MinTxRate = MinSupport;
3081 if (*auto_rate_cur_p)
3085 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3087 if (bLinkUp == TRUE)
3088 pAd->CommonCfg.TxRate = RATE_24;
3090 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3093 pAd->CommonCfg.TxRate = RATE_11;
3095 pAd->CommonCfg.TxRate = RATE_24;
3097 // should never exceed MaxTxRate (consider 11B-only mode)
3098 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3099 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3101 pAd->CommonCfg.TxRateIndex = 0;
3105 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3106 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3107 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3109 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3110 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3111 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3112 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3115 if (pAd->CommonCfg.TxRate <= RATE_11)
3117 pMaxHtPhy->field.MODE = MODE_CCK;
3118 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3119 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3123 pMaxHtPhy->field.MODE = MODE_OFDM;
3124 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3125 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3126 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3128 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3131 pHtPhy->word = (pMaxHtPhy->word);
3132 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3134 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3135 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3136 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3140 switch (pAd->CommonCfg.PhyMode)
3142 case PHY_11BG_MIXED:
3144 case PHY_11BGN_MIXED:
3145 pAd->CommonCfg.MlmeRate = RATE_1;
3146 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3147 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3148 pAd->CommonCfg.RtsRate = RATE_11;
3152 case PHY_11AGN_MIXED:
3153 case PHY_11GN_MIXED:
3155 case PHY_11AN_MIXED:
3157 pAd->CommonCfg.MlmeRate = RATE_6;
3158 pAd->CommonCfg.RtsRate = RATE_6;
3159 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3160 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3162 case PHY_11ABG_MIXED:
3163 case PHY_11ABGN_MIXED:
3164 if (pAd->CommonCfg.Channel <= 14)
3166 pAd->CommonCfg.MlmeRate = RATE_1;
3167 pAd->CommonCfg.RtsRate = RATE_1;
3168 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3169 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3173 pAd->CommonCfg.MlmeRate = RATE_6;
3174 pAd->CommonCfg.RtsRate = RATE_6;
3175 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3176 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3180 pAd->CommonCfg.MlmeRate = RATE_6;
3181 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3182 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3183 pAd->CommonCfg.RtsRate = RATE_1;
3187 // Keep Basic Mlme Rate.
3189 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3190 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3191 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3193 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3194 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3197 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3198 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3199 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3200 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3201 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3202 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3203 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 ));
3207 ==========================================================================
3209 This function update HT Rate setting.
3210 Input Wcid value is valid for 2 case :
3211 1. it's used for Station in infra mode that copy AP rate to Mactable.
3212 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3214 IRQL = DISPATCH_LEVEL
3216 ==========================================================================
3218 VOID MlmeUpdateHtTxRates(
3219 IN PRTMP_ADAPTER pAd,
3222 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3224 RT_HT_CAPABILITY *pRtHtCap = NULL;
3225 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3228 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3229 PHTTRANSMIT_SETTING pHtPhy = NULL;
3230 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3231 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3232 BOOLEAN *auto_rate_cur_p;
3234 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3236 auto_rate_cur_p = NULL;
3239 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3240 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3241 pHtPhy = &pAd->StaCfg.HTPhyMode;
3242 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3243 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3245 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3248 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3250 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3253 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3254 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3255 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3256 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3257 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3258 pMaxHtPhy->field.STBC = STBC_USE;
3260 pMaxHtPhy->field.STBC = STBC_NONE;
3264 if (pDesireHtPhy->bHtEnable == FALSE)
3267 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3268 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3269 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3270 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3271 pMaxHtPhy->field.STBC = STBC_USE;
3273 pMaxHtPhy->field.STBC = STBC_NONE;
3276 // Decide MAX ht rate.
3277 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3278 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3280 pMaxHtPhy->field.MODE = MODE_HTMIX;
3282 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3283 pMaxHtPhy->field.BW = BW_40;
3285 pMaxHtPhy->field.BW = BW_20;
3287 if (pMaxHtPhy->field.BW == BW_20)
3288 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3290 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3292 for (i=23; i>=0; i--) // 3*3
3295 bitmask = (1<<(i-(j*8)));
3297 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3299 pMaxHtPhy->field.MCS = i;
3307 // Copy MIN ht rate. rt2860???
3308 pMinHtPhy->field.BW = BW_20;
3309 pMinHtPhy->field.MCS = 0;
3310 pMinHtPhy->field.STBC = 0;
3311 pMinHtPhy->field.ShortGI = 0;
3312 //If STA assigns fixed rate. update to fixed here.
3313 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3315 if (pDesireHtPhy->MCSSet[4] != 0)
3317 pMaxHtPhy->field.MCS = 32;
3318 pMinHtPhy->field.MCS = 32;
3319 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3322 for (i=23; (CHAR)i >= 0; i--) // 3*3
3325 bitmask = (1<<(i-(j*8)));
3326 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3328 pMaxHtPhy->field.MCS = i;
3329 pMinHtPhy->field.MCS = i;
3338 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3339 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3340 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3341 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3342 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3344 // use default now. rt2860
3345 if (pDesireHtPhy->MCSSet[0] != 0xff)
3346 *auto_rate_cur_p = FALSE;
3348 *auto_rate_cur_p = TRUE;
3350 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3351 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3352 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3353 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3356 // IRQL = DISPATCH_LEVEL
3358 IN PRTMP_ADAPTER pAd)
3360 RT28XX_MLME_RADIO_OFF(pAd);
3363 // IRQL = DISPATCH_LEVEL
3365 IN PRTMP_ADAPTER pAd)
3367 RT28XX_MLME_RADIO_ON(pAd);
3370 // ===========================================================================================
3372 // ===========================================================================================
3375 /*! \brief initialize BSS table
3376 * \param p_tab pointer to the table
3381 IRQL = PASSIVE_LEVEL
3382 IRQL = DISPATCH_LEVEL
3391 Tab->BssOverlapNr = 0;
3392 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3394 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3395 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3400 IN PRTMP_ADAPTER pAd,
3405 Tab->numAsOriginator = 0;
3406 Tab->numAsRecipient = 0;
3407 NdisAllocateSpinLock(&pAd->BATabLock);
3408 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3410 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3411 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3413 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3415 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3419 /*! \brief search the BSS table by SSID
3420 * \param p_tab pointer to the bss table
3421 * \param ssid SSID string
3422 * \return index of the table, BSS_NOT_FOUND if not in the table
3425 * \note search by sequential search
3427 IRQL = DISPATCH_LEVEL
3430 ULONG BssTableSearch(
3437 for (i = 0; i < Tab->BssNr; i++)
3440 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3441 // We should distinguish this case.
3443 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3444 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3445 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3450 return (ULONG)BSS_NOT_FOUND;
3453 ULONG BssSsidTableSearch(
3462 for (i = 0; i < Tab->BssNr; i++)
3465 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3466 // We should distinguish this case.
3468 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3469 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3470 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3471 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3476 return (ULONG)BSS_NOT_FOUND;
3479 ULONG BssTableSearchWithSSID(
3488 for (i = 0; i < Tab->BssNr; i++)
3490 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3491 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3492 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3493 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3494 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3495 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3500 return (ULONG)BSS_NOT_FOUND;
3503 // IRQL = DISPATCH_LEVEL
3504 VOID BssTableDeleteEntry(
3505 IN OUT BSS_TABLE *Tab,
3511 for (i = 0; i < Tab->BssNr; i++)
3513 if ((Tab->BssEntry[i].Channel == Channel) &&
3514 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3516 for (j = i; j < Tab->BssNr - 1; j++)
3518 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3520 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3528 ========================================================================
3529 Routine Description:
3530 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3533 // IRQL = DISPATCH_LEVEL
3534 ========================================================================
3536 VOID BATableDeleteORIEntry(
3537 IN OUT PRTMP_ADAPTER pAd,
3538 IN BA_ORI_ENTRY *pBAORIEntry)
3541 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3543 NdisAcquireSpinLock(&pAd->BATabLock);
3544 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3546 pAd->BATable.numAsOriginator -= 1;
3547 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3548 // Erase Bitmap flag.
3550 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3551 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3552 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3553 pBAORIEntry->Token = 1;
3554 // Not clear Sequence here.
3555 NdisReleaseSpinLock(&pAd->BATabLock);
3565 IRQL = DISPATCH_LEVEL
3569 IN PRTMP_ADAPTER pAd,
3570 OUT BSS_ENTRY *pBss,
3575 IN USHORT BeaconPeriod,
3576 IN PCF_PARM pCfParm,
3578 IN USHORT CapabilityInfo,
3580 IN UCHAR SupRateLen,
3582 IN UCHAR ExtRateLen,
3583 IN HT_CAPABILITY_IE *pHtCapability,
3584 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3585 IN UCHAR HtCapabilityLen,
3586 IN UCHAR AddHtInfoLen,
3587 IN UCHAR NewExtChanOffset,
3590 IN LARGE_INTEGER TimeStamp,
3592 IN PEDCA_PARM pEdcaParm,
3593 IN PQOS_CAPABILITY_PARM pQosCapability,
3594 IN PQBSS_LOAD_PARM pQbssLoad,
3595 IN USHORT LengthVIE,
3596 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3598 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3599 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3603 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3604 // Or send beacon /probe response with SSID len matching real SSID length,
3605 // but SSID is all zero. such as "00-00-00-00" with length 4.
3606 // We have to prevent this case overwrite correct table
3607 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3609 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3610 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3611 pBss->SsidLen = SsidLen;
3617 pBss->BssType = BssType;
3618 pBss->BeaconPeriod = BeaconPeriod;
3619 if (BssType == BSS_INFRA)
3621 if (pCfParm->bValid)
3623 pBss->CfpCount = pCfParm->CfpCount;
3624 pBss->CfpPeriod = pCfParm->CfpPeriod;
3625 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3626 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3631 pBss->AtimWin = AtimWin;
3634 pBss->CapabilityInfo = CapabilityInfo;
3635 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3636 // Combine with AuthMode, they will decide the connection methods.
3637 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3638 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3639 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3640 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3642 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3643 pBss->SupRateLen = SupRateLen;
3644 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3645 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3646 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3647 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3648 pBss->NewExtChanOffset = NewExtChanOffset;
3649 pBss->ExtRateLen = ExtRateLen;
3650 pBss->Channel = Channel;
3651 pBss->CentralChannel = Channel;
3653 // Update CkipFlag. if not exists, the value is 0x0
3654 pBss->CkipFlag = CkipFlag;
3656 // New for microsoft Fixed IEs
3657 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3658 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3659 pBss->FixIEs.Capabilities = CapabilityInfo;
3661 // New for microsoft Variable IEs
3664 pBss->VarIELen = LengthVIE;
3665 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3672 pBss->AddHtInfoLen = 0;
3673 pBss->HtCapabilityLen = 0;
3675 if (HtCapabilityLen> 0)
3677 pBss->HtCapabilityLen = HtCapabilityLen;
3678 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3679 if (AddHtInfoLen > 0)
3681 pBss->AddHtInfoLen = AddHtInfoLen;
3682 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3684 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3686 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3688 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3690 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3695 BssCipherParse(pBss);
3699 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3701 pBss->EdcaParm.bValid = FALSE;
3703 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3705 pBss->QosCapability.bValid = FALSE;
3707 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3709 pBss->QbssLoad.bValid = FALSE;
3716 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3717 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3719 pEid = (PEID_STRUCT) pVIE;
3721 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3726 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3728 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3730 pBss->WpaIE.IELen = 0;
3733 pBss->WpaIE.IELen = pEid->Len + 2;
3734 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3738 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3740 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3742 pBss->RsnIE.IELen = 0;
3745 pBss->RsnIE.IELen = pEid->Len + 2;
3746 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3750 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3751 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3757 * \brief insert an entry into the bss table
3758 * \param p_tab The BSS table
3759 * \param Bssid BSSID
3761 * \param ssid_len Length of SSID
3763 * \param beacon_period
3770 * \param channel_idx
3774 * \note If SSID is identical, the old entry will be replaced by the new one
3776 IRQL = DISPATCH_LEVEL
3779 ULONG BssTableSetEntry(
3780 IN PRTMP_ADAPTER pAd,
3786 IN USHORT BeaconPeriod,
3789 IN USHORT CapabilityInfo,
3791 IN UCHAR SupRateLen,
3793 IN UCHAR ExtRateLen,
3794 IN HT_CAPABILITY_IE *pHtCapability,
3795 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3796 IN UCHAR HtCapabilityLen,
3797 IN UCHAR AddHtInfoLen,
3798 IN UCHAR NewExtChanOffset,
3801 IN LARGE_INTEGER TimeStamp,
3803 IN PEDCA_PARM pEdcaParm,
3804 IN PQOS_CAPABILITY_PARM pQosCapability,
3805 IN PQBSS_LOAD_PARM pQbssLoad,
3806 IN USHORT LengthVIE,
3807 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3811 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3812 if (Idx == BSS_NOT_FOUND)
3814 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3817 // It may happen when BSS Table was full.
3818 // The desired AP will not be added into BSS Table
3819 // In this case, if we found the desired AP then overwrite BSS Table.
3821 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3823 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3824 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3826 Idx = Tab->BssOverlapNr;
3827 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3828 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3829 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3830 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3836 return BSS_NOT_FOUND;
3840 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3841 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3842 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3848 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3849 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3850 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3853 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3854 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3855 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3864 // IRQL = DISPATCH_LEVEL
3865 VOID BssTableSsidSort(
3866 IN PRTMP_ADAPTER pAd,
3867 OUT BSS_TABLE *OutTab,
3872 BssTableInit(OutTab);
3874 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3876 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3877 BOOLEAN bIsHiddenApIncluded = FALSE;
3879 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3880 (pAd->MlmeAux.Channel > 14) &&
3881 RadarChannelCheck(pAd, pInBss->Channel))
3885 bIsHiddenApIncluded = TRUE;
3888 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3889 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3891 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3893 // 2.4G/5G N only mode
3894 if ((pInBss->HtCapabilityLen == 0) &&
3895 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3897 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3902 // Check the Authmode first
3903 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3905 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3906 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3910 // Check cipher suite, AP must have more secured cipher than station setting
3911 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3913 // If it's not mixed mode, we should only let BSS pass with the same encryption
3914 if (pInBss->WPA.bMixMode == FALSE)
3915 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3918 // check group cipher
3921 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3922 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3924 pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3927 // check pairwise cipher, skip if none matched
3928 // If profile set to AES, let it pass without question.
3929 // If profile set to TKIP, we must find one mateched
3930 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3931 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3932 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3935 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3937 // If it's not mixed mode, we should only let BSS pass with the same encryption
3938 if (pInBss->WPA2.bMixMode == FALSE)
3939 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3942 // check group cipher
3945 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3946 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3948 pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3951 // check pairwise cipher, skip if none matched
3952 // If profile set to AES, let it pass without question.
3953 // If profile set to TKIP, we must find one mateched
3954 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3955 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3956 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3960 // Bss Type matched, SSID matched.
3961 // We will check wepstatus for qualification Bss
3962 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3964 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3966 // For the SESv2 case, we will not qualify WepStatus.
3972 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3973 // It definitely will fail. So, skip it.
3974 // CCX also require not even try to connect it!!
3978 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3979 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3980 if ((pInBss->CentralChannel != pInBss->Channel) &&
3981 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3983 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3985 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3987 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3991 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3998 // copy matching BSS from InTab to OutTab
3999 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4003 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4005 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4007 // 2.4G/5G N only mode
4008 if ((pInBss->HtCapabilityLen == 0) &&
4009 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4011 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4016 // Check the Authmode first
4017 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4019 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4020 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4024 // Check cipher suite, AP must have more secured cipher than station setting
4025 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4027 // If it's not mixed mode, we should only let BSS pass with the same encryption
4028 if (pInBss->WPA.bMixMode == FALSE)
4029 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4032 // check group cipher
4033 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4036 // check pairwise cipher, skip if none matched
4037 // If profile set to AES, let it pass without question.
4038 // If profile set to TKIP, we must find one mateched
4039 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4040 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4041 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4044 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4046 // If it's not mixed mode, we should only let BSS pass with the same encryption
4047 if (pInBss->WPA2.bMixMode == FALSE)
4048 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4051 // check group cipher
4052 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4055 // check pairwise cipher, skip if none matched
4056 // If profile set to AES, let it pass without question.
4057 // If profile set to TKIP, we must find one mateched
4058 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4059 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4060 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4064 // Bss Type matched, SSID matched.
4065 // We will check wepstatus for qualification Bss
4066 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4069 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4070 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4071 if ((pInBss->CentralChannel != pInBss->Channel) &&
4072 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4074 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4076 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4078 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4082 // copy matching BSS from InTab to OutTab
4083 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4088 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4092 BssTableSortByRssi(OutTab);
4096 // IRQL = DISPATCH_LEVEL
4097 VOID BssTableSortByRssi(
4098 IN OUT BSS_TABLE *OutTab)
4103 for (i = 0; i < OutTab->BssNr - 1; i++)
4105 for (j = i+1; j < OutTab->BssNr; j++)
4107 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4109 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4110 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4111 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4117 VOID BssCipherParse(
4118 IN OUT PBSS_ENTRY pBss)
4122 PRSN_IE_HEADER_STRUCT pRsnHeader;
4123 PCIPHER_SUITE_STRUCT pCipher;
4124 PAKM_SUITE_STRUCT pAKM;
4127 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4130 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4134 pBss->WepStatus = Ndis802_11WEPEnabled;
4138 pBss->WepStatus = Ndis802_11WEPDisabled;
4140 // Set default to disable & open authentication before parsing variable IE
4141 pBss->AuthMode = Ndis802_11AuthModeOpen;
4142 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4145 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4146 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4147 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4148 pBss->WPA.RsnCapability = 0;
4149 pBss->WPA.bMixMode = FALSE;
4151 // Init WPA2 setting
4152 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4153 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4154 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4155 pBss->WPA2.RsnCapability = 0;
4156 pBss->WPA2.bMixMode = FALSE;
4159 Length = (INT) pBss->VarIELen;
4163 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4164 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4165 pEid = (PEID_STRUCT) pTmp;
4169 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4170 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4176 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4177 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4178 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4179 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4182 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4183 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4184 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4187 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4188 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4189 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4195 // if Cisco IE_WPA, break
4198 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4203 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4205 // if unsupported vendor specific IE
4208 // Skip OUI, version, and multicast suite
4209 // This part should be improved in the future when AP supported multiple cipher suite.
4210 // For now, it's OK since almost all APs have fixed cipher suite supported.
4211 // pTmp = (PUCHAR) pEid->Octet;
4214 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4222 // Parse group cipher
4227 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4230 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4233 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4234 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4238 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4241 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4246 // number of unicast suite
4249 // skip all unicast cipher suites
4250 //Count = *(PUSHORT) pTmp;
4251 Count = (pTmp[1]<<8) + pTmp[0];
4252 pTmp += sizeof(USHORT);
4254 // Parsing all unicast cipher suite
4259 TmpCipher = Ndis802_11WEPDisabled;
4263 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4264 TmpCipher = Ndis802_11Encryption1Enabled;
4267 TmpCipher = Ndis802_11Encryption2Enabled;
4270 TmpCipher = Ndis802_11Encryption3Enabled;
4275 if (TmpCipher > pBss->WPA.PairCipher)
4277 // Move the lower cipher suite to PairCipherAux
4278 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4279 pBss->WPA.PairCipher = TmpCipher;
4283 pBss->WPA.PairCipherAux = TmpCipher;
4289 // 4. get AKM suite counts
4290 //Count = *(PUSHORT) pTmp;
4291 Count = (pTmp[1]<<8) + pTmp[0];
4292 pTmp += sizeof(USHORT);
4298 // Set AP support WPA mode
4299 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4300 pBss->AuthMode = Ndis802_11AuthModeWPA;
4302 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4305 // Set AP support WPA mode
4306 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4307 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4309 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4316 // Fixed for WPA-None
4317 if (pBss->BssType == BSS_ADHOC)
4319 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4320 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4321 pBss->WepStatus = pBss->WPA.GroupCipher;
4322 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4323 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4326 pBss->WepStatus = pBss->WPA.PairCipher;
4328 // Check the Pair & Group, if different, turn on mixed mode flag
4329 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4330 pBss->WPA.bMixMode = TRUE;
4335 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4337 // 0. Version must be 1
4338 if (le2cpu16(pRsnHeader->Version) != 1)
4340 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4342 // 1. Check group cipher
4343 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4344 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4347 // Parse group cipher
4348 switch (pCipher->Type)
4352 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4355 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4358 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4359 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4363 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4366 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4371 // set to correct offset for next parsing
4372 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4374 // 2. Get pairwise cipher counts
4375 //Count = *(PUSHORT) pTmp;
4376 Count = (pTmp[1]<<8) + pTmp[0];
4377 pTmp += sizeof(USHORT);
4379 // 3. Get pairwise cipher
4380 // Parsing all unicast cipher suite
4384 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4385 TmpCipher = Ndis802_11WEPDisabled;
4386 switch (pCipher->Type)
4389 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4390 TmpCipher = Ndis802_11Encryption1Enabled;
4393 TmpCipher = Ndis802_11Encryption2Enabled;
4396 TmpCipher = Ndis802_11Encryption3Enabled;
4401 if (TmpCipher > pBss->WPA2.PairCipher)
4403 // Move the lower cipher suite to PairCipherAux
4404 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4405 pBss->WPA2.PairCipher = TmpCipher;
4409 pBss->WPA2.PairCipherAux = TmpCipher;
4411 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4415 // 4. get AKM suite counts
4416 //Count = *(PUSHORT) pTmp;
4417 Count = (pTmp[1]<<8) + pTmp[0];
4418 pTmp += sizeof(USHORT);
4420 // 5. Get AKM ciphers
4421 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4422 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4428 // Set AP support WPA mode
4429 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4430 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4432 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4435 // Set AP support WPA mode
4436 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4437 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4439 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4444 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4446 // Fixed for WPA-None
4447 if (pBss->BssType == BSS_ADHOC)
4449 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4450 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4451 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4452 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4453 pBss->WepStatus = pBss->WPA.GroupCipher;
4454 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4455 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4457 pBss->WepStatus = pBss->WPA2.PairCipher;
4459 // 6. Get RSN capability
4460 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4461 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4462 pTmp += sizeof(USHORT);
4464 // Check the Pair & Group, if different, turn on mixed mode flag
4465 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4466 pBss->WPA2.bMixMode = TRUE;
4472 Length -= (pEid->Len + 2);
4476 // ===========================================================================================
4478 // ===========================================================================================
4480 /*! \brief generates a random mac address value for IBSS BSSID
4481 * \param Addr the bssid location
4486 VOID MacAddrRandomBssid(
4487 IN PRTMP_ADAPTER pAd,
4492 for (i = 0; i < MAC_ADDR_LEN; i++)
4494 pAddr[i] = RandomByte(pAd);
4497 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4500 /*! \brief init the management mac frame header
4501 * \param p_hdr mac header
4502 * \param subtype subtype of the frame
4503 * \param p_ds destination address, don't care if it is a broadcast address
4505 * \pre the station has the following information in the pAd->StaCfg
4509 * \note this function initializes the following field
4511 IRQL = PASSIVE_LEVEL
4512 IRQL = DISPATCH_LEVEL
4515 VOID MgtMacHeaderInit(
4516 IN PRTMP_ADAPTER pAd,
4517 IN OUT PHEADER_802_11 pHdr80211,
4523 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4525 pHdr80211->FC.Type = BTYPE_MGMT;
4526 pHdr80211->FC.SubType = SubType;
4527 pHdr80211->FC.ToDs = ToDs;
4528 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4530 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4532 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4535 // ===========================================================================================
4537 // ===========================================================================================
4539 /*!***************************************************************************
4540 * This routine build an outgoing frame, and fill all information specified
4541 * in argument list to the frame body. The actual frame size is the summation
4544 * Buffer - pointer to a pre-allocated memory segment
4545 * args - a list of <int arg_size, arg> pairs.
4546 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4547 * function will FAIL!!!
4549 * Size of the buffer
4551 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4553 IRQL = PASSIVE_LEVEL
4554 IRQL = DISPATCH_LEVEL
4556 ****************************************************************************/
4557 ULONG MakeOutgoingFrame(
4559 OUT ULONG *FrameLen, ...)
4566 // calculates the total length
4568 va_start(Args, FrameLen);
4571 leng = va_arg(Args, int);
4572 if (leng == END_OF_ARGS)
4576 p = va_arg(Args, PVOID);
4577 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4578 TotLeng = TotLeng + leng;
4581 va_end(Args); /* clean up */
4582 *FrameLen = TotLeng;
4586 // ===========================================================================================
4588 // ===========================================================================================
4590 /*! \brief Initialize The MLME Queue, used by MLME Functions
4591 * \param *Queue The MLME Queue
4592 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4595 * \note Because this is done only once (at the init stage), no need to be locked
4597 IRQL = PASSIVE_LEVEL
4600 NDIS_STATUS MlmeQueueInit(
4601 IN MLME_QUEUE *Queue)
4605 NdisAllocateSpinLock(&Queue->Lock);
4611 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4613 Queue->Entry[i].Occupied = FALSE;
4614 Queue->Entry[i].MsgLen = 0;
4615 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4618 return NDIS_STATUS_SUCCESS;
4621 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4622 * \param *Queue The MLME Queue
4623 * \param Machine The State Machine Id
4624 * \param MsgType The Message Type
4625 * \param MsgLen The Message length
4626 * \param *Msg The message pointer
4627 * \return TRUE if enqueue is successful, FALSE if the queue is full
4630 * \note The message has to be initialized
4632 IRQL = PASSIVE_LEVEL
4633 IRQL = DISPATCH_LEVEL
4636 BOOLEAN MlmeEnqueue(
4637 IN PRTMP_ADAPTER pAd,
4644 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4646 // Do nothing if the driver is starting halt state.
4647 // This might happen when timer already been fired before cancel timer with mlmehalt
4648 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4651 // First check the size, it MUST not exceed the mlme queue size
4652 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4654 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4658 if (MlmeQueueFull(Queue))
4663 NdisAcquireSpinLock(&(Queue->Lock));
4667 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4672 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4673 Queue->Entry[Tail].Occupied = TRUE;
4674 Queue->Entry[Tail].Machine = Machine;
4675 Queue->Entry[Tail].MsgType = MsgType;
4676 Queue->Entry[Tail].MsgLen = MsgLen;
4680 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4683 NdisReleaseSpinLock(&(Queue->Lock));
4687 /*! \brief This function is used when Recv gets a MLME message
4688 * \param *Queue The MLME Queue
4689 * \param TimeStampHigh The upper 32 bit of timestamp
4690 * \param TimeStampLow The lower 32 bit of timestamp
4691 * \param Rssi The receiving RSSI strength
4692 * \param MsgLen The length of the message
4693 * \param *Msg The message pointer
4694 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4698 IRQL = DISPATCH_LEVEL
4701 BOOLEAN MlmeEnqueueForRecv(
4702 IN PRTMP_ADAPTER pAd,
4704 IN ULONG TimeStampHigh,
4705 IN ULONG TimeStampLow,
4714 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4716 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4718 // Do nothing if the driver is starting halt state.
4719 // This might happen when timer already been fired before cancel timer with mlmehalt
4720 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4722 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4726 // First check the size, it MUST not exceed the mlme queue size
4727 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4729 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4733 if (MlmeQueueFull(Queue))
4739 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4741 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4746 // OK, we got all the informations, it is time to put things into queue
4747 NdisAcquireSpinLock(&(Queue->Lock));
4751 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4755 Queue->Entry[Tail].Occupied = TRUE;
4756 Queue->Entry[Tail].Machine = Machine;
4757 Queue->Entry[Tail].MsgType = MsgType;
4758 Queue->Entry[Tail].MsgLen = MsgLen;
4759 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4760 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4761 Queue->Entry[Tail].Rssi0 = Rssi0;
4762 Queue->Entry[Tail].Rssi1 = Rssi1;
4763 Queue->Entry[Tail].Rssi2 = Rssi2;
4764 Queue->Entry[Tail].Signal = Signal;
4765 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4767 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4771 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4774 NdisReleaseSpinLock(&(Queue->Lock));
4776 RT28XX_MLME_HANDLER(pAd);
4782 /*! \brief Dequeue a message from the MLME Queue
4783 * \param *Queue The MLME Queue
4784 * \param *Elem The message dequeued from MLME Queue
4785 * \return TRUE if the Elem contains something, FALSE otherwise
4789 IRQL = DISPATCH_LEVEL
4792 BOOLEAN MlmeDequeue(
4793 IN MLME_QUEUE *Queue,
4794 OUT MLME_QUEUE_ELEM **Elem)
4796 NdisAcquireSpinLock(&(Queue->Lock));
4797 *Elem = &(Queue->Entry[Queue->Head]);
4800 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4804 NdisReleaseSpinLock(&(Queue->Lock));
4808 // IRQL = DISPATCH_LEVEL
4809 VOID MlmeRestartStateMachine(
4810 IN PRTMP_ADAPTER pAd)
4813 MLME_QUEUE_ELEM *Elem = NULL;
4817 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4820 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4821 if(pAd->Mlme.bRunning)
4823 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4828 pAd->Mlme.bRunning = TRUE;
4830 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4832 // Remove all Mlme queues elements
4833 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4835 //From message type, determine which state machine I should drive
4836 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4838 // free MLME element
4839 Elem->Occupied = FALSE;
4844 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4850 // Cancel all timer events
4851 // Be careful to cancel new added timer
4852 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4853 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4854 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4855 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4856 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4857 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4860 // Change back to original channel in case of doing scan
4861 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4862 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4864 // Resume MSDU which is turned off durning scan
4865 RTMPResumeMsduTransmission(pAd);
4868 // Set all state machines back IDLE
4869 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4870 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4871 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4872 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4873 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4874 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4878 // Remove running state
4879 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4880 pAd->Mlme.bRunning = FALSE;
4881 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4885 /*! \brief test if the MLME Queue is empty
4886 * \param *Queue The MLME Queue
4887 * \return TRUE if the Queue is empty, FALSE otherwise
4891 IRQL = DISPATCH_LEVEL
4894 BOOLEAN MlmeQueueEmpty(
4895 IN MLME_QUEUE *Queue)
4899 NdisAcquireSpinLock(&(Queue->Lock));
4900 Ans = (Queue->Num == 0);
4901 NdisReleaseSpinLock(&(Queue->Lock));
4906 /*! \brief test if the MLME Queue is full
4907 * \param *Queue The MLME Queue
4908 * \return TRUE if the Queue is empty, FALSE otherwise
4912 IRQL = PASSIVE_LEVEL
4913 IRQL = DISPATCH_LEVEL
4916 BOOLEAN MlmeQueueFull(
4917 IN MLME_QUEUE *Queue)
4921 NdisAcquireSpinLock(&(Queue->Lock));
4922 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4923 NdisReleaseSpinLock(&(Queue->Lock));
4928 /*! \brief The destructor of MLME Queue
4933 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4935 IRQL = PASSIVE_LEVEL
4938 VOID MlmeQueueDestroy(
4939 IN MLME_QUEUE *pQueue)
4941 NdisAcquireSpinLock(&(pQueue->Lock));
4945 NdisReleaseSpinLock(&(pQueue->Lock));
4946 NdisFreeSpinLock(&(pQueue->Lock));
4949 /*! \brief To substitute the message type if the message is coming from external
4950 * \param pFrame The frame received
4951 * \param *Machine The state machine
4952 * \param *MsgType the message type for the state machine
4953 * \return TRUE if the substitution is successful, FALSE otherwise
4957 IRQL = DISPATCH_LEVEL
4960 BOOLEAN MsgTypeSubst(
4961 IN PRTMP_ADAPTER pAd,
4962 IN PFRAME_802_11 pFrame,
4970 // Pointer to start of data frames including SNAP header
4971 pData = (PUCHAR) pFrame + LENGTH_802_11;
4973 // The only data type will pass to this function is EAPOL frame
4974 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4976 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4978 // Cisco Aironet SNAP header
4979 *Machine = AIRONET_STATE_MACHINE;
4980 *MsgType = MT2_AIRONET_MSG;
4984 *Machine = WPA_PSK_STATE_MACHINE;
4985 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4986 return(WpaMsgTypeSubst(EAPType, MsgType));
4990 switch (pFrame->Hdr.FC.SubType)
4992 case SUBTYPE_ASSOC_REQ:
4993 *Machine = ASSOC_STATE_MACHINE;
4994 *MsgType = MT2_PEER_ASSOC_REQ;
4996 case SUBTYPE_ASSOC_RSP:
4997 *Machine = ASSOC_STATE_MACHINE;
4998 *MsgType = MT2_PEER_ASSOC_RSP;
5000 case SUBTYPE_REASSOC_REQ:
5001 *Machine = ASSOC_STATE_MACHINE;
5002 *MsgType = MT2_PEER_REASSOC_REQ;
5004 case SUBTYPE_REASSOC_RSP:
5005 *Machine = ASSOC_STATE_MACHINE;
5006 *MsgType = MT2_PEER_REASSOC_RSP;
5008 case SUBTYPE_PROBE_REQ:
5009 *Machine = SYNC_STATE_MACHINE;
5010 *MsgType = MT2_PEER_PROBE_REQ;
5012 case SUBTYPE_PROBE_RSP:
5013 *Machine = SYNC_STATE_MACHINE;
5014 *MsgType = MT2_PEER_PROBE_RSP;
5016 case SUBTYPE_BEACON:
5017 *Machine = SYNC_STATE_MACHINE;
5018 *MsgType = MT2_PEER_BEACON;
5021 *Machine = SYNC_STATE_MACHINE;
5022 *MsgType = MT2_PEER_ATIM;
5024 case SUBTYPE_DISASSOC:
5025 *Machine = ASSOC_STATE_MACHINE;
5026 *MsgType = MT2_PEER_DISASSOC_REQ;
5029 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5030 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5031 if (Seq == 1 || Seq == 3)
5033 *Machine = AUTH_RSP_STATE_MACHINE;
5034 *MsgType = MT2_PEER_AUTH_ODD;
5036 else if (Seq == 2 || Seq == 4)
5038 *Machine = AUTH_STATE_MACHINE;
5039 *MsgType = MT2_PEER_AUTH_EVEN;
5046 case SUBTYPE_DEAUTH:
5047 *Machine = AUTH_RSP_STATE_MACHINE;
5048 *MsgType = MT2_PEER_DEAUTH;
5050 case SUBTYPE_ACTION:
5051 *Machine = ACTION_STATE_MACHINE;
5052 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5053 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5055 *MsgType = MT2_ACT_INVALID;
5059 *MsgType = (pFrame->Octet[0]&0x7F);
5070 // ===========================================================================================
5072 // ===========================================================================================
5074 /*! \brief Initialize the state machine.
5075 * \param *S pointer to the state machine
5076 * \param Trans State machine transition function
5077 * \param StNr number of states
5078 * \param MsgNr number of messages
5079 * \param DefFunc default function, when there is invalid state/message combination
5080 * \param InitState initial state of the state machine
5081 * \param Base StateMachine base, internal use only
5082 * \pre p_sm should be a legal pointer
5085 IRQL = PASSIVE_LEVEL
5088 VOID StateMachineInit(
5089 IN STATE_MACHINE *S,
5090 IN STATE_MACHINE_FUNC Trans[],
5093 IN STATE_MACHINE_FUNC DefFunc,
5099 // set number of states and messages
5104 S->TransFunc = Trans;
5106 // init all state transition to default function
5107 for (i = 0; i < StNr; i++)
5109 for (j = 0; j < MsgNr; j++)
5111 S->TransFunc[i * MsgNr + j] = DefFunc;
5115 // set the starting state
5116 S->CurrState = InitState;
5119 /*! \brief This function fills in the function pointer into the cell in the state machine
5120 * \param *S pointer to the state machine
5122 * \param Msg incoming message
5123 * \param f the function to be executed when (state, message) combination occurs at the state machine
5124 * \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
5127 IRQL = PASSIVE_LEVEL
5130 VOID StateMachineSetAction(
5131 IN STATE_MACHINE *S,
5134 IN STATE_MACHINE_FUNC Func)
5138 MsgIdx = Msg - S->Base;
5140 if (St < S->NrState && MsgIdx < S->NrMsg)
5142 // boundary checking before setting the action
5143 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5147 /*! \brief This function does the state transition
5148 * \param *Adapter the NIC adapter pointer
5149 * \param *S the state machine
5150 * \param *Elem the message to be executed
5153 IRQL = DISPATCH_LEVEL
5156 VOID StateMachinePerformAction(
5157 IN PRTMP_ADAPTER pAd,
5158 IN STATE_MACHINE *S,
5159 IN MLME_QUEUE_ELEM *Elem)
5161 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5165 ==========================================================================
5167 The drop function, when machine executes this, the message is simply
5168 ignored. This function does nothing, the message is freed in
5169 StateMachinePerformAction()
5170 ==========================================================================
5173 IN PRTMP_ADAPTER pAd,
5174 IN MLME_QUEUE_ELEM *Elem)
5178 // ===========================================================================================
5180 // ===========================================================================================
5183 ==========================================================================
5186 IRQL = PASSIVE_LEVEL
5188 ==========================================================================
5191 IN PRTMP_ADAPTER pAd,
5195 pAd->Mlme.ShiftReg = 1;
5197 pAd->Mlme.ShiftReg = Seed;
5201 ==========================================================================
5203 ==========================================================================
5206 IN PRTMP_ADAPTER pAd)
5213 if (pAd->Mlme.ShiftReg == 0)
5214 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5216 for (i = 0; i < 8; i++)
5218 if (pAd->Mlme.ShiftReg & 0x00000001)
5220 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5225 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5228 R = (R << 1) | Result;
5234 VOID AsicUpdateAutoFallBackTable(
5235 IN PRTMP_ADAPTER pAd,
5236 IN PUCHAR pRateTable)
5239 HT_FBK_CFG0_STRUC HtCfg0;
5240 HT_FBK_CFG1_STRUC HtCfg1;
5241 LG_FBK_CFG0_STRUC LgCfg0;
5242 LG_FBK_CFG1_STRUC LgCfg1;
5243 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5245 // set to initial value
5246 HtCfg0.word = 0x65432100;
5247 HtCfg1.word = 0xedcba988;
5248 LgCfg0.word = 0xedcba988;
5249 LgCfg1.word = 0x00002100;
5251 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5252 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5254 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5255 switch (pCurrTxRate->Mode)
5261 switch(pCurrTxRate->CurrMCS)
5264 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5267 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5270 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5273 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5276 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5279 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5282 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5285 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5293 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5295 switch(pCurrTxRate->CurrMCS)
5298 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5301 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5304 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5307 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5310 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5313 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5316 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5319 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5322 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5325 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5328 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5331 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5334 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5337 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5340 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5343 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5346 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5353 pNextTxRate = pCurrTxRate;
5356 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5357 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5358 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5359 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5363 ========================================================================
5365 Routine Description:
5366 Set MAC register value according operation mode.
5367 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5368 If MM or GF mask is not set, those passing argument doesn't not take effect.
5370 Operation mode meaning:
5371 = 0 : Pure HT, no preotection.
5372 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5373 = 0x10: No Transmission in 40M is protected.
5374 = 0x11: Transmission in both 40M and 20M shall be protected
5376 we should choose not to use GF. But still set correct ASIC registers.
5377 ========================================================================
5379 VOID AsicUpdateProtect(
5380 IN PRTMP_ADAPTER pAd,
5381 IN USHORT OperationMode,
5383 IN BOOLEAN bDisableBGProtect,
5384 IN BOOLEAN bNonGFExist)
5386 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5392 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5397 if (pAd->BATable.numAsOriginator)
5400 // enable the RTS/CTS to avoid channel collision
5402 SetMask = ALLN_SETPROTECT;
5406 // Config ASIC RTS threshold register
5407 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5408 MacReg &= 0xFF0000FF;
5410 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5412 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5413 (pAd->CommonCfg.bAggregationCapable == TRUE))
5414 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5416 MacReg |= (0x1000 << 8);
5420 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5423 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5425 // Initial common protection settings
5426 RTMPZeroMemory(Protect, sizeof(Protect));
5429 ProtCfg.field.TxopAllowGF40 = 1;
5430 ProtCfg.field.TxopAllowGF20 = 1;
5431 ProtCfg.field.TxopAllowMM40 = 1;
5432 ProtCfg.field.TxopAllowMM20 = 1;
5433 ProtCfg.field.TxopAllowOfdm = 1;
5434 ProtCfg.field.TxopAllowCck = 1;
5435 ProtCfg.field.RTSThEn = 1;
5436 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5438 // update PHY mode and rate
5439 if (pAd->CommonCfg.Channel > 14)
5440 ProtCfg.field.ProtectRate = 0x4000;
5441 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5443 // Handle legacy(B/G) protection
5444 if (bDisableBGProtect)
5446 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5447 ProtCfg.field.ProtectCtrl = 0;
5448 Protect[0] = ProtCfg.word;
5449 Protect[1] = ProtCfg.word;
5453 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5454 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5455 Protect[0] = ProtCfg.word;
5456 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5457 Protect[1] = ProtCfg.word;
5460 // Decide HT frame protection.
5461 if ((SetMask & ALLN_SETPROTECT) != 0)
5463 switch(OperationMode)
5467 // 1.All STAs in the BSS are 20/40 MHz HT
5468 // 2. in ai 20/40MHz BSS
5469 // 3. all STAs are 20MHz in a 20MHz BSS
5470 // Pure HT. no protection.
5474 // PROT_TXOP(25:20) -- 010111
5475 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5476 // PROT_CTRL(17:16) -- 00 (None)
5477 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5478 Protect[2] = 0x01744004;
5482 // PROT_TXOP(25:20) -- 111111
5483 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5484 // PROT_CTRL(17:16) -- 00 (None)
5485 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5486 Protect[3] = 0x03f44084;
5490 // PROT_TXOP(25:20) -- 010111
5491 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5492 // PROT_CTRL(17:16) -- 00 (None)
5493 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5494 Protect[4] = 0x01744004;
5498 // PROT_TXOP(25:20) -- 111111
5499 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5500 // PROT_CTRL(17:16) -- 00 (None)
5501 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5502 Protect[5] = 0x03f44084;
5506 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5507 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5508 Protect[4] = 0x01754004;
5509 Protect[5] = 0x03f54084;
5511 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5515 // This is "HT non-member protection mode."
5516 // If there may be non-HT STAs my BSS
5517 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5518 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5519 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5521 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5522 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5524 //Assign Protection method for 20&40 MHz packets
5525 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5526 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5527 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5528 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5529 Protect[2] = ProtCfg.word;
5530 Protect[3] = ProtCfg4.word;
5531 Protect[4] = ProtCfg.word;
5532 Protect[5] = ProtCfg4.word;
5533 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5537 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5538 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5539 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5541 //Assign Protection method for 40MHz packets
5542 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5543 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5544 Protect[2] = ProtCfg.word;
5545 Protect[3] = ProtCfg4.word;
5548 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5549 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5551 Protect[4] = ProtCfg.word;
5552 Protect[5] = ProtCfg4.word;
5554 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5558 // HT mixed mode. PROTECT ALL!
5560 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5561 ProtCfg4.word = 0x03f44084;
5562 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5563 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5565 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5566 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5568 //Assign Protection method for 20&40 MHz packets
5569 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5570 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5571 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5572 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5573 Protect[2] = ProtCfg.word;
5574 Protect[3] = ProtCfg4.word;
5575 Protect[4] = ProtCfg.word;
5576 Protect[5] = ProtCfg4.word;
5577 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5581 // Special on for Atheros problem n chip.
5582 Protect[2] = 0x01754004;
5583 Protect[3] = 0x03f54084;
5584 Protect[4] = 0x01754004;
5585 Protect[5] = 0x03f54084;
5586 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5591 offset = CCK_PROT_CFG;
5592 for (i = 0;i < 6;i++)
5594 if ((SetMask & (1<< i)))
5596 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5602 // add by johnli, RF power sequence setup
5604 ==========================================================================
5607 Load RF normal operation-mode setup
5609 ==========================================================================
5611 VOID RT30xxLoadRFNormalModeSetup(
5612 IN PRTMP_ADAPTER pAd)
5616 // 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
5617 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5618 RFValue = (RFValue & (~0x0C)) | 0x31;
5619 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5621 // TX_LO2_en, RF R15 register Bit 3 to 0
5622 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5624 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5626 // TX_LO1_en, RF R17 register Bit 3 to 0
5627 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5629 // to fix rx long range issue
5630 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5634 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5636 // RX_LO1_en, RF R20 register Bit 3 to 0
5637 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5639 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5641 // RX_LO2_en, RF R21 register Bit 3 to 0
5642 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5644 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5646 // LDORF_VC, RF R27 register Bit 2 to 0
5647 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5648 if ((pAd->MACVersion & 0xffff) < 0x0211)
5649 RFValue = (RFValue & (~0x77)) | 0x3;
5651 RFValue = (RFValue & (~0x77));
5652 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5657 ==========================================================================
5660 Load RF sleep-mode setup
5662 ==========================================================================
5664 VOID RT30xxLoadRFSleepModeSetup(
5665 IN PRTMP_ADAPTER pAd)
5670 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5671 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5673 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5675 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5676 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5678 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5680 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5681 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5683 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5685 // RX_CTB_en, RF R21 register Bit 7 to 0
5686 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5688 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5690 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5691 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5693 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5695 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5696 MACValue |= 0x1D000000;
5697 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5701 ==========================================================================
5704 Reverse RF sleep-mode setup
5706 ==========================================================================
5708 VOID RT30xxReverseRFSleepModeSetup(
5709 IN PRTMP_ADAPTER pAd)
5714 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5715 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5717 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5719 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5720 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5722 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5724 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5725 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5727 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5729 // RX_CTB_en, RF R21 register Bit 7 to 1
5730 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5732 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5734 // LDORF_VC, RF R27 register Bit 2 to 0
5735 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5736 if ((pAd->MACVersion & 0xffff) < 0x0211)
5737 RFValue = (RFValue & (~0x77)) | 0x3;
5739 RFValue = (RFValue & (~0x77));
5740 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5742 // RT3071 version E has fixed this issue
5743 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5745 // patch tx EVM issue temporarily
5746 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5747 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5748 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5752 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5753 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5754 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5761 ==========================================================================
5764 IRQL = PASSIVE_LEVEL
5765 IRQL = DISPATCH_LEVEL
5767 ==========================================================================
5769 VOID AsicSwitchChannel(
5770 IN PRTMP_ADAPTER pAd,
5774 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5775 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5777 UINT32 Value = 0; //BbpReg, Value;
5778 RTMP_RF_REGS *RFRegTable;
5780 // Search Tx power value
5782 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5783 // in ChannelList, so use TxPower array instead.
5785 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5787 if (Channel == pAd->TxPower[index].Channel)
5789 TxPwer = pAd->TxPower[index].Power;
5790 TxPwer2 = pAd->TxPower[index].Power2;
5796 for (index = 0; index < pAd->ChannelListNum; index++)
5798 if (Channel == pAd->ChannelList[index].Channel)
5800 TxPwer = pAd->ChannelList[index].Power;
5801 TxPwer2 = pAd->ChannelList[index].Power2;
5807 if (index == MAX_NUM_OF_CHANNELS)
5808 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5811 // The RF programming sequence is difference between 3xxx and 2xxx
5813 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5814 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5817 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5820 /* modify by WY for Read RF Reg. error */
5823 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5825 if (Channel == FreqItems3020[index].Channel)
5827 // Programming channel parameters
5828 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5829 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5832 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5833 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5834 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5837 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5838 RFValue = (RFValue & 0xE0) | TxPwer;
5839 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5842 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5843 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5844 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5847 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5848 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5849 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5852 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5853 RFValue = (RFValue & 0xE0) | TxPwer;
5854 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5857 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5858 RFValue = (RFValue & 0xE0) | TxPwer2;
5859 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5861 // Tx/Rx Stream setting
5862 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5863 //if (IS_RT3090(pAd))
5864 // RFValue |= 0x01; // Enable RF block.
5865 RFValue &= 0x03; //clear bit[7~2]
5866 if (pAd->Antenna.field.TxPath == 1)
5868 else if (pAd->Antenna.field.TxPath == 2)
5870 if (pAd->Antenna.field.RxPath == 1)
5872 else if (pAd->Antenna.field.RxPath == 2)
5874 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5877 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5878 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5879 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5883 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5885 RFValue = pAd->Mlme.CaliBW40RfR24;
5886 //DISABLE_11N_CHECK(pAd);
5890 RFValue = pAd->Mlme.CaliBW20RfR24;
5893 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5896 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5897 RFValue = RFValue | 0x1;
5898 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5900 // latch channel for future usage.
5901 pAd->LatchRfRegs.Channel = Channel;
5904 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5905 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5908 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5909 RFValue = RFValue | 0x1;
5910 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5912 // latch channel for future usage.
5913 pAd->LatchRfRegs.Channel = Channel;
5915 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5920 pAd->Antenna.field.TxPath,
5921 FreqItems3020[index].N,
5922 FreqItems3020[index].K,
5923 FreqItems3020[index].R));
5930 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5935 pAd->Antenna.field.TxPath,
5936 FreqItems3020[index].N,
5937 FreqItems3020[index].K,
5938 FreqItems3020[index].R));
5943 RFRegTable = RF2850RegTable;
5945 switch (pAd->RfIcType)
5952 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5954 if (Channel == RFRegTable[index].Channel)
5956 R2 = RFRegTable[index].R2;
5957 if (pAd->Antenna.field.TxPath == 1)
5959 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5962 if (pAd->Antenna.field.RxPath == 2)
5964 R2 |= 0x40; // write 1 to off Rxpath.
5966 else if (pAd->Antenna.field.RxPath == 1)
5968 R2 |= 0x20040; // write 1 to off RxPath
5973 // initialize R3, R4
5974 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5975 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5977 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5979 if ((TxPwer >= -7) && (TxPwer < 0))
5981 TxPwer = (7+TxPwer);
5982 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5983 R3 |= (TxPwer << 10);
5984 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5988 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5989 R3 |= (TxPwer << 10) | (1 << 9);
5993 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5995 TxPwer2 = (7+TxPwer2);
5996 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5997 R4 |= (TxPwer2 << 7);
5998 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
6002 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6003 R4 |= (TxPwer2 << 7) | (1 << 6);
6008 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6009 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6012 // Based on BBP current mode before changing RF channel.
6013 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6019 pAd->LatchRfRegs.Channel = Channel;
6020 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6021 pAd->LatchRfRegs.R2 = R2;
6022 pAd->LatchRfRegs.R3 = R3;
6023 pAd->LatchRfRegs.R4 = R4;
6025 // Set RF value 1's set R3[bit2] = [0]
6026 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6027 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6028 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6029 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6033 // Set RF value 2's set R3[bit2] = [1]
6034 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6035 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6036 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6037 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6041 // Set RF value 3's set R3[bit2] = [0]
6042 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6043 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6044 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6045 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6057 // Change BBP setting during siwtch from a->g, g->a
6060 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6062 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6063 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6064 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6065 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.
6066 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6068 // Rx High power VGA offset for LNA select
6069 if (pAd->NicConfig2.field.ExternalLNAForG)
6071 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6072 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6076 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6077 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6080 // 5G band selection PIN, bit1 and bit2 are complement
6081 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6084 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6086 // Turn off unused PA or LNA when only 1T or 1R
6087 if (pAd->Antenna.field.TxPath == 1)
6089 TxPinCfg &= 0xFFFFFFF3;
6091 if (pAd->Antenna.field.RxPath == 1)
6093 TxPinCfg &= 0xFFFFF3FF;
6096 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6100 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6102 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6103 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6104 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6105 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.
6106 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6108 // Rx High power VGA offset for LNA select
6109 if (pAd->NicConfig2.field.ExternalLNAForA)
6111 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6115 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6118 // 5G band selection PIN, bit1 and bit2 are complement
6119 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6122 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6124 // Turn off unused PA or LNA when only 1T or 1R
6125 if (pAd->Antenna.field.TxPath == 1)
6127 TxPinCfg &= 0xFFFFFFF3;
6129 if (pAd->Antenna.field.RxPath == 1)
6131 TxPinCfg &= 0xFFFFF3FF;
6134 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6137 // R66 should be set according to Channel and use 20MHz when scanning
6138 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6140 RTMPSetAGCInitValue(pAd, BW_20);
6142 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6145 // On 11A, We should delay and wait RF/BBP to be stable
6146 // and the appropriate time should be 1000 micro seconds
6147 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6149 RTMPusecDelay(1000);
6151 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",
6154 (R3 & 0x00003e00) >> 9,
6155 (R4 & 0x000007c0) >> 6,
6156 pAd->Antenna.field.TxPath,
6157 pAd->LatchRfRegs.R1,
6158 pAd->LatchRfRegs.R2,
6159 pAd->LatchRfRegs.R3,
6160 pAd->LatchRfRegs.R4));
6164 ==========================================================================
6166 This function is required for 2421 only, and should not be used during
6167 site survey. It's only required after NIC decided to stay at a channel
6168 for a longer period.
6169 When this function is called, it's always after AsicSwitchChannel().
6171 IRQL = PASSIVE_LEVEL
6172 IRQL = DISPATCH_LEVEL
6174 ==========================================================================
6176 VOID AsicLockChannel(
6177 IN PRTMP_ADAPTER pAd,
6183 ==========================================================================
6186 IRQL = PASSIVE_LEVEL
6187 IRQL = DISPATCH_LEVEL
6189 ==========================================================================
6191 VOID AsicAntennaSelect(
6192 IN PRTMP_ADAPTER pAd,
6196 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6198 // patch for AsicSetRxAnt failed
6199 pAd->RxAnt.EvaluatePeriod = 0;
6201 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6202 // valid indication of the distance between this AP and its clients.
6203 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6207 // if no traffic then reset average rssi to trigger evaluation
6208 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6210 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6211 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6212 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6215 pAd->StaCfg.NumOfAvgRssiSample = 0;
6216 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6218 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6220 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6221 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6223 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6224 AsicEvaluateRxAnt(pAd);
6229 // if not connected, always switch antenna to try to connect
6232 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6233 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6234 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6236 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6238 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6245 ========================================================================
6247 Routine Description:
6248 Antenna miscellaneous setting.
6251 pAd Pointer to our adapter
6252 BandState Indicate current Band State.
6257 IRQL <= DISPATCH_LEVEL
6260 1.) Frame End type control
6261 only valid for G only (RF_2527 & RF_2529)
6262 0: means DPDT, set BBP R4 bit 5 to 1
6263 1: means SPDT, set BBP R4 bit 5 to 0
6266 ========================================================================
6268 VOID AsicAntennaSetting(
6269 IN PRTMP_ADAPTER pAd,
6270 IN ABGBAND_STATE BandState)
6274 VOID AsicRfTuningExec(
6275 IN PVOID SystemSpecific1,
6276 IN PVOID FunctionContext,
6277 IN PVOID SystemSpecific2,
6278 IN PVOID SystemSpecific3)
6283 ==========================================================================
6285 Gives CCK TX rate 2 more dB TX power.
6286 This routine works only in LINK UP in INFRASTRUCTURE mode.
6288 calculate desired Tx power in RF R3.Tx0~5, should consider -
6289 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6290 1. TxPowerPercentage
6291 2. auto calibration based on TSSI feedback
6292 3. extra 2 db for CCK
6293 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6295 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6296 it should be called AFTER MlmeDynamicTxRatSwitching()
6297 ==========================================================================
6299 VOID AsicAdjustTxPower(
6300 IN PRTMP_ADAPTER pAd)
6304 BOOLEAN bAutoTxAgc = FALSE;
6305 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6306 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6307 PCHAR pTxAgcCompensate;
6312 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6313 || (pAd->bPCIclkOff == TRUE)
6314 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6315 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6319 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6321 if (pAd->CommonCfg.CentralChannel > 14)
6323 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6324 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6325 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6326 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6327 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6331 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6332 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6333 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6334 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6335 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6340 if (pAd->CommonCfg.Channel > 14)
6342 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6343 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6344 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6345 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6346 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6350 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6351 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6352 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6353 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6354 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6358 // TX power compensation for temperature variation based on TSSI. try every 4 second
6359 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6361 if (pAd->CommonCfg.Channel <= 14)
6364 bAutoTxAgc = pAd->bAutoTxAgcG;
6365 TssiRef = pAd->TssiRefG;
6366 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6367 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6368 TxAgcStep = pAd->TxAgcStepG;
6369 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6374 bAutoTxAgc = pAd->bAutoTxAgcA;
6375 TssiRef = pAd->TssiRefA;
6376 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6377 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6378 TxAgcStep = pAd->TxAgcStepA;
6379 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6384 /* BbpR1 is unsigned char */
6385 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6387 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6388 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6389 /* step value is defined in pAd->TxAgcStepG for tx power value */
6391 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6392 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6393 above value are examined in mass factory production */
6394 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6396 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6397 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6398 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6400 if (BbpR49 > pTssiMinusBoundary[1])
6402 // Reading is larger than the reference value
6403 // check for how large we need to decrease the Tx power
6404 for (idx = 1; idx < 5; idx++)
6406 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6409 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6410 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6412 DeltaPwr += (*pTxAgcCompensate);
6413 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6414 BbpR49, TssiRef, TxAgcStep, idx-1));
6416 else if (BbpR49 < pTssiPlusBoundary[1])
6418 // Reading is smaller than the reference value
6419 // check for how large we need to increase the Tx power
6420 for (idx = 1; idx < 5; idx++)
6422 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6425 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6426 *pTxAgcCompensate = TxAgcStep * (idx-1);
6427 DeltaPwr += (*pTxAgcCompensate);
6428 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6429 BbpR49, TssiRef, TxAgcStep, idx-1));
6433 *pTxAgcCompensate = 0;
6434 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6435 BbpR49, TssiRef, TxAgcStep, 0));
6441 if (pAd->CommonCfg.Channel <= 14)
6443 bAutoTxAgc = pAd->bAutoTxAgcG;
6444 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6448 bAutoTxAgc = pAd->bAutoTxAgcA;
6449 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6453 DeltaPwr += (*pTxAgcCompensate);
6456 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6459 /* calculate delta power based on the percentage specified from UI */
6460 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6461 // We lower TX power here according to the percentage specified from UI
6462 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6464 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6466 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6470 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6474 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6478 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6483 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6488 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6490 /* reset different new tx power for different TX rate */
6493 if (TxPwr[i] != 0xffffffff)
6497 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6499 if ((Value + DeltaPwr) < 0)
6501 Value = 0; /* min */
6503 else if ((Value + DeltaPwr) > 0xF)
6505 Value = 0xF; /* max */
6509 Value += DeltaPwr; /* temperature compensation */
6512 /* fill new value to CSR offset */
6513 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6516 /* write tx power value to CSR */
6517 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6518 TX power for OFDM 6M/9M
6519 TX power for CCK5.5M/11M
6520 TX power for CCK1M/2M */
6521 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6522 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6529 ==========================================================================
6531 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6532 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6533 the wakeup timer timeout. Driver has to issue a separate command to wake
6536 IRQL = DISPATCH_LEVEL
6538 ==========================================================================
6540 VOID AsicSleepThenAutoWakeup(
6541 IN PRTMP_ADAPTER pAd,
6542 IN USHORT TbttNumToNextWakeUp)
6544 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6548 ==========================================================================
6550 AsicForceWakeup() is used whenever manual wakeup is required
6551 AsicForceSleep() should only be used when not in INFRA BSS. When
6552 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6553 ==========================================================================
6555 VOID AsicForceSleep(
6556 IN PRTMP_ADAPTER pAd)
6562 ==========================================================================
6564 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6567 IRQL = PASSIVE_LEVEL
6568 IRQL = DISPATCH_LEVEL
6569 ==========================================================================
6571 VOID AsicForceWakeup(
6572 IN PRTMP_ADAPTER pAd,
6580 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6582 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6585 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6590 ==========================================================================
6594 IRQL = DISPATCH_LEVEL
6596 ==========================================================================
6599 IN PRTMP_ADAPTER pAd,
6603 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6604 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6606 Addr4 = (ULONG)(pBssid[0]) |
6607 (ULONG)(pBssid[1] << 8) |
6608 (ULONG)(pBssid[2] << 16) |
6609 (ULONG)(pBssid[3] << 24);
6610 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6613 // always one BSSID in STA mode
6614 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6616 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6619 VOID AsicSetMcastWC(
6620 IN PRTMP_ADAPTER pAd)
6622 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6625 pEntry->Sst = SST_ASSOC;
6626 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6627 pEntry->PsMode = PWR_ACTIVE;
6628 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6629 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6633 ==========================================================================
6636 IRQL = DISPATCH_LEVEL
6638 ==========================================================================
6640 VOID AsicDelWcidTab(
6641 IN PRTMP_ADAPTER pAd,
6644 ULONG Addr0 = 0x0, Addr1 = 0x0;
6647 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6648 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6649 RTMP_IO_WRITE32(pAd, offset, Addr0);
6651 RTMP_IO_WRITE32(pAd, offset, Addr1);
6655 ==========================================================================
6658 IRQL = DISPATCH_LEVEL
6660 ==========================================================================
6663 IN PRTMP_ADAPTER pAd)
6665 TX_LINK_CFG_STRUC TxLinkCfg;
6668 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6669 TxLinkCfg.field.TxRDGEn = 1;
6670 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6672 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6675 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6677 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6681 ==========================================================================
6684 IRQL = DISPATCH_LEVEL
6686 ==========================================================================
6688 VOID AsicDisableRDG(
6689 IN PRTMP_ADAPTER pAd)
6691 TX_LINK_CFG_STRUC TxLinkCfg;
6695 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6696 TxLinkCfg.field.TxRDGEn = 0;
6697 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6699 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6702 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6703 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6706 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6707 if (pAd->CommonCfg.bEnableTxBurst)
6710 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6714 ==========================================================================
6717 IRQL = PASSIVE_LEVEL
6718 IRQL = DISPATCH_LEVEL
6720 ==========================================================================
6722 VOID AsicDisableSync(
6723 IN PRTMP_ADAPTER pAd)
6725 BCN_TIME_CFG_STRUC csr;
6727 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6729 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6730 // that NIC will never wakes up because TSF stops and no more
6732 pAd->TbttTickCount = 0;
6733 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6734 csr.field.bBeaconGen = 0;
6735 csr.field.bTBTTEnable = 0;
6736 csr.field.TsfSyncMode = 0;
6737 csr.field.bTsfTicking = 0;
6738 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6743 ==========================================================================
6746 IRQL = DISPATCH_LEVEL
6748 ==========================================================================
6750 VOID AsicEnableBssSync(
6751 IN PRTMP_ADAPTER pAd)
6753 BCN_TIME_CFG_STRUC csr;
6755 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6757 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6760 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6761 csr.field.bTsfTicking = 1;
6762 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6763 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6764 csr.field.bTBTTEnable = 1;
6767 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6771 ==========================================================================
6774 BEACON frame in shared memory should be built ok before this routine
6775 can be called. Otherwise, a garbage frame maybe transmitted out every
6778 IRQL = DISPATCH_LEVEL
6780 ==========================================================================
6782 VOID AsicEnableIbssSync(
6783 IN PRTMP_ADAPTER pAd)
6785 BCN_TIME_CFG_STRUC csr9;
6789 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6791 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6792 csr9.field.bBeaconGen = 0;
6793 csr9.field.bTBTTEnable = 0;
6794 csr9.field.bTsfTicking = 0;
6795 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6798 // move BEACON TXD and frame content to on-chip memory
6799 ptr = (PUCHAR)&pAd->BeaconTxWI;
6800 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6802 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6803 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6807 // start right after the 16-byte TXWI field
6808 ptr = pAd->BeaconBuf;
6809 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6811 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6812 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6817 // move BEACON TXD and frame content to on-chip memory
6818 ptr = (PUCHAR)&pAd->BeaconTxWI;
6819 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6821 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6825 // start right after the 16-byte TXWI field
6826 ptr = pAd->BeaconBuf;
6827 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6829 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6834 // start sending BEACON
6835 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6836 csr9.field.bTsfTicking = 1;
6837 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6838 csr9.field.bTBTTEnable = 1;
6839 csr9.field.bBeaconGen = 1;
6840 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6844 ==========================================================================
6847 IRQL = PASSIVE_LEVEL
6848 IRQL = DISPATCH_LEVEL
6850 ==========================================================================
6852 VOID AsicSetEdcaParm(
6853 IN PRTMP_ADAPTER pAd,
6854 IN PEDCA_PARM pEdcaParm)
6856 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6857 AC_TXOP_CSR0_STRUC csr0;
6858 AC_TXOP_CSR1_STRUC csr1;
6859 AIFSN_CSR_STRUC AifsnCsr;
6860 CWMIN_CSR_STRUC CwminCsr;
6861 CWMAX_CSR_STRUC CwmaxCsr;
6868 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6870 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6871 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6872 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6874 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6875 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6878 //========================================================
6879 // MAC Register has a copy .
6880 //========================================================
6881 if( pAd->CommonCfg.bEnableTxBurst )
6883 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6884 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6887 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6888 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6889 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6890 Ac0Cfg.field.Aifsn = 2;
6891 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6893 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6894 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6895 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6896 Ac1Cfg.field.Aifsn = 2;
6897 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6899 if (pAd->CommonCfg.PhyMode == PHY_11B)
6901 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6902 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6906 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6907 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6909 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6910 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6911 Ac2Cfg.field.Aifsn = 2;
6912 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6913 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6914 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6915 Ac3Cfg.field.Aifsn = 2;
6916 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6918 //========================================================
6919 // DMA Register has a copy too.
6920 //========================================================
6921 csr0.field.Ac0Txop = 0; // QID_AC_BE
6922 csr0.field.Ac1Txop = 0; // QID_AC_BK
6923 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6924 if (pAd->CommonCfg.PhyMode == PHY_11B)
6926 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6927 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6931 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6932 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6934 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6937 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6938 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6939 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6940 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6941 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6944 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6945 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6946 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6947 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6948 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6950 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6952 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6956 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6957 //========================================================
6958 // MAC Register has a copy.
6959 //========================================================
6961 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6962 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6964 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6966 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6967 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6968 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6969 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6971 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6972 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6973 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6974 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6976 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6977 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6978 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6979 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6982 // Tuning for Wi-Fi WMM S06
6983 if (pAd->CommonCfg.bWiFiTest &&
6984 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6985 Ac2Cfg.field.Aifsn -= 1;
6987 // Tuning for TGn Wi-Fi 5.2.32
6988 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6989 if (STA_TGN_WIFI_ON(pAd) &&
6990 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6992 Ac0Cfg.field.Aifsn = 3;
6993 Ac2Cfg.field.AcTxop = 5;
6997 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6999 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
7000 Ac2Cfg.field.Aifsn = 5;
7005 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7006 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7007 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7008 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7011 if (pAd->CommonCfg.bWiFiTest)
7013 if (Ac3Cfg.field.AcTxop == 102)
7015 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7016 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7017 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7018 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7019 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7022 //#endif // WIFI_TEST //
7024 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7025 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7026 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7027 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7030 //========================================================
7031 // DMA Register has a copy too.
7032 //========================================================
7033 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7034 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7035 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7037 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7038 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7039 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7042 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7043 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7044 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7046 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7048 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7051 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7052 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7053 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7054 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7055 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7058 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7059 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7060 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7063 // Tuning for Wi-Fi WMM S06
7064 if (pAd->CommonCfg.bWiFiTest &&
7065 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7066 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7068 // Tuning for TGn Wi-Fi 5.2.32
7069 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7070 if (STA_TGN_WIFI_ON(pAd) &&
7071 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7073 AifsnCsr.field.Aifsn0 = 3;
7074 AifsnCsr.field.Aifsn2 = 7;
7078 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7082 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7084 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7085 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7088 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7090 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7093 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7094 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7095 pEdcaParm->Aifsn[0],
7096 pEdcaParm->Cwmin[0],
7097 pEdcaParm->Cwmax[0],
7098 pEdcaParm->Txop[0]<<5,
7099 pEdcaParm->bACM[0]));
7100 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7101 pEdcaParm->Aifsn[1],
7102 pEdcaParm->Cwmin[1],
7103 pEdcaParm->Cwmax[1],
7104 pEdcaParm->Txop[1]<<5,
7105 pEdcaParm->bACM[1]));
7106 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7107 pEdcaParm->Aifsn[2],
7108 pEdcaParm->Cwmin[2],
7109 pEdcaParm->Cwmax[2],
7110 pEdcaParm->Txop[2]<<5,
7111 pEdcaParm->bACM[2]));
7112 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7113 pEdcaParm->Aifsn[3],
7114 pEdcaParm->Cwmin[3],
7115 pEdcaParm->Cwmax[3],
7116 pEdcaParm->Txop[3]<<5,
7117 pEdcaParm->bACM[3]));
7123 ==========================================================================
7126 IRQL = PASSIVE_LEVEL
7127 IRQL = DISPATCH_LEVEL
7129 ==========================================================================
7131 VOID AsicSetSlotTime(
7132 IN PRTMP_ADAPTER pAd,
7133 IN BOOLEAN bUseShortSlotTime)
7136 UINT32 RegValue = 0;
7138 if (pAd->CommonCfg.Channel > 14)
7139 bUseShortSlotTime = TRUE;
7141 if (bUseShortSlotTime)
7142 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7144 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7146 SlotTime = (bUseShortSlotTime)? 9 : 20;
7150 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7151 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7152 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7155 // In this case, we will think it is doing Wi-Fi test
7156 // And we will not set to short slot when bEnableTxBurst is TRUE.
7158 else if (pAd->CommonCfg.bEnableTxBurst)
7161 if (pAd->CommonCfg.bEnableTxBurst)
7167 // For some reasons, always set it to short slot time.
7169 // ToDo: Should consider capability with 11B
7171 if (pAd->StaCfg.BssType == BSS_ADHOC)
7174 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7175 RegValue = RegValue & 0xFFFFFF00;
7177 RegValue |= SlotTime;
7179 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7183 ========================================================================
7185 Add Shared key information into ASIC.
7186 Update shared key, TxMic and RxMic to Asic Shared key table
7187 Update its cipherAlg to Asic Shared key Mode.
7190 ========================================================================
7192 VOID AsicAddSharedKeyEntry(
7193 IN PRTMP_ADAPTER pAd,
7201 ULONG offset; //, csr0;
7202 SHAREDKEY_MODE_STRUC csr1;
7207 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7208 //============================================================================================
7210 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7211 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7212 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]));
7215 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7216 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7220 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7221 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7223 //============================================================================================
7225 // fill key material - key + TX MIC + RX MIC
7228 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7230 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7232 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7236 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7238 offset += MAX_LEN_OF_SHARE_KEY;
7244 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7248 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7258 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7262 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7268 // Update cipher algorithm. WSTA always use BSS0
7270 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7271 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7272 if ((BssIndex%2) == 0)
7275 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7276 else if (KeyIdx == 1)
7277 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7278 else if (KeyIdx == 2)
7279 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7281 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7286 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7287 else if (KeyIdx == 1)
7288 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7289 else if (KeyIdx == 2)
7290 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7292 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7294 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7295 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7299 // IRQL = DISPATCH_LEVEL
7300 VOID AsicRemoveSharedKeyEntry(
7301 IN PRTMP_ADAPTER pAd,
7306 SHAREDKEY_MODE_STRUC csr1;
7308 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7310 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7311 if ((BssIndex%2) == 0)
7314 csr1.field.Bss0Key0CipherAlg = 0;
7315 else if (KeyIdx == 1)
7316 csr1.field.Bss0Key1CipherAlg = 0;
7317 else if (KeyIdx == 2)
7318 csr1.field.Bss0Key2CipherAlg = 0;
7320 csr1.field.Bss0Key3CipherAlg = 0;
7325 csr1.field.Bss1Key0CipherAlg = 0;
7326 else if (KeyIdx == 1)
7327 csr1.field.Bss1Key1CipherAlg = 0;
7328 else if (KeyIdx == 2)
7329 csr1.field.Bss1Key2CipherAlg = 0;
7331 csr1.field.Bss1Key3CipherAlg = 0;
7333 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7334 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7335 ASSERT(BssIndex < 4);
7341 VOID AsicUpdateWCIDAttribute(
7342 IN PRTMP_ADAPTER pAd,
7346 IN BOOLEAN bUsePairewiseKeyTable)
7348 ULONG WCIDAttri = 0, offset;
7351 // Update WCID attribute.
7352 // Only TxKey could update WCID attribute.
7354 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7355 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7356 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7359 VOID AsicUpdateWCIDIVEIV(
7360 IN PRTMP_ADAPTER pAd,
7367 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7369 RTMP_IO_WRITE32(pAd, offset, uIV);
7370 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7373 VOID AsicUpdateRxWCIDTable(
7374 IN PRTMP_ADAPTER pAd,
7381 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7382 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7383 RTMP_IO_WRITE32(pAd, offset, Addr);
7384 Addr = pAddr[4] + (pAddr[5] << 8);
7385 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7390 ========================================================================
7392 Routine Description:
7393 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7396 pAd Pointer to our adapter
7397 WCID WCID Entry number.
7398 BssIndex BSSID index, station or none multiple BSSID support
7399 this value should be 0.
7400 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7401 pCipherKey Pointer to Cipher Key.
7402 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7403 otherwise PairewiseKey table
7404 bTxKey This is the transmit key if enabled.
7410 This routine will set the relative key stuff to Asic including WCID attribute,
7411 Cipher Key, Cipher algorithm and IV/EIV.
7413 IV/EIV will be update if this CipherKey is the transmission key because
7414 ASIC will base on IV's KeyID value to select Cipher Key.
7416 If bTxKey sets to FALSE, this is not the TX key, but it could be
7419 For AP mode bTxKey must be always set to TRUE.
7420 ========================================================================
7422 VOID AsicAddKeyEntry(
7423 IN PRTMP_ADAPTER pAd,
7427 IN PCIPHER_KEY pCipherKey,
7428 IN BOOLEAN bUsePairewiseKeyTable,
7433 PUCHAR pKey = pCipherKey->Key;
7434 PUCHAR pTxMic = pCipherKey->TxMic;
7435 PUCHAR pRxMic = pCipherKey->RxMic;
7436 PUCHAR pTxtsc = pCipherKey->TxTsc;
7437 UCHAR CipherAlg = pCipherKey->CipherAlg;
7438 SHAREDKEY_MODE_STRUC csr1;
7443 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7445 // 1.) decide key table offset
7447 if (bUsePairewiseKeyTable)
7448 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7450 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7453 // 2.) Set Key to Asic
7455 //for (i = 0; i < KeyLen; i++)
7457 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7459 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7463 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7465 offset += MAX_LEN_OF_PEER_KEY;
7468 // 3.) Set MIC key if available
7473 for (i = 0; i < 8; i++)
7475 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7479 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7482 offset += LEN_TKIP_TXMICK;
7487 for (i = 0; i < 8; i++)
7489 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7493 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7499 // 4.) Modify IV/EIV if needs
7500 // This will force Asic to use this key ID by setting IV.
7505 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7509 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7510 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7511 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7513 IV4 = (KeyIdx << 6);
7514 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7515 IV4 |= 0x20; // turn on extension bit means EIV existence
7517 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7523 for (i = 0; i < 4; i++)
7525 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7535 IV4 = (KeyIdx << 6);
7536 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7537 IV4 |= 0x20; // turn on extension bit means EIV existence
7539 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7540 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7546 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7548 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7551 if (!bUsePairewiseKeyTable)
7554 // Only update the shared key security mode
7556 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7557 if ((BssIndex % 2) == 0)
7560 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7561 else if (KeyIdx == 1)
7562 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7563 else if (KeyIdx == 2)
7564 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7566 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7571 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7572 else if (KeyIdx == 1)
7573 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7574 else if (KeyIdx == 2)
7575 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7577 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7579 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7582 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7587 ========================================================================
7589 Add Pair-wise key material into ASIC.
7590 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7593 ========================================================================
7595 VOID AsicAddPairwiseKeyEntry(
7596 IN PRTMP_ADAPTER pAd,
7599 IN CIPHER_KEY *pCipherKey)
7603 PUCHAR pKey = pCipherKey->Key;
7604 PUCHAR pTxMic = pCipherKey->TxMic;
7605 PUCHAR pRxMic = pCipherKey->RxMic;
7607 UCHAR CipherAlg = pCipherKey->CipherAlg;
7611 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7613 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7615 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7619 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7621 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7624 RTMP_IO_READ32(pAd, offset + i, &Value);
7627 offset += MAX_LEN_OF_PEER_KEY;
7635 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7639 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7648 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7652 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7656 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7657 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7658 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]));
7661 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7662 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7666 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7667 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7671 ========================================================================
7673 Remove Pair-wise key material from ASIC.
7676 ========================================================================
7678 VOID AsicRemovePairwiseKeyEntry(
7679 IN PRTMP_ADAPTER pAd,
7686 // re-set the entry's WCID attribute as OPEN-NONE.
7687 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7688 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7689 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7692 BOOLEAN AsicSendCommandToMcu(
7693 IN PRTMP_ADAPTER pAd,
7699 HOST_CMD_CSR_STRUC H2MCmd;
7700 H2M_MAILBOX_STRUC H2MMailbox;
7705 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7706 if (H2MMailbox.field.Owner == 0)
7719 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7721 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7723 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7724 // Reset DMA/CPU ring index
7725 RTMPRingCleanUp(pAd, QID_AC_BK);
7726 RTMPRingCleanUp(pAd, QID_AC_BE);
7727 RTMPRingCleanUp(pAd, QID_AC_VI);
7728 RTMPRingCleanUp(pAd, QID_AC_VO);
7729 RTMPRingCleanUp(pAd, QID_HCCA);
7730 RTMPRingCleanUp(pAd, QID_MGMT);
7731 RTMPRingCleanUp(pAd, QID_RX);
7734 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7736 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7738 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7746 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7747 H2MMailbox.field.CmdToken = Token;
7748 H2MMailbox.field.HighByte = Arg1;
7749 H2MMailbox.field.LowByte = Arg0;
7750 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7753 H2MCmd.field.HostCommand = Command;
7754 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7756 if (Command != 0x80)
7764 BOOLEAN AsicCheckCommanOk(
7765 IN PRTMP_ADAPTER pAd,
7768 UINT32 CmdStatus = 0, CID = 0, i;
7769 UINT32 ThisCIDMask = 0;
7774 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7775 // Find where the command is. Because this is randomly specified by firmware.
7776 if ((CID & CID0MASK) == Command)
7778 ThisCIDMask = CID0MASK;
7781 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7783 ThisCIDMask = CID1MASK;
7786 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7788 ThisCIDMask = CID2MASK;
7791 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7793 ThisCIDMask = CID3MASK;
7801 // Get CommandStatus Value
7802 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7804 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7807 // If Status is 1, the comamnd is success.
7808 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7809 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7811 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7812 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7813 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7816 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7820 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7822 // Clear Command and Status.
7823 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7824 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7831 ========================================================================
7833 Routine Description:
7834 Verify the support rate for different PHY type
7837 pAd Pointer to our adapter
7842 IRQL = PASSIVE_LEVEL
7844 ========================================================================
7846 VOID RTMPCheckRates(
7847 IN PRTMP_ADAPTER pAd,
7848 IN OUT UCHAR SupRate[],
7849 IN OUT UCHAR *SupRateLen)
7851 UCHAR RateIdx, i, j;
7852 UCHAR NewRate[12], NewRateLen;
7856 if (pAd->CommonCfg.PhyMode == PHY_11B)
7861 // Check for support rates exclude basic rate bit
7862 for (i = 0; i < *SupRateLen; i++)
7863 for (j = 0; j < RateIdx; j++)
7864 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7865 NewRate[NewRateLen++] = SupRate[i];
7867 *SupRateLen = NewRateLen;
7868 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7871 BOOLEAN RTMPCheckChannel(
7872 IN PRTMP_ADAPTER pAd,
7873 IN UCHAR CentralChannel,
7877 UCHAR UpperChannel = 0, LowerChannel = 0;
7878 UCHAR NoEffectChannelinList = 0;
7880 // Find upper and lower channel according to 40MHz current operation.
7881 if (CentralChannel < Channel)
7883 UpperChannel = Channel;
7884 if (CentralChannel > 2)
7885 LowerChannel = CentralChannel - 2;
7889 else if (CentralChannel > Channel)
7891 UpperChannel = CentralChannel + 2;
7892 LowerChannel = Channel;
7895 for (k = 0;k < pAd->ChannelListNum;k++)
7897 if (pAd->ChannelList[k].Channel == UpperChannel)
7899 NoEffectChannelinList ++;
7901 if (pAd->ChannelList[k].Channel == LowerChannel)
7903 NoEffectChannelinList ++;
7907 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7908 if (NoEffectChannelinList == 2)
7915 ========================================================================
7917 Routine Description:
7918 Verify the support rate for HT phy type
7921 pAd Pointer to our adapter
7924 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7926 IRQL = PASSIVE_LEVEL
7928 ========================================================================
7930 BOOLEAN RTMPCheckHt(
7931 IN PRTMP_ADAPTER pAd,
7933 IN HT_CAPABILITY_IE *pHtCapability,
7934 IN ADD_HT_INFO_IE *pAddHtInfo)
7936 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7939 // If use AMSDU, set flag.
7940 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7941 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7942 // Save Peer Capability
7943 if (pHtCapability->HtCapInfo.ShortGIfor20)
7944 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7945 if (pHtCapability->HtCapInfo.ShortGIfor40)
7946 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7947 if (pHtCapability->HtCapInfo.TxSTBC)
7948 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7949 if (pHtCapability->HtCapInfo.RxSTBC)
7950 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7951 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7953 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7956 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7958 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7961 // Will check ChannelWidth for MCSSet[4] below
7962 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7963 switch (pAd->CommonCfg.RxStream)
7966 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7967 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7968 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7969 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7972 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7973 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7974 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7975 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7978 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7979 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7980 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7981 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7985 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7987 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7988 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7989 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7991 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7993 // Send Assoc Req with my HT capability.
7994 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7995 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7996 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7997 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7998 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7999 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
8000 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
8001 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
8002 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8003 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8004 if (pAd->CommonCfg.bRdg)
8006 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8007 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8010 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8011 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8013 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8018 ========================================================================
8020 Routine Description:
8021 Verify the support rate for different PHY type
8024 pAd Pointer to our adapter
8029 IRQL = PASSIVE_LEVEL
8031 ========================================================================
8033 VOID RTMPUpdateMlmeRate(
8034 IN PRTMP_ADAPTER pAd)
8037 UCHAR ProperMlmeRate; //= RATE_54;
8038 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8039 BOOLEAN bMatch = FALSE;
8041 switch (pAd->CommonCfg.PhyMode)
8044 ProperMlmeRate = RATE_11;
8045 MinimumRate = RATE_1;
8047 case PHY_11BG_MIXED:
8048 case PHY_11ABGN_MIXED:
8049 case PHY_11BGN_MIXED:
8050 if ((pAd->MlmeAux.SupRateLen == 4) &&
8051 (pAd->MlmeAux.ExtRateLen == 0))
8053 ProperMlmeRate = RATE_11;
8055 ProperMlmeRate = RATE_24;
8057 if (pAd->MlmeAux.Channel <= 14)
8058 MinimumRate = RATE_1;
8060 MinimumRate = RATE_6;
8063 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8064 case PHY_11GN_MIXED:
8065 case PHY_11AGN_MIXED:
8066 case PHY_11AN_MIXED:
8068 ProperMlmeRate = RATE_24;
8069 MinimumRate = RATE_6;
8071 case PHY_11ABG_MIXED:
8072 ProperMlmeRate = RATE_24;
8073 if (pAd->MlmeAux.Channel <= 14)
8074 MinimumRate = RATE_1;
8076 MinimumRate = RATE_6;
8079 ProperMlmeRate = RATE_1;
8080 MinimumRate = RATE_1;
8084 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8086 for (j = 0; j < RateIdx; j++)
8088 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8090 if (j == ProperMlmeRate)
8102 if (bMatch == FALSE)
8104 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8106 for (j = 0; j < RateIdx; j++)
8108 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8110 if (j == ProperMlmeRate)
8123 if (bMatch == FALSE)
8125 ProperMlmeRate = MinimumRate;
8128 pAd->CommonCfg.MlmeRate = MinimumRate;
8129 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8130 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8132 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8133 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8134 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8135 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8139 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8140 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8141 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8142 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8145 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8149 IN PRTMP_ADAPTER pAd,
8156 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8161 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8163 larger = max(Rssi0, Rssi1);
8166 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8168 larger = max(larger, Rssi2);
8178 // Antenna divesity use GPIO3 and EESK pin for control
8179 // Antenna and EEPROM access are both using EESK pin,
8180 // Therefor we should avoid accessing EESK at the same time
8181 // Then restore antenna after EEPROM access
8183 IN PRTMP_ADAPTER pAd,
8189 if ((pAd->EepromAccess) ||
8190 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8191 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8192 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8193 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8198 // the antenna selection is through firmware and MAC register(GPIO3)
8202 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8204 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8206 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8208 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8209 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8214 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8216 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8218 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8221 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8222 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8228 ========================================================================
8229 Routine Description:
8230 Periodic evaluate antenna link status
8233 pAd - Adapter pointer
8238 ========================================================================
8240 VOID AsicEvaluateRxAnt(
8241 IN PRTMP_ADAPTER pAd)
8245 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8246 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8247 fRTMP_ADAPTER_RADIO_OFF |
8248 fRTMP_ADAPTER_NIC_NOT_EXIST |
8249 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
8251 || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8252 || (pAd->EepromAccess)
8258 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8259 // one is antenna diversity:there is only one antenna can rx and tx
8260 // the other is failed antenna remove:two physical antenna can rx and tx
8261 if (pAd->NicConfig2.field.AntDiversity)
8263 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8264 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8266 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8268 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8269 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8270 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8272 // a one-shot timer to end the evalution
8273 // dynamic adjust antenna evaluation period according to the traffic
8274 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8275 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8277 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8282 if (pAd->StaCfg.Psm == PWR_SAVE)
8285 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8287 if(pAd->Antenna.field.RxPath == 3)
8291 else if(pAd->Antenna.field.RxPath == 2)
8295 else if(pAd->Antenna.field.RxPath == 1)
8299 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8302 pAd->StaCfg.BBPR3 = BBPR3;
8306 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8309 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8310 pAd->RalinkCounters.OneSecTxRetryOkCount +
8311 pAd->RalinkCounters.OneSecTxFailCount;
8313 // dynamic adjust antenna evaluation period according to the traffic
8314 if (TxTotalCnt > 50)
8316 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8317 pAd->Mlme.bLowThroughput = FALSE;
8321 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8322 pAd->Mlme.bLowThroughput = TRUE;
8328 ========================================================================
8329 Routine Description:
8330 After evaluation, check antenna link status
8333 pAd - Adapter pointer
8338 ========================================================================
8340 VOID AsicRxAntEvalTimeout(
8341 IN PVOID SystemSpecific1,
8342 IN PVOID FunctionContext,
8343 IN PVOID SystemSpecific2,
8344 IN PVOID SystemSpecific3)
8346 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8348 CHAR larger = -127, rssi0, rssi1, rssi2;
8352 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8353 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8354 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8355 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8358 if (pAd->StaCfg.Psm == PWR_SAVE)
8362 // if the traffic is low, use average rssi as the criteria
8363 if (pAd->Mlme.bLowThroughput == TRUE)
8365 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8366 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8367 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8371 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8372 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8373 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8376 if(pAd->Antenna.field.RxPath == 3)
8378 larger = max(rssi0, rssi1);
8380 if (larger > (rssi2 + 20))
8381 pAd->Mlme.RealRxPath = 2;
8383 pAd->Mlme.RealRxPath = 3;
8385 else if(pAd->Antenna.field.RxPath == 2)
8387 if (rssi0 > (rssi1 + 20))
8388 pAd->Mlme.RealRxPath = 1;
8390 pAd->Mlme.RealRxPath = 2;
8393 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8395 if(pAd->Mlme.RealRxPath == 3)
8399 else if(pAd->Mlme.RealRxPath == 2)
8403 else if(pAd->Mlme.RealRxPath == 1)
8407 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8409 pAd->StaCfg.BBPR3 = BBPR3;
8414 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8415 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8416 fRTMP_ADAPTER_RADIO_OFF |
8417 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8418 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8420 || (pAd->EepromAccess)
8426 //if (pAd->StaCfg.Psm == PWR_SAVE)
8429 if (pAd->NicConfig2.field.AntDiversity)
8431 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8436 // select PrimaryRxAntPair
8437 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8438 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8440 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8441 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8442 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8444 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8445 pAd->RxAnt.EvaluateStableCnt = 0;
8449 // if the evaluated antenna is not better than original, switch back to original antenna
8450 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8451 pAd->RxAnt.EvaluateStableCnt ++;
8454 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8456 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8457 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8461 if (pAd->StaCfg.Psm == PWR_SAVE)
8464 // if the traffic is low, use average rssi as the criteria
8465 if (pAd->Mlme.bLowThroughput == TRUE)
8467 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8468 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8469 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8473 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8474 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8475 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8478 if(pAd->Antenna.field.RxPath == 3)
8480 larger = max(rssi0, rssi1);
8482 if (larger > (rssi2 + 20))
8483 pAd->Mlme.RealRxPath = 2;
8485 pAd->Mlme.RealRxPath = 3;
8487 else if(pAd->Antenna.field.RxPath == 2)
8489 if (rssi0 > (rssi1 + 20))
8490 pAd->Mlme.RealRxPath = 1;
8492 pAd->Mlme.RealRxPath = 2;
8495 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8497 if(pAd->Mlme.RealRxPath == 3)
8501 else if(pAd->Mlme.RealRxPath == 2)
8505 else if(pAd->Mlme.RealRxPath == 1)
8509 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8517 VOID APSDPeriodicExec(
8518 IN PVOID SystemSpecific1,
8519 IN PVOID FunctionContext,
8520 IN PVOID SystemSpecific2,
8521 IN PVOID SystemSpecific3)
8523 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8525 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8528 pAd->CommonCfg.TriggerTimerCount++;
8533 ========================================================================
8534 Routine Description:
8535 Set/reset MAC registers according to bPiggyBack parameter
8538 pAd - Adapter pointer
8539 bPiggyBack - Enable / Disable Piggy-Back
8544 ========================================================================
8546 VOID RTMPSetPiggyBack(
8547 IN PRTMP_ADAPTER pAd,
8548 IN BOOLEAN bPiggyBack)
8550 TX_LINK_CFG_STRUC TxLinkCfg;
8552 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8554 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8555 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8559 ========================================================================
8560 Routine Description:
8561 check if this entry need to switch rate automatically
8571 ========================================================================
8573 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8574 IN PRTMP_ADAPTER pAd,
8575 IN PMAC_TABLE_ENTRY pEntry)
8577 BOOLEAN result = TRUE;
8580 // only associated STA counts
8581 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8583 result = pAd->StaCfg.bAutoTxRateSwitch;
8593 BOOLEAN RTMPAutoRateSwitchCheck(
8594 IN PRTMP_ADAPTER pAd)
8596 if (pAd->StaCfg.bAutoTxRateSwitch)
8604 ========================================================================
8605 Routine Description:
8606 check if this entry need to fix tx legacy rate
8616 ========================================================================
8618 UCHAR RTMPStaFixedTxMode(
8619 IN PRTMP_ADAPTER pAd,
8620 IN PMAC_TABLE_ENTRY pEntry)
8622 UCHAR tx_mode = FIXED_TXMODE_HT;
8624 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8630 ========================================================================
8631 Routine Description:
8632 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8642 ========================================================================
8644 VOID RTMPUpdateLegacyTxSetting(
8645 UCHAR fixed_tx_mode,
8646 PMAC_TABLE_ENTRY pEntry)
8648 HTTRANSMIT_SETTING TransmitSetting;
8650 if (fixed_tx_mode == FIXED_TXMODE_HT)
8653 TransmitSetting.word = 0;
8655 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8656 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8658 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8660 TransmitSetting.field.MODE = MODE_CCK;
8661 // CCK mode allow MCS 0~3
8662 if (TransmitSetting.field.MCS > MCS_3)
8663 TransmitSetting.field.MCS = MCS_3;
8667 TransmitSetting.field.MODE = MODE_OFDM;
8668 // OFDM mode allow MCS 0~7
8669 if (TransmitSetting.field.MCS > MCS_7)
8670 TransmitSetting.field.MCS = MCS_7;
8673 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8675 pEntry->HTPhyMode.word = TransmitSetting.word;
8676 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8677 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8682 ==========================================================================
8684 dynamic tune BBP R66 to find a balance between sensibility and
8687 IRQL = DISPATCH_LEVEL
8689 ==========================================================================
8691 VOID AsicStaBbpTuning(
8692 IN PRTMP_ADAPTER pAd)
8694 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8697 // 2860C did not support Fase CCA, therefore can't tune
8698 if (pAd->MACVersion == 0x28600100)
8704 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8707 if ((pAd->OpMode == OPMODE_STA)
8708 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8710 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8712 && (pAd->bPCIclkOff == FALSE))
8718 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8721 if (pAd->Antenna.field.RxPath > 1)
8722 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8724 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8726 if (pAd->LatchRfRegs.Channel <= 14)
8729 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8730 // Otherwise, it will have some throughput side effect when low RSSI
8738 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8740 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8741 if (OrigR66Value != R66)
8742 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8746 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8747 if (OrigR66Value != R66)
8748 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8754 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8756 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8757 if (OrigR66Value != R66)
8759 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8764 R66 = 0x2E + GET_LNA_GAIN(pAd);
8765 if (OrigR66Value != R66)
8767 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8774 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8776 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8778 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8779 if (OrigR66Value != R66)
8781 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8786 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8787 if (OrigR66Value != R66)
8789 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8795 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8797 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8798 if (OrigR66Value != R66)
8800 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8805 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8806 if (OrigR66Value != R66)
8808 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8819 VOID AsicResetFromDMABusy(
8820 IN PRTMP_ADAPTER pAd)
8823 BOOLEAN bCtrl = FALSE;
8825 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8827 // Be sure restore link control value so we can write register.
8828 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8829 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8831 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8832 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8833 RTMPusecDelay(6000);
8834 pAd->bPCIclkOff = FALSE;
8838 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8840 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8842 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8843 // Reset DMA/CPU ring index
8844 RTMPRingCleanUp(pAd, QID_AC_BK);
8845 RTMPRingCleanUp(pAd, QID_AC_BE);
8846 RTMPRingCleanUp(pAd, QID_AC_VI);
8847 RTMPRingCleanUp(pAd, QID_AC_VO);
8848 RTMPRingCleanUp(pAd, QID_HCCA);
8849 RTMPRingCleanUp(pAd, QID_MGMT);
8850 RTMPRingCleanUp(pAd, QID_RX);
8853 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8855 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8857 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8858 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8859 RTMPPCIeLinkCtrlSetting(pAd, 3);
8861 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8862 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8863 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8867 IN PRTMP_ADAPTER pAd)
8869 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8871 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8872 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8873 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8875 // After hard-reset BBP, initialize all BBP values.
8876 NICRestoreBBPValue(pAd);
8877 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8881 IN PRTMP_ADAPTER pAd)
8885 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8886 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8888 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8890 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8892 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8896 IN PRTMP_ADAPTER pAd)
8898 ULONG Value1, Value2;
8901 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8902 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8905 // sum should be equals to 0xff, which is the total buffer size.
8906 if ((Value1 + Value2) < 0xff)
8908 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8909 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8911 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8913 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8915 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8920 VOID RTMPSetAGCInitValue(
8921 IN PRTMP_ADAPTER pAd,
8926 if (pAd->LatchRfRegs.Channel <= 14)
8928 R66 = 0x2E + GET_LNA_GAIN(pAd);
8929 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8933 if (BandWidth == BW_20)
8935 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8936 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8940 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8941 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8947 VOID AsicTurnOffRFClk(
8948 IN PRTMP_ADAPTER pAd,
8953 UINT32 R1 = 0, R2 = 0, R3 = 0;
8955 RTMP_RF_REGS *RFRegTable;
8957 // The RF programming sequence is difference between 3xxx and 2xxx
8960 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8964 RFRegTable = RF2850RegTable;
8966 switch (pAd->RfIcType)
8973 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8975 if (Channel == RFRegTable[index].Channel)
8977 R1 = RFRegTable[index].R1 & 0xffffdfff;
8978 R2 = RFRegTable[index].R2 & 0xfffbffff;
8979 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8981 RTMP_RF_IO_WRITE32(pAd, R1);
8982 RTMP_RF_IO_WRITE32(pAd, R2);
8984 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8985 // Set RF R2 bit18=0, R3 bit[18:19]=0
8986 //if (pAd->StaCfg.bRadio == FALSE)
8989 RTMP_RF_IO_WRITE32(pAd, R3);
8991 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8992 Channel, pAd->RfIcType, R2, R3));
8995 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8996 Channel, pAd->RfIcType, R2));
9008 VOID AsicTurnOnRFClk(
9009 IN PRTMP_ADAPTER pAd,
9014 UINT32 R1 = 0, R2 = 0, R3 = 0;
9016 RTMP_RF_REGS *RFRegTable;
9018 // The RF programming sequence is difference between 3xxx and 2xxx
9022 RFRegTable = RF2850RegTable;
9024 switch (pAd->RfIcType)
9031 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9033 if (Channel == RFRegTable[index].Channel)
9035 R3 = pAd->LatchRfRegs.R3;
9038 RTMP_RF_IO_WRITE32(pAd, R3);
9040 R1 = RFRegTable[index].R1;
9041 RTMP_RF_IO_WRITE32(pAd, R1);
9043 R2 = RFRegTable[index].R2;
9044 if (pAd->Antenna.field.TxPath == 1)
9046 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
9049 if (pAd->Antenna.field.RxPath == 2)
9051 R2 |= 0x40; // write 1 to off Rxpath.
9053 else if (pAd->Antenna.field.RxPath == 1)
9055 R2 |= 0x20040; // write 1 to off RxPath
9057 RTMP_RF_IO_WRITE32(pAd, R2);
9068 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",