Staging: rt28x0: MlmeSelectTxRateTable() fix
[linux-2.6/mini2440.git] / drivers / staging / rt2860 / common / mlme.c
blob994821e18c542a0018e7b00e59d73ecf82e206b6
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
27 Module Name:
28 mlme.c
30 Abstract:
32 Revision History:
33 Who When What
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"
40 #include <stdarg.h>
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
47 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
48 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
49 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
50 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
51 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
52 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
54 UCHAR RateSwitchTable[] = {
55 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
56 0x11, 0x00, 0, 0, 0, // Initial used item after association
57 0x00, 0x00, 0, 40, 101,
58 0x01, 0x00, 1, 40, 50,
59 0x02, 0x00, 2, 35, 45,
60 0x03, 0x00, 3, 20, 45,
61 0x04, 0x21, 0, 30, 50,
62 0x05, 0x21, 1, 20, 50,
63 0x06, 0x21, 2, 20, 50,
64 0x07, 0x21, 3, 15, 50,
65 0x08, 0x21, 4, 15, 30,
66 0x09, 0x21, 5, 10, 25,
67 0x0a, 0x21, 6, 8, 25,
68 0x0b, 0x21, 7, 8, 25,
69 0x0c, 0x20, 12, 15, 30,
70 0x0d, 0x20, 13, 8, 20,
71 0x0e, 0x20, 14, 8, 20,
72 0x0f, 0x20, 15, 8, 25,
73 0x10, 0x22, 15, 8, 25,
74 0x11, 0x00, 0, 0, 0,
75 0x12, 0x00, 0, 0, 0,
76 0x13, 0x00, 0, 0, 0,
77 0x14, 0x00, 0, 0, 0,
78 0x15, 0x00, 0, 0, 0,
79 0x16, 0x00, 0, 0, 0,
80 0x17, 0x00, 0, 0, 0,
81 0x18, 0x00, 0, 0, 0,
82 0x19, 0x00, 0, 0, 0,
83 0x1a, 0x00, 0, 0, 0,
84 0x1b, 0x00, 0, 0, 0,
85 0x1c, 0x00, 0, 0, 0,
86 0x1d, 0x00, 0, 0, 0,
87 0x1e, 0x00, 0, 0, 0,
88 0x1f, 0x00, 0, 0, 0,
91 UCHAR RateSwitchTable11B[] = {
92 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
93 0x04, 0x03, 0, 0, 0, // Initial used item after association
94 0x00, 0x00, 0, 40, 101,
95 0x01, 0x00, 1, 40, 50,
96 0x02, 0x00, 2, 35, 45,
97 0x03, 0x00, 3, 20, 45,
100 UCHAR RateSwitchTable11BG[] = {
101 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
102 0x0a, 0x00, 0, 0, 0, // Initial used item after association
103 0x00, 0x00, 0, 40, 101,
104 0x01, 0x00, 1, 40, 50,
105 0x02, 0x00, 2, 35, 45,
106 0x03, 0x00, 3, 20, 45,
107 0x04, 0x10, 2, 20, 35,
108 0x05, 0x10, 3, 16, 35,
109 0x06, 0x10, 4, 10, 25,
110 0x07, 0x10, 5, 16, 25,
111 0x08, 0x10, 6, 10, 25,
112 0x09, 0x10, 7, 10, 13,
115 UCHAR RateSwitchTable11G[] = {
116 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
117 0x08, 0x00, 0, 0, 0, // Initial used item after association
118 0x00, 0x10, 0, 20, 101,
119 0x01, 0x10, 1, 20, 35,
120 0x02, 0x10, 2, 20, 35,
121 0x03, 0x10, 3, 16, 35,
122 0x04, 0x10, 4, 10, 25,
123 0x05, 0x10, 5, 16, 25,
124 0x06, 0x10, 6, 10, 25,
125 0x07, 0x10, 7, 10, 13,
128 UCHAR RateSwitchTable11N1S[] = {
129 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
130 0x09, 0x00, 0, 0, 0, // Initial used item after association
131 0x00, 0x21, 0, 30, 101,
132 0x01, 0x21, 1, 20, 50,
133 0x02, 0x21, 2, 20, 50,
134 0x03, 0x21, 3, 15, 50,
135 0x04, 0x21, 4, 15, 30,
136 0x05, 0x21, 5, 10, 25,
137 0x06, 0x21, 6, 8, 14,
138 0x07, 0x21, 7, 8, 14,
139 0x08, 0x23, 7, 8, 14,
142 UCHAR RateSwitchTable11N2S[] = {
143 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
144 0x0a, 0x00, 0, 0, 0, // Initial used item after association
145 0x00, 0x21, 0, 30, 101,
146 0x01, 0x21, 1, 20, 50,
147 0x02, 0x21, 2, 20, 50,
148 0x03, 0x21, 3, 15, 50,
149 0x04, 0x21, 4, 15, 30,
150 0x05, 0x20, 12, 15, 30,
151 0x06, 0x20, 13, 8, 20,
152 0x07, 0x20, 14, 8, 20,
153 0x08, 0x20, 15, 8, 25,
154 0x09, 0x22, 15, 8, 25,
157 UCHAR RateSwitchTable11N3S[] = {
158 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
159 0x0a, 0x00, 0, 0, 0, // Initial used item after association
160 0x00, 0x21, 0, 30, 101,
161 0x01, 0x21, 1, 20, 50,
162 0x02, 0x21, 2, 20, 50,
163 0x03, 0x21, 3, 15, 50,
164 0x04, 0x21, 4, 15, 30,
165 0x05, 0x20, 12, 15, 30,
166 0x06, 0x20, 13, 8, 20,
167 0x07, 0x20, 14, 8, 20,
168 0x08, 0x20, 15, 8, 25,
169 0x09, 0x22, 15, 8, 25,
172 UCHAR RateSwitchTable11N2SForABand[] = {
173 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
174 0x0b, 0x09, 0, 0, 0, // Initial used item after association
175 0x00, 0x21, 0, 30, 101,
176 0x01, 0x21, 1, 20, 50,
177 0x02, 0x21, 2, 20, 50,
178 0x03, 0x21, 3, 15, 50,
179 0x04, 0x21, 4, 15, 30,
180 0x05, 0x21, 5, 15, 30,
181 0x06, 0x20, 12, 15, 30,
182 0x07, 0x20, 13, 8, 20,
183 0x08, 0x20, 14, 8, 20,
184 0x09, 0x20, 15, 8, 25,
185 0x0a, 0x22, 15, 8, 25,
188 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
189 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
190 0x0b, 0x09, 0, 0, 0, // Initial used item after association
191 0x00, 0x21, 0, 30, 101,
192 0x01, 0x21, 1, 20, 50,
193 0x02, 0x21, 2, 20, 50,
194 0x03, 0x21, 3, 15, 50,
195 0x04, 0x21, 4, 15, 30,
196 0x05, 0x21, 5, 15, 30,
197 0x06, 0x20, 12, 15, 30,
198 0x07, 0x20, 13, 8, 20,
199 0x08, 0x20, 14, 8, 20,
200 0x09, 0x20, 15, 8, 25,
201 0x0a, 0x22, 15, 8, 25,
204 UCHAR RateSwitchTable11BGN1S[] = {
205 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
206 0x0d, 0x00, 0, 0, 0, // Initial used item after association
207 0x00, 0x00, 0, 40, 101,
208 0x01, 0x00, 1, 40, 50,
209 0x02, 0x00, 2, 35, 45,
210 0x03, 0x00, 3, 20, 45,
211 0x04, 0x21, 0, 30,101, //50
212 0x05, 0x21, 1, 20, 50,
213 0x06, 0x21, 2, 20, 50,
214 0x07, 0x21, 3, 15, 50,
215 0x08, 0x21, 4, 15, 30,
216 0x09, 0x21, 5, 10, 25,
217 0x0a, 0x21, 6, 8, 14,
218 0x0b, 0x21, 7, 8, 14,
219 0x0c, 0x23, 7, 8, 14,
222 UCHAR RateSwitchTable11BGN2S[] = {
223 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
224 0x0a, 0x00, 0, 0, 0, // Initial used item after association
225 0x00, 0x21, 0, 30,101, //50
226 0x01, 0x21, 1, 20, 50,
227 0x02, 0x21, 2, 20, 50,
228 0x03, 0x21, 3, 15, 50,
229 0x04, 0x21, 4, 15, 30,
230 0x05, 0x20, 12, 15, 30,
231 0x06, 0x20, 13, 8, 20,
232 0x07, 0x20, 14, 8, 20,
233 0x08, 0x20, 15, 8, 25,
234 0x09, 0x22, 15, 8, 25,
237 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
238 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
239 0x0a, 0x00, 0, 0, 0, // Initial used item after association
240 0x00, 0x21, 0, 30,101, //50
241 0x01, 0x21, 1, 20, 50,
242 0x02, 0x21, 2, 20, 50,
243 0x03, 0x21, 3, 20, 50,
244 0x04, 0x21, 4, 15, 50,
245 0x05, 0x20, 20, 15, 30,
246 0x06, 0x20, 21, 8, 20,
247 0x07, 0x20, 22, 8, 20,
248 0x08, 0x20, 23, 8, 25,
249 0x09, 0x22, 23, 8, 25,
252 UCHAR RateSwitchTable11BGN2SForABand[] = {
253 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
254 0x0b, 0x09, 0, 0, 0, // Initial used item after association
255 0x00, 0x21, 0, 30,101, //50
256 0x01, 0x21, 1, 20, 50,
257 0x02, 0x21, 2, 20, 50,
258 0x03, 0x21, 3, 15, 50,
259 0x04, 0x21, 4, 15, 30,
260 0x05, 0x21, 5, 15, 30,
261 0x06, 0x20, 12, 15, 30,
262 0x07, 0x20, 13, 8, 20,
263 0x08, 0x20, 14, 8, 20,
264 0x09, 0x20, 15, 8, 25,
265 0x0a, 0x22, 15, 8, 25,
268 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
269 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
270 0x0c, 0x09, 0, 0, 0, // Initial used item after association
271 0x00, 0x21, 0, 30,101, //50
272 0x01, 0x21, 1, 20, 50,
273 0x02, 0x21, 2, 20, 50,
274 0x03, 0x21, 3, 15, 50,
275 0x04, 0x21, 4, 15, 30,
276 0x05, 0x21, 5, 15, 30,
277 0x06, 0x21, 12, 15, 30,
278 0x07, 0x20, 20, 15, 30,
279 0x08, 0x20, 21, 8, 20,
280 0x09, 0x20, 22, 8, 20,
281 0x0a, 0x20, 23, 8, 25,
282 0x0b, 0x22, 23, 8, 25,
285 PUCHAR ReasonString[] = {
286 /* 0 */ "Reserved",
287 /* 1 */ "Unspecified Reason",
288 /* 2 */ "Previous Auth no longer valid",
289 /* 3 */ "STA is leaving / has left",
290 /* 4 */ "DIS-ASSOC due to inactivity",
291 /* 5 */ "AP unable to hanle all associations",
292 /* 6 */ "class 2 error",
293 /* 7 */ "class 3 error",
294 /* 8 */ "STA is leaving / has left",
295 /* 9 */ "require auth before assoc/re-assoc",
296 /* 10 */ "Reserved",
297 /* 11 */ "Reserved",
298 /* 12 */ "Reserved",
299 /* 13 */ "invalid IE",
300 /* 14 */ "MIC error",
301 /* 15 */ "4-way handshake timeout",
302 /* 16 */ "2-way (group key) handshake timeout",
303 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
304 /* 18 */
307 extern UCHAR OfdmRateToRxwiMCS[];
308 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
309 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
310 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
311 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
312 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
314 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
315 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
316 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
318 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
319 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
320 // clean environment.
321 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
322 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
324 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
325 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
327 UCHAR SsidIe = IE_SSID;
328 UCHAR SupRateIe = IE_SUPP_RATES;
329 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
330 UCHAR HtCapIe = IE_HT_CAP;
331 UCHAR AddHtInfoIe = IE_ADD_HT;
332 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
333 UCHAR ErpIe = IE_ERP;
334 UCHAR DsIe = IE_DS_PARM;
335 UCHAR TimIe = IE_TIM;
336 UCHAR WpaIe = IE_WPA;
337 UCHAR Wpa2Ie = IE_WPA2;
338 UCHAR IbssIe = IE_IBSS_PARM;
339 UCHAR Ccx2Ie = IE_CCX_V2;
341 extern UCHAR WPA_OUI[];
343 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
345 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
346 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
348 // Reset the RFIC setting to new series
349 RTMP_RF_REGS RF2850RegTable[] = {
350 // ch R1 R2 R3(TX0~4=0) R4
351 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
352 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
353 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
354 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
355 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
356 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
357 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
358 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
359 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
360 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
361 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
362 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
363 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
364 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
366 // 802.11 UNI / HyperLan 2
367 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
368 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
369 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
370 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
371 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
372 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
373 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
374 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
375 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
376 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
377 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
378 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
380 // 802.11 HyperLan 2
381 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
383 // 2008.04.30 modified
384 // The system team has AN to improve the EVM value
385 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
386 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
387 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
388 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
390 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
391 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
392 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
393 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
394 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
395 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
396 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
397 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
398 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
399 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
400 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
401 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
403 // 802.11 UNII
404 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
405 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
406 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
407 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
408 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
409 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
410 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
412 // Japan
413 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
414 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
415 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
416 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
417 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
418 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
419 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
421 // still lack of MMAC(Japan) ch 34,38,42,46
423 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
425 FREQUENCY_ITEM FreqItems3020[] =
427 /**************************************************/
428 // ISM : 2.4 to 2.483 GHz //
429 /**************************************************/
430 // 11g
431 /**************************************************/
432 //-CH---N-------R---K-----------
433 {1, 241, 2, 2},
434 {2, 241, 2, 7},
435 {3, 242, 2, 2},
436 {4, 242, 2, 7},
437 {5, 243, 2, 2},
438 {6, 243, 2, 7},
439 {7, 244, 2, 2},
440 {8, 244, 2, 7},
441 {9, 245, 2, 2},
442 {10, 245, 2, 7},
443 {11, 246, 2, 2},
444 {12, 246, 2, 7},
445 {13, 247, 2, 2},
446 {14, 248, 2, 4},
448 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
451 ==========================================================================
452 Description:
453 initialize the MLME task and its data structure (queue, spinlock,
454 timer, state machines).
456 IRQL = PASSIVE_LEVEL
458 Return:
459 always return NDIS_STATUS_SUCCESS
461 ==========================================================================
463 NDIS_STATUS MlmeInit(
464 IN PRTMP_ADAPTER pAd)
466 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
468 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
472 Status = MlmeQueueInit(&pAd->Mlme.Queue);
473 if(Status != NDIS_STATUS_SUCCESS)
474 break;
476 pAd->Mlme.bRunning = FALSE;
477 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
480 BssTableInit(&pAd->ScanTab);
482 // init STA state machines
483 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
484 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
485 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
486 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
487 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
488 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
490 // Since we are using switch/case to implement it, the init is different from the above
491 // state machine init
492 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
495 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
497 // Init mlme periodic timer
498 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
500 // Set mlme periodic timer
501 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
503 // software-based RX Antenna diversity
504 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
506 #ifdef RT2860
508 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
510 // only PCIe cards need these two timers
511 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
512 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
515 #endif
516 } while (FALSE);
518 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
520 return Status;
524 ==========================================================================
525 Description:
526 main loop of the MLME
527 Pre:
528 Mlme has to be initialized, and there are something inside the queue
529 Note:
530 This function is invoked from MPSetInformation and MPReceive;
531 This task guarantee only one MlmeHandler will run.
533 IRQL = DISPATCH_LEVEL
535 ==========================================================================
537 VOID MlmeHandler(
538 IN PRTMP_ADAPTER pAd)
540 MLME_QUEUE_ELEM *Elem = NULL;
542 // Only accept MLME and Frame from peer side, no other (control/data) frame should
543 // get into this state machine
545 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
546 if(pAd->Mlme.bRunning)
548 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
549 return;
551 else
553 pAd->Mlme.bRunning = TRUE;
555 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
557 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
559 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
560 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
561 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
563 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
564 break;
567 //From message type, determine which state machine I should drive
568 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
570 #ifdef RT2870
571 if (Elem->MsgType == MT2_RESET_CONF)
573 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
574 MlmeRestartStateMachine(pAd);
575 Elem->Occupied = FALSE;
576 Elem->MsgLen = 0;
577 continue;
579 #endif // RT2870 //
581 // if dequeue success
582 switch (Elem->Machine)
584 // STA state machines
585 case ASSOC_STATE_MACHINE:
586 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
587 break;
588 case AUTH_STATE_MACHINE:
589 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
590 break;
591 case AUTH_RSP_STATE_MACHINE:
592 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
593 break;
594 case SYNC_STATE_MACHINE:
595 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
596 break;
597 case MLME_CNTL_STATE_MACHINE:
598 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
599 break;
600 case WPA_PSK_STATE_MACHINE:
601 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
602 break;
603 case AIRONET_STATE_MACHINE:
604 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
605 break;
606 case ACTION_STATE_MACHINE:
607 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
608 break;
613 default:
614 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
615 break;
616 } // end of switch
618 // free MLME element
619 Elem->Occupied = FALSE;
620 Elem->MsgLen = 0;
623 else {
624 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
628 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
629 pAd->Mlme.bRunning = FALSE;
630 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
634 ==========================================================================
635 Description:
636 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
637 Parameters:
638 Adapter - NIC Adapter pointer
639 Post:
640 The MLME task will no longer work properly
642 IRQL = PASSIVE_LEVEL
644 ==========================================================================
646 VOID MlmeHalt(
647 IN PRTMP_ADAPTER pAd)
649 BOOLEAN Cancelled;
650 #ifdef RT3070
651 UINT32 TxPinCfg = 0x00050F0F;
652 #endif // RT3070 //
654 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
656 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
658 // disable BEACON generation and other BEACON related hardware timers
659 AsicDisableSync(pAd);
663 // Cancel pending timers
664 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
665 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
666 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
667 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
668 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
669 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
670 #ifdef RT2860
671 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
673 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
674 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
676 #endif
679 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
680 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
684 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
686 // Set LED
687 RTMPSetLED(pAd, LED_HALT);
688 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
689 #ifdef RT2870
691 LED_CFG_STRUC LedCfg;
692 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
693 LedCfg.field.LedPolar = 0;
694 LedCfg.field.RLedMode = 0;
695 LedCfg.field.GLedMode = 0;
696 LedCfg.field.YLedMode = 0;
697 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
699 #endif // RT2870 //
700 #ifdef RT3070
702 // Turn off LNA_PE
704 if (IS_RT3070(pAd) || IS_RT3071(pAd))
706 TxPinCfg &= 0xFFFFF0F0;
707 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
709 #endif // RT3070 //
712 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
714 MlmeQueueDestroy(&pAd->Mlme.Queue);
715 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
717 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
720 VOID MlmeResetRalinkCounters(
721 IN PRTMP_ADAPTER pAd)
723 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
724 // clear all OneSecxxx counters.
725 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
726 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
727 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
728 pAd->RalinkCounters.OneSecRxOkCnt = 0;
729 pAd->RalinkCounters.OneSecTxFailCount = 0;
730 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
731 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
732 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
734 // TODO: for debug only. to be removed
735 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
736 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
737 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
738 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
739 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
740 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
741 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
742 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
743 pAd->RalinkCounters.OneSecTxDoneCount = 0;
744 pAd->RalinkCounters.OneSecRxCount = 0;
745 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
746 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
748 return;
751 unsigned long rx_AMSDU;
752 unsigned long rx_Total;
755 ==========================================================================
756 Description:
757 This routine is executed periodically to -
758 1. Decide if it's a right time to turn on PwrMgmt bit of all
759 outgoiing frames
760 2. Calculate ChannelQuality based on statistics of the last
761 period, so that TX rate won't toggling very frequently between a
762 successful TX and a failed TX.
763 3. If the calculated ChannelQuality indicated current connection not
764 healthy, then a ROAMing attempt is tried here.
766 IRQL = DISPATCH_LEVEL
768 ==========================================================================
770 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
771 VOID MlmePeriodicExec(
772 IN PVOID SystemSpecific1,
773 IN PVOID FunctionContext,
774 IN PVOID SystemSpecific2,
775 IN PVOID SystemSpecific3)
777 ULONG TxTotalCnt;
778 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
780 #ifdef RT2860
781 //Baron 2008/07/10
782 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
783 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
784 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
785 if(pAd->StaCfg.WepStatus<2)
787 pAd->StaCfg.WpaSupplicantUP = 0;
789 else
791 pAd->StaCfg.WpaSupplicantUP = 1;
795 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
796 // Move code to here, because following code will return when radio is off
797 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
798 (pAd->StaCfg.bHardwareRadio == TRUE) &&
799 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
800 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
801 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
803 UINT32 data = 0;
805 // Read GPIO pin2 as Hardware controlled radio state
806 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
807 if (data & 0x04)
809 pAd->StaCfg.bHwRadio = TRUE;
811 else
813 pAd->StaCfg.bHwRadio = FALSE;
815 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
817 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
818 if (pAd->StaCfg.bRadio == TRUE)
820 MlmeRadioOn(pAd);
821 // Update extra information
822 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
824 else
826 MlmeRadioOff(pAd);
827 // Update extra information
828 pAd->ExtraInfo = HW_RADIO_OFF;
833 #endif /* RT2860 */
835 // Do nothing if the driver is starting halt state.
836 // This might happen when timer already been fired before cancel timer with mlmehalt
837 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
838 fRTMP_ADAPTER_RADIO_OFF |
839 fRTMP_ADAPTER_RADIO_MEASUREMENT |
840 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
841 return;
843 #ifdef RT2860
845 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
847 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
848 pAd->SameRxByteCount++;
850 else
851 pAd->SameRxByteCount = 0;
853 // If after BBP, still not work...need to check to reset PBF&MAC.
854 if (pAd->SameRxByteCount == 702)
856 pAd->SameRxByteCount = 0;
857 AsicResetPBF(pAd);
858 AsicResetMAC(pAd);
861 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
862 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
864 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
866 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
867 pAd->SameRxByteCount = 700;
868 AsicResetBBP(pAd);
872 // Update lastReceiveByteCount.
873 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
875 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
877 pAd->CheckDmaBusyCount = 0;
878 AsicResetFromDMABusy(pAd);
881 #endif /* RT2860 */
882 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
885 // Do nothing if monitor mode is on
886 if (MONITOR_ON(pAd))
887 return;
889 if (pAd->Mlme.PeriodicRound & 0x1)
891 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
892 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
893 (STA_TGN_WIFI_ON(pAd)) &&
894 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
897 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
898 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
900 else if ((STA_TGN_WIFI_ON(pAd)) &&
901 ((pAd->MACVersion & 0xffff) == 0x0101))
903 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
904 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
909 pAd->bUpdateBcnCntDone = FALSE;
911 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
912 pAd->Mlme.PeriodicRound ++;
914 #ifdef RT3070
915 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
916 NICUpdateFifoStaCounters(pAd);
917 #endif // RT3070 //
918 // execute every 500ms
919 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
921 // perform dynamic tx rate switching based on past TX history
923 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
925 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
926 MlmeDynamicTxRateSwitching(pAd);
930 // Normal 1 second Mlme PeriodicExec.
931 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
933 pAd->Mlme.OneSecPeriodicRound ++;
935 if (rx_Total)
938 // reset counters
939 rx_AMSDU = 0;
940 rx_Total = 0;
943 // Media status changed, report to NDIS
944 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
946 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
947 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
949 pAd->IndicateMediaState = NdisMediaStateConnected;
950 RTMP_IndicateMediaState(pAd);
953 else
955 pAd->IndicateMediaState = NdisMediaStateDisconnected;
956 RTMP_IndicateMediaState(pAd);
960 NdisGetSystemUpTime(&pAd->Mlme.Now32);
962 // add the most up-to-date h/w raw counters into software variable, so that
963 // the dynamic tuning mechanism below are based on most up-to-date information
964 NICUpdateRawCounters(pAd);
966 #ifdef RT2870
967 RT2870_WatchDog(pAd);
968 #endif // RT2870 //
970 // Need statistics after read counter. So put after NICUpdateRawCounters
971 ORIBATimerTimeout(pAd);
973 // The time period for checking antenna is according to traffic
974 if (pAd->Mlme.bEnableAutoAntennaCheck)
976 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
977 pAd->RalinkCounters.OneSecTxRetryOkCount +
978 pAd->RalinkCounters.OneSecTxFailCount;
980 // dynamic adjust antenna evaluation period according to the traffic
981 if (TxTotalCnt > 50)
983 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
985 AsicEvaluateRxAnt(pAd);
988 else
990 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
992 AsicEvaluateRxAnt(pAd);
997 STAMlmePeriodicExec(pAd);
999 MlmeResetRalinkCounters(pAd);
1002 #ifdef RT2860
1003 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1004 #endif
1006 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1007 // and sending CTS-to-self over and over.
1008 // Software Patch Solution:
1009 // 1. Polling debug state register 0x10F4 every one second.
1010 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1011 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1013 UINT32 MacReg = 0;
1015 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1016 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1018 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1019 RTMPusecDelay(1);
1020 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1022 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1027 RT28XX_MLME_HANDLER(pAd);
1030 pAd->bUpdateBcnCntDone = FALSE;
1033 VOID STAMlmePeriodicExec(
1034 PRTMP_ADAPTER pAd)
1036 #ifdef RT2860
1037 ULONG TxTotalCnt;
1038 #endif
1039 #ifdef RT2870
1040 ULONG TxTotalCnt;
1041 int i;
1042 #endif
1044 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1046 // WPA MIC error should block association attempt for 60 seconds
1047 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1048 pAd->StaCfg.bBlockAssoc = FALSE;
1051 #ifdef RT2860
1052 //Baron 2008/07/10
1053 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1054 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1055 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1056 if(pAd->StaCfg.WepStatus<2)
1058 pAd->StaCfg.WpaSupplicantUP = 0;
1060 else
1062 pAd->StaCfg.WpaSupplicantUP = 1;
1064 #endif
1066 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1068 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1070 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1072 pAd->PreMediaState = pAd->IndicateMediaState;
1075 #ifdef RT2860
1076 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1077 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1078 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1079 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1080 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1081 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1083 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1085 #endif
1089 AsicStaBbpTuning(pAd);
1091 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1092 pAd->RalinkCounters.OneSecTxRetryOkCount +
1093 pAd->RalinkCounters.OneSecTxFailCount;
1095 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1097 // update channel quality for Roaming and UI LinkQuality display
1098 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1101 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1102 // Radio is currently in noisy environment
1103 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1104 AsicAdjustTxPower(pAd);
1106 if (INFRA_ON(pAd))
1108 // Is PSM bit consistent with user power management policy?
1109 // This is the only place that will set PSM bit ON.
1110 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1111 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1113 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1115 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1116 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1117 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1119 RTMPSetAGCInitValue(pAd, BW_20);
1120 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1124 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1126 // When APSD is enabled, the period changes as 20 sec
1127 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1128 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1130 else
1132 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1133 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1135 if (pAd->CommonCfg.bWmmCapable)
1136 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1137 else
1138 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1143 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1145 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1146 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1147 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1149 // Lost AP, send disconnect & link down event
1150 LinkDown(pAd, FALSE);
1153 union iwreq_data wrqu;
1154 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1155 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1158 MlmeAutoReconnectLastSSID(pAd);
1160 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1162 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1163 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1164 MlmeAutoReconnectLastSSID(pAd);
1167 // Add auto seamless roaming
1168 if (pAd->StaCfg.bFastRoaming)
1170 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1172 DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
1174 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1176 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1180 else if (ADHOC_ON(pAd))
1182 #ifdef RT2860
1183 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1184 // the "TX BEACON competition" for the entire past 1 sec.
1185 // So that even when ASIC's BEACONgen engine been blocked
1186 // by peer's BEACON due to slower system clock, this STA still can send out
1187 // minimum BEACON to tell the peer I'm alive.
1188 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1189 // EnqueueBeaconFrame(pAd); // software send BEACON
1191 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1192 // restore outgoing BEACON to support B/G-mixed mode
1193 if ((pAd->CommonCfg.Channel <= 14) &&
1194 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1195 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1196 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1198 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1199 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1200 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1201 MlmeUpdateTxRates(pAd, FALSE, 0);
1202 MakeIbssBeacon(pAd); // re-build BEACON frame
1203 AsicEnableIbssSync(pAd); // copy to on-chip memory
1204 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1207 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1209 if ((pAd->StaCfg.AdhocBGJoined) &&
1210 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1212 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1213 pAd->StaCfg.AdhocBGJoined = FALSE;
1216 if ((pAd->StaCfg.Adhoc20NJoined) &&
1217 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1219 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1220 pAd->StaCfg.Adhoc20NJoined = FALSE;
1223 #endif /* RT2860 */
1225 //radar detect
1226 if ((pAd->CommonCfg.Channel > 14)
1227 && (pAd->CommonCfg.bIEEE80211H == 1)
1228 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1230 RadarDetectPeriodic(pAd);
1233 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1234 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1235 // join later.
1236 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1237 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1239 MLME_START_REQ_STRUCT StartReq;
1241 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1242 LinkDown(pAd, FALSE);
1244 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1245 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1246 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1249 #ifdef RT2870
1250 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1252 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1254 if (pEntry->ValidAsCLI == FALSE)
1255 continue;
1257 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1258 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1260 #endif
1262 else // no INFRA nor ADHOC connection
1265 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1266 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1267 goto SKIP_AUTO_SCAN_CONN;
1268 else
1269 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1271 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1272 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1273 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1275 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1277 MLME_SCAN_REQ_STRUCT ScanReq;
1279 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1281 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1282 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1283 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1284 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1285 // Reset Missed scan number
1286 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1288 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1289 MlmeAutoReconnectLastSSID(pAd);
1291 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1293 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1295 MlmeAutoScan(pAd);
1296 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1298 else
1300 MlmeAutoReconnectLastSSID(pAd);
1306 SKIP_AUTO_SCAN_CONN:
1308 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1310 pAd->MacTab.fAnyBASession = TRUE;
1311 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1313 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1315 pAd->MacTab.fAnyBASession = FALSE;
1316 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1319 return;
1322 // Link down report
1323 VOID LinkDownExec(
1324 IN PVOID SystemSpecific1,
1325 IN PVOID FunctionContext,
1326 IN PVOID SystemSpecific2,
1327 IN PVOID SystemSpecific3)
1330 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1332 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1333 RTMP_IndicateMediaState(pAd);
1334 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1337 // IRQL = DISPATCH_LEVEL
1338 VOID MlmeAutoScan(
1339 IN PRTMP_ADAPTER pAd)
1341 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1342 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1344 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1345 MlmeEnqueue(pAd,
1346 MLME_CNTL_STATE_MACHINE,
1347 OID_802_11_BSSID_LIST_SCAN,
1349 NULL);
1350 RT28XX_MLME_HANDLER(pAd);
1354 // IRQL = DISPATCH_LEVEL
1355 VOID MlmeAutoReconnectLastSSID(
1356 IN PRTMP_ADAPTER pAd)
1360 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1361 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1362 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1364 NDIS_802_11_SSID OidSsid;
1365 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1366 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1368 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1369 MlmeEnqueue(pAd,
1370 MLME_CNTL_STATE_MACHINE,
1371 OID_802_11_SSID,
1372 sizeof(NDIS_802_11_SSID),
1373 &OidSsid);
1374 RT28XX_MLME_HANDLER(pAd);
1379 ==========================================================================
1380 Validate SSID for connection try and rescan purpose
1381 Valid SSID will have visible chars only.
1382 The valid length is from 0 to 32.
1383 IRQL = DISPATCH_LEVEL
1384 ==========================================================================
1386 BOOLEAN MlmeValidateSSID(
1387 IN PUCHAR pSsid,
1388 IN UCHAR SsidLen)
1390 int index;
1392 if (SsidLen > MAX_LEN_OF_SSID)
1393 return (FALSE);
1395 // Check each character value
1396 for (index = 0; index < SsidLen; index++)
1398 if (pSsid[index] < 0x20)
1399 return (FALSE);
1402 // All checked
1403 return (TRUE);
1406 VOID MlmeSelectTxRateTable(
1407 IN PRTMP_ADAPTER pAd,
1408 IN PMAC_TABLE_ENTRY pEntry,
1409 IN PUCHAR *ppTable,
1410 IN PUCHAR pTableSize,
1411 IN PUCHAR pInitTxRateIdx)
1415 // decide the rate table for tuning
1416 if (pAd->CommonCfg.TxRateTableSize > 0)
1418 *ppTable = RateSwitchTable;
1419 *pTableSize = RateSwitchTable[0];
1420 *pInitTxRateIdx = RateSwitchTable[1];
1422 break;
1425 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1427 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1428 #ifdef RT2860
1429 !pAd->StaCfg.AdhocBOnlyJoined &&
1430 !pAd->StaCfg.AdhocBGJoined &&
1431 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1432 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1433 #endif
1434 #ifdef RT2870
1435 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1436 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1437 #endif
1438 {// 11N 1S Adhoc
1439 *ppTable = RateSwitchTable11N1S;
1440 *pTableSize = RateSwitchTable11N1S[0];
1441 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1444 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1445 #ifdef RT2860
1446 !pAd->StaCfg.AdhocBOnlyJoined &&
1447 !pAd->StaCfg.AdhocBGJoined &&
1448 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1449 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1450 #endif
1451 #ifdef RT2870
1452 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1453 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1454 #endif
1455 (pAd->Antenna.field.TxPath == 2))
1456 {// 11N 2S Adhoc
1457 if (pAd->LatchRfRegs.Channel <= 14)
1459 *ppTable = RateSwitchTable11N2S;
1460 *pTableSize = RateSwitchTable11N2S[0];
1461 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1463 else
1465 *ppTable = RateSwitchTable11N2SForABand;
1466 *pTableSize = RateSwitchTable11N2SForABand[0];
1467 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1471 else
1472 #ifdef RT2860
1473 if (pAd->CommonCfg.PhyMode == PHY_11B)
1475 *ppTable = RateSwitchTable11B;
1476 *pTableSize = RateSwitchTable11B[0];
1477 *pInitTxRateIdx = RateSwitchTable11B[1];
1480 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1481 #endif
1482 #ifdef RT2870
1483 if ((pEntry->RateLen == 4)
1484 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1486 #endif
1488 // USe B Table when Only b-only Station in my IBSS .
1489 *ppTable = RateSwitchTable11B;
1490 *pTableSize = RateSwitchTable11B[0];
1491 *pInitTxRateIdx = RateSwitchTable11B[1];
1494 else if (pAd->LatchRfRegs.Channel <= 14)
1496 *ppTable = RateSwitchTable11BG;
1497 *pTableSize = RateSwitchTable11BG[0];
1498 *pInitTxRateIdx = RateSwitchTable11BG[1];
1501 else
1503 *ppTable = RateSwitchTable11G;
1504 *pTableSize = RateSwitchTable11G[0];
1505 *pInitTxRateIdx = RateSwitchTable11G[1];
1508 break;
1511 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1512 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1513 {// 11BGN 1S AP
1514 *ppTable = RateSwitchTable11BGN1S;
1515 *pTableSize = RateSwitchTable11BGN1S[0];
1516 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1518 break;
1521 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1522 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1523 {// 11BGN 2S AP
1524 if (pAd->LatchRfRegs.Channel <= 14)
1526 *ppTable = RateSwitchTable11BGN2S;
1527 *pTableSize = RateSwitchTable11BGN2S[0];
1528 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1531 else
1533 *ppTable = RateSwitchTable11BGN2SForABand;
1534 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1535 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1538 break;
1541 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1542 {// 11N 1S AP
1543 *ppTable = RateSwitchTable11N1S;
1544 *pTableSize = RateSwitchTable11N1S[0];
1545 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1547 break;
1550 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1551 {// 11N 2S AP
1552 if (pAd->LatchRfRegs.Channel <= 14)
1554 *ppTable = RateSwitchTable11N2S;
1555 *pTableSize = RateSwitchTable11N2S[0];
1556 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1558 else
1560 *ppTable = RateSwitchTable11N2SForABand;
1561 *pTableSize = RateSwitchTable11N2SForABand[0];
1562 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1565 break;
1568 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1569 if (pEntry->RateLen == 4)
1570 {// B only AP
1571 *ppTable = RateSwitchTable11B;
1572 *pTableSize = RateSwitchTable11B[0];
1573 *pInitTxRateIdx = RateSwitchTable11B[1];
1575 break;
1578 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1579 if ((pEntry->RateLen > 8)
1580 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1582 {// B/G mixed AP
1583 *ppTable = RateSwitchTable11BG;
1584 *pTableSize = RateSwitchTable11BG[0];
1585 *pInitTxRateIdx = RateSwitchTable11BG[1];
1587 break;
1590 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1591 if ((pEntry->RateLen == 8)
1592 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1594 {// G only AP
1595 *ppTable = RateSwitchTable11G;
1596 *pTableSize = RateSwitchTable11G[0];
1597 *pInitTxRateIdx = RateSwitchTable11G[1];
1599 break;
1603 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1604 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1605 { // Legacy mode
1606 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1608 *ppTable = RateSwitchTable11B;
1609 *pTableSize = RateSwitchTable11B[0];
1610 *pInitTxRateIdx = RateSwitchTable11B[1];
1612 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1614 *ppTable = RateSwitchTable11G;
1615 *pTableSize = RateSwitchTable11G[0];
1616 *pInitTxRateIdx = RateSwitchTable11G[1];
1619 else
1621 *ppTable = RateSwitchTable11BG;
1622 *pTableSize = RateSwitchTable11BG[0];
1623 *pInitTxRateIdx = RateSwitchTable11BG[1];
1625 break;
1628 if (pAd->LatchRfRegs.Channel <= 14)
1630 if (pAd->CommonCfg.TxStream == 1)
1632 *ppTable = RateSwitchTable11N1S;
1633 *pTableSize = RateSwitchTable11N1S[0];
1634 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1635 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1637 else
1639 *ppTable = RateSwitchTable11N2S;
1640 *pTableSize = RateSwitchTable11N2S[0];
1641 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1642 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1645 else
1647 if (pAd->CommonCfg.TxStream == 1)
1649 *ppTable = RateSwitchTable11N1S;
1650 *pTableSize = RateSwitchTable11N1S[0];
1651 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1652 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1654 else
1656 *ppTable = RateSwitchTable11N2SForABand;
1657 *pTableSize = RateSwitchTable11N2SForABand[0];
1658 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1659 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1663 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1664 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1666 } while(FALSE);
1670 ==========================================================================
1671 Description:
1672 This routine checks if there're other APs out there capable for
1673 roaming. Caller should call this routine only when Link up in INFRA mode
1674 and channel quality is below CQI_GOOD_THRESHOLD.
1676 IRQL = DISPATCH_LEVEL
1678 Output:
1679 ==========================================================================
1681 VOID MlmeCheckForRoaming(
1682 IN PRTMP_ADAPTER pAd,
1683 IN ULONG Now32)
1685 USHORT i;
1686 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1687 BSS_ENTRY *pBss;
1689 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1690 // put all roaming candidates into RoamTab, and sort in RSSI order
1691 BssTableInit(pRoamTab);
1692 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1694 pBss = &pAd->ScanTab.BssEntry[i];
1696 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1697 continue; // AP disappear
1698 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1699 continue; // RSSI too weak. forget it.
1700 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1701 continue; // skip current AP
1702 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1703 continue; // only AP with stronger RSSI is eligible for roaming
1705 // AP passing all above rules is put into roaming candidate table
1706 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1707 pRoamTab->BssNr += 1;
1710 if (pRoamTab->BssNr > 0)
1712 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1713 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1715 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1716 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1717 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1718 RT28XX_MLME_HANDLER(pAd);
1721 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1725 ==========================================================================
1726 Description:
1727 This routine checks if there're other APs out there capable for
1728 roaming. Caller should call this routine only when link up in INFRA mode
1729 and channel quality is below CQI_GOOD_THRESHOLD.
1731 IRQL = DISPATCH_LEVEL
1733 Output:
1734 ==========================================================================
1736 VOID MlmeCheckForFastRoaming(
1737 IN PRTMP_ADAPTER pAd,
1738 IN ULONG Now)
1740 USHORT i;
1741 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1742 BSS_ENTRY *pBss;
1744 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1745 // put all roaming candidates into RoamTab, and sort in RSSI order
1746 BssTableInit(pRoamTab);
1747 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1749 pBss = &pAd->ScanTab.BssEntry[i];
1751 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1752 continue; // RSSI too weak. forget it.
1753 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1754 continue; // skip current AP
1755 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1756 continue; // skip different SSID
1757 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1758 continue; // skip AP without better RSSI
1760 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));
1761 // AP passing all above rules is put into roaming candidate table
1762 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1763 pRoamTab->BssNr += 1;
1766 if (pRoamTab->BssNr > 0)
1768 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1769 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1771 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1772 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1773 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1774 RT28XX_MLME_HANDLER(pAd);
1777 // Maybe site survey required
1778 else
1780 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1782 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1783 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1784 pAd->StaCfg.ScanCnt = 2;
1785 pAd->StaCfg.LastScanTime = Now;
1786 MlmeAutoScan(pAd);
1790 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1794 ==========================================================================
1795 Description:
1796 This routine calculates TxPER, RxPER of the past N-sec period. And
1797 according to the calculation result, ChannelQuality is calculated here
1798 to decide if current AP is still doing the job.
1800 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1801 Output:
1802 StaCfg.ChannelQuality - 0..100
1804 IRQL = DISPATCH_LEVEL
1806 NOTE: This routine decide channle quality based on RX CRC error ratio.
1807 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1808 is performed right before this routine, so that this routine can decide
1809 channel quality based on the most up-to-date information
1810 ==========================================================================
1812 VOID MlmeCalculateChannelQuality(
1813 IN PRTMP_ADAPTER pAd,
1814 IN ULONG Now32)
1816 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1817 ULONG RxCnt, RxPER;
1818 UCHAR NorRssi;
1819 CHAR MaxRssi;
1820 ULONG BeaconLostTime = BEACON_LOST_TIME;
1822 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1825 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1827 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1828 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1829 if (TxCnt < 5)
1831 TxPER = 0;
1832 TxPRR = 0;
1834 else
1836 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1837 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1841 // calculate RX PER - don't take RxPER into consideration if too few sample
1843 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1844 if (RxCnt < 5)
1845 RxPER = 0;
1846 else
1847 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1850 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1852 if (INFRA_ON(pAd) &&
1853 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1854 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1856 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1857 pAd->Mlme.ChannelQuality = 0;
1859 else
1861 // Normalize Rssi
1862 if (MaxRssi > -40)
1863 NorRssi = 100;
1864 else if (MaxRssi < -90)
1865 NorRssi = 0;
1866 else
1867 NorRssi = (MaxRssi + 90) * 2;
1869 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1870 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1871 TX_WEIGHTING * (100 - TxPRR) +
1872 RX_WEIGHTING* (100 - RxPER)) / 100;
1873 if (pAd->Mlme.ChannelQuality >= 100)
1874 pAd->Mlme.ChannelQuality = 100;
1879 VOID MlmeSetTxRate(
1880 IN PRTMP_ADAPTER pAd,
1881 IN PMAC_TABLE_ENTRY pEntry,
1882 IN PRTMP_TX_RATE_SWITCH pTxRate)
1884 UCHAR MaxMode = MODE_OFDM;
1886 MaxMode = MODE_HTGREENFIELD;
1888 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1889 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1890 else
1891 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1893 if (pTxRate->CurrMCS < MCS_AUTO)
1894 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1896 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1897 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1899 if (ADHOC_ON(pAd))
1901 // If peer adhoc is b-only mode, we can't send 11g rate.
1902 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1903 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1906 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1908 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1909 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1910 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1912 // Patch speed error in status page
1913 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1915 else
1917 if (pTxRate->Mode <= MaxMode)
1918 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1920 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1921 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1922 else
1923 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1925 // Reexam each bandwidth's SGI support.
1926 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1928 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1929 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1930 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1931 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1934 // Turn RTS/CTS rate to 6Mbps.
1935 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1937 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1938 if (pAd->MacTab.fAnyBASession)
1940 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1942 else
1944 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1947 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1949 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1950 if (pAd->MacTab.fAnyBASession)
1952 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1954 else
1956 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1959 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1961 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1964 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1966 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1969 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1970 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1971 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1972 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1974 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1975 pAd->WIFItestbed.bGreenField)
1976 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1979 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1983 ==========================================================================
1984 Description:
1985 This routine calculates the acumulated TxPER of eaxh TxRate. And
1986 according to the calculation result, change CommonCfg.TxRate which
1987 is the stable TX Rate we expect the Radio situation could sustained.
1989 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1990 Output:
1991 CommonCfg.TxRate -
1993 IRQL = DISPATCH_LEVEL
1995 NOTE:
1996 call this routine every second
1997 ==========================================================================
1999 VOID MlmeDynamicTxRateSwitching(
2000 IN PRTMP_ADAPTER pAd)
2002 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2003 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2004 ULONG TxErrorRatio = 0;
2005 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2006 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2007 PUCHAR pTable;
2008 UCHAR TableSize = 0;
2009 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2010 CHAR Rssi, RssiOffset = 0;
2011 TX_STA_CNT1_STRUC StaTx1;
2012 TX_STA_CNT0_STRUC TxStaCnt0;
2013 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2014 MAC_TABLE_ENTRY *pEntry;
2017 // walk through MAC table, see if need to change AP's TX rate toward each entry
2019 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2021 pEntry = &pAd->MacTab.Content[i];
2023 // check if this entry need to switch rate automatically
2024 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2025 continue;
2027 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2029 #ifdef RT2860
2030 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2031 #endif
2032 #ifdef RT2870
2033 Rssi = RTMPMaxRssi(pAd,
2034 pAd->StaCfg.RssiSample.AvgRssi0,
2035 pAd->StaCfg.RssiSample.AvgRssi1,
2036 pAd->StaCfg.RssiSample.AvgRssi2);
2037 #endif
2039 // Update statistic counter
2040 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2041 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2042 pAd->bUpdateBcnCntDone = TRUE;
2043 TxRetransmit = StaTx1.field.TxRetransmit;
2044 TxSuccess = StaTx1.field.TxSuccess;
2045 TxFailCount = TxStaCnt0.field.TxFailCount;
2046 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2048 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2049 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2050 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2051 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2052 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2053 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2055 // if no traffic in the past 1-sec period, don't change TX rate,
2056 // but clear all bad history. because the bad history may affect the next
2057 // Chariot throughput test
2058 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2059 pAd->RalinkCounters.OneSecTxRetryOkCount +
2060 pAd->RalinkCounters.OneSecTxFailCount;
2062 if (TxTotalCnt)
2063 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2065 else
2067 #ifdef RT2860
2068 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2069 #endif
2070 #ifdef RT2870
2071 if (INFRA_ON(pAd) && (i == 1))
2072 Rssi = RTMPMaxRssi(pAd,
2073 pAd->StaCfg.RssiSample.AvgRssi0,
2074 pAd->StaCfg.RssiSample.AvgRssi1,
2075 pAd->StaCfg.RssiSample.AvgRssi2);
2076 else
2077 Rssi = RTMPMaxRssi(pAd,
2078 pEntry->RssiSample.AvgRssi0,
2079 pEntry->RssiSample.AvgRssi1,
2080 pEntry->RssiSample.AvgRssi2);
2081 #endif
2083 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2084 pEntry->OneSecTxRetryOkCount +
2085 pEntry->OneSecTxFailCount;
2087 if (TxTotalCnt)
2088 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2091 CurrRateIdx = pEntry->CurrTxRateIndex;
2093 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2095 if (CurrRateIdx >= TableSize)
2097 CurrRateIdx = TableSize - 1;
2100 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2101 // So need to sync here.
2102 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2103 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2104 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2108 // Need to sync Real Tx rate and our record.
2109 // Then return for next DRS.
2110 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2111 pEntry->CurrTxRateIndex = InitTxRateIdx;
2112 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2114 // reset all OneSecTx counters
2115 RESET_ONE_SEC_TX_CNT(pEntry);
2116 continue;
2119 // decide the next upgrade rate and downgrade rate, if any
2120 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2122 UpRateIdx = CurrRateIdx + 1;
2123 DownRateIdx = CurrRateIdx -1;
2125 else if (CurrRateIdx == 0)
2127 UpRateIdx = CurrRateIdx + 1;
2128 DownRateIdx = CurrRateIdx;
2130 else if (CurrRateIdx == (TableSize - 1))
2132 UpRateIdx = CurrRateIdx;
2133 DownRateIdx = CurrRateIdx - 1;
2136 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2138 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2140 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2141 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2143 else
2145 TrainUp = pCurrTxRate->TrainUp;
2146 TrainDown = pCurrTxRate->TrainDown;
2149 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2152 // Keep the last time TxRateChangeAction status.
2154 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2159 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2160 // (criteria copied from RT2500 for Netopia case)
2162 if (TxTotalCnt <= 15)
2164 CHAR idx = 0;
2165 UCHAR TxRateIdx;
2166 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2167 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2168 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2169 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2171 // check the existence and index of each needed MCS
2172 while (idx < pTable[0])
2174 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2176 if (pCurrTxRate->CurrMCS == MCS_0)
2178 MCS0 = idx;
2180 else if (pCurrTxRate->CurrMCS == MCS_1)
2182 MCS1 = idx;
2184 else if (pCurrTxRate->CurrMCS == MCS_2)
2186 MCS2 = idx;
2188 else if (pCurrTxRate->CurrMCS == MCS_3)
2190 MCS3 = idx;
2192 else if (pCurrTxRate->CurrMCS == MCS_4)
2194 MCS4 = idx;
2196 else if (pCurrTxRate->CurrMCS == MCS_5)
2198 MCS5 = idx;
2200 else if (pCurrTxRate->CurrMCS == MCS_6)
2202 MCS6 = idx;
2204 //else if (pCurrTxRate->CurrMCS == MCS_7)
2205 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2207 MCS7 = idx;
2209 else if (pCurrTxRate->CurrMCS == MCS_12)
2211 MCS12 = idx;
2213 else if (pCurrTxRate->CurrMCS == MCS_13)
2215 MCS13 = idx;
2217 else if (pCurrTxRate->CurrMCS == MCS_14)
2219 MCS14 = idx;
2221 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
2223 MCS15 = idx;
2225 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2227 MCS20 = idx;
2229 else if (pCurrTxRate->CurrMCS == MCS_21)
2231 MCS21 = idx;
2233 else if (pCurrTxRate->CurrMCS == MCS_22)
2235 MCS22 = idx;
2237 else if (pCurrTxRate->CurrMCS == MCS_23)
2239 MCS23 = idx;
2241 idx ++;
2244 if (pAd->LatchRfRegs.Channel <= 14)
2246 if (pAd->NicConfig2.field.ExternalLNAForG)
2248 RssiOffset = 2;
2250 else
2252 RssiOffset = 5;
2255 else
2257 if (pAd->NicConfig2.field.ExternalLNAForA)
2259 RssiOffset = 5;
2261 else
2263 RssiOffset = 8;
2267 /*if (MCS15)*/
2268 if ((pTable == RateSwitchTable11BGN3S) ||
2269 (pTable == RateSwitchTable11N3S) ||
2270 (pTable == RateSwitchTable))
2271 {// N mode with 3 stream // 3*3
2272 if (MCS23 && (Rssi >= -70))
2273 TxRateIdx = MCS15;
2274 else if (MCS22 && (Rssi >= -72))
2275 TxRateIdx = MCS14;
2276 else if (MCS21 && (Rssi >= -76))
2277 TxRateIdx = MCS13;
2278 else if (MCS20 && (Rssi >= -78))
2279 TxRateIdx = MCS12;
2280 else if (MCS4 && (Rssi >= -82))
2281 TxRateIdx = MCS4;
2282 else if (MCS3 && (Rssi >= -84))
2283 TxRateIdx = MCS3;
2284 else if (MCS2 && (Rssi >= -86))
2285 TxRateIdx = MCS2;
2286 else if (MCS1 && (Rssi >= -88))
2287 TxRateIdx = MCS1;
2288 else
2289 TxRateIdx = MCS0;
2291 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2292 {// N mode with 2 stream
2293 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2294 TxRateIdx = MCS15;
2295 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2296 TxRateIdx = MCS14;
2297 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2298 TxRateIdx = MCS13;
2299 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2300 TxRateIdx = MCS12;
2301 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2302 TxRateIdx = MCS4;
2303 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2304 TxRateIdx = MCS3;
2305 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2306 TxRateIdx = MCS2;
2307 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2308 TxRateIdx = MCS1;
2309 else
2310 TxRateIdx = MCS0;
2312 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2313 {// N mode with 1 stream
2314 if (MCS7 && (Rssi > (-72+RssiOffset)))
2315 TxRateIdx = MCS7;
2316 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2317 TxRateIdx = MCS6;
2318 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2319 TxRateIdx = MCS5;
2320 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2321 TxRateIdx = MCS4;
2322 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2323 TxRateIdx = MCS3;
2324 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2325 TxRateIdx = MCS2;
2326 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2327 TxRateIdx = MCS1;
2328 else
2329 TxRateIdx = MCS0;
2331 else
2332 {// Legacy mode
2333 if (MCS7 && (Rssi > -70))
2334 TxRateIdx = MCS7;
2335 else if (MCS6 && (Rssi > -74))
2336 TxRateIdx = MCS6;
2337 else if (MCS5 && (Rssi > -78))
2338 TxRateIdx = MCS5;
2339 else if (MCS4 && (Rssi > -82))
2340 TxRateIdx = MCS4;
2341 else if (MCS4 == 0) // for B-only mode
2342 TxRateIdx = MCS3;
2343 else if (MCS3 && (Rssi > -85))
2344 TxRateIdx = MCS3;
2345 else if (MCS2 && (Rssi > -87))
2346 TxRateIdx = MCS2;
2347 else if (MCS1 && (Rssi > -90))
2348 TxRateIdx = MCS1;
2349 else
2350 TxRateIdx = MCS0;
2354 pEntry->CurrTxRateIndex = TxRateIdx;
2355 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2356 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2359 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2360 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2361 pEntry->fLastSecAccordingRSSI = TRUE;
2362 // reset all OneSecTx counters
2363 RESET_ONE_SEC_TX_CNT(pEntry);
2365 continue;
2368 if (pEntry->fLastSecAccordingRSSI == TRUE)
2370 pEntry->fLastSecAccordingRSSI = FALSE;
2371 pEntry->LastSecTxRateChangeAction = 0;
2372 // reset all OneSecTx counters
2373 RESET_ONE_SEC_TX_CNT(pEntry);
2375 continue;
2380 BOOLEAN bTrainUpDown = FALSE;
2382 pEntry->CurrTxRateStableTime ++;
2384 // downgrade TX quality if PER >= Rate-Down threshold
2385 if (TxErrorRatio >= TrainDown)
2387 bTrainUpDown = TRUE;
2388 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2390 // upgrade TX quality if PER <= Rate-Up threshold
2391 else if (TxErrorRatio <= TrainUp)
2393 bTrainUpDown = TRUE;
2394 bUpgradeQuality = TRUE;
2395 if (pEntry->TxQuality[CurrRateIdx])
2396 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2398 if (pEntry->TxRateUpPenalty)
2399 pEntry->TxRateUpPenalty --;
2400 else if (pEntry->TxQuality[UpRateIdx])
2401 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2404 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2406 if (bTrainUpDown)
2408 // perform DRS - consider TxRate Down first, then rate up.
2409 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2411 pEntry->CurrTxRateIndex = DownRateIdx;
2413 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2415 pEntry->CurrTxRateIndex = UpRateIdx;
2418 } while (FALSE);
2420 // if rate-up happen, clear all bad history of all TX rates
2421 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2423 pEntry->CurrTxRateStableTime = 0;
2424 pEntry->TxRateUpPenalty = 0;
2425 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2426 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2427 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2430 // For TxRate fast train up
2432 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2434 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2436 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2438 bTxRateChanged = TRUE;
2440 // if rate-down happen, only clear DownRate's bad history
2441 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2443 pEntry->CurrTxRateStableTime = 0;
2444 pEntry->TxRateUpPenalty = 0; // no penalty
2445 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2446 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2447 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2450 // For TxRate fast train down
2452 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2454 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2456 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2458 bTxRateChanged = TRUE;
2460 else
2462 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2463 bTxRateChanged = FALSE;
2466 pEntry->LastTxOkCount = TxSuccess;
2468 // reset all OneSecTx counters
2469 RESET_ONE_SEC_TX_CNT(pEntry);
2471 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2472 if (bTxRateChanged && pNextTxRate)
2474 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2480 ========================================================================
2481 Routine Description:
2482 Station side, Auto TxRate faster train up timer call back function.
2484 Arguments:
2485 SystemSpecific1 - Not used.
2486 FunctionContext - Pointer to our Adapter context.
2487 SystemSpecific2 - Not used.
2488 SystemSpecific3 - Not used.
2490 Return Value:
2491 None
2493 ========================================================================
2495 VOID StaQuickResponeForRateUpExec(
2496 IN PVOID SystemSpecific1,
2497 IN PVOID FunctionContext,
2498 IN PVOID SystemSpecific2,
2499 IN PVOID SystemSpecific3)
2501 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2502 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2503 ULONG TxTotalCnt;
2504 ULONG TxErrorRatio = 0;
2505 #ifdef RT2860
2506 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2507 #endif
2508 #ifdef RT2870
2509 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2510 #endif
2511 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2512 PUCHAR pTable;
2513 UCHAR TableSize = 0;
2514 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2515 TX_STA_CNT1_STRUC StaTx1;
2516 TX_STA_CNT0_STRUC TxStaCnt0;
2517 CHAR Rssi, ratio;
2518 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2519 MAC_TABLE_ENTRY *pEntry;
2520 ULONG i;
2522 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2525 // walk through MAC table, see if need to change AP's TX rate toward each entry
2527 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2529 pEntry = &pAd->MacTab.Content[i];
2531 // check if this entry need to switch rate automatically
2532 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2533 continue;
2535 #ifdef RT2860
2536 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2537 if (pAd->Antenna.field.TxPath > 1)
2538 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2539 else
2540 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2541 #endif
2542 #ifdef RT2870
2543 if (INFRA_ON(pAd) && (i == 1))
2544 Rssi = RTMPMaxRssi(pAd,
2545 pAd->StaCfg.RssiSample.AvgRssi0,
2546 pAd->StaCfg.RssiSample.AvgRssi1,
2547 pAd->StaCfg.RssiSample.AvgRssi2);
2548 else
2549 Rssi = RTMPMaxRssi(pAd,
2550 pEntry->RssiSample.AvgRssi0,
2551 pEntry->RssiSample.AvgRssi1,
2552 pEntry->RssiSample.AvgRssi2);
2553 #endif
2555 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2557 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2559 // decide the next upgrade rate and downgrade rate, if any
2560 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2562 UpRateIdx = CurrRateIdx + 1;
2563 DownRateIdx = CurrRateIdx -1;
2565 else if (CurrRateIdx == 0)
2567 UpRateIdx = CurrRateIdx + 1;
2568 DownRateIdx = CurrRateIdx;
2570 else if (CurrRateIdx == (TableSize - 1))
2572 UpRateIdx = CurrRateIdx;
2573 DownRateIdx = CurrRateIdx - 1;
2576 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2578 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2580 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2581 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2583 else
2585 TrainUp = pCurrTxRate->TrainUp;
2586 TrainDown = pCurrTxRate->TrainDown;
2589 if (pAd->MacTab.Size == 1)
2591 // Update statistic counter
2592 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2593 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2595 TxRetransmit = StaTx1.field.TxRetransmit;
2596 TxSuccess = StaTx1.field.TxSuccess;
2597 TxFailCount = TxStaCnt0.field.TxFailCount;
2598 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2600 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2601 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2602 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2603 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2604 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2605 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2607 if (TxTotalCnt)
2608 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2610 else
2612 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2613 pEntry->OneSecTxRetryOkCount +
2614 pEntry->OneSecTxFailCount;
2616 if (TxTotalCnt)
2617 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2622 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2623 // (criteria copied from RT2500 for Netopia case)
2625 if (TxTotalCnt <= 12)
2627 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2628 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2630 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2632 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2633 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2635 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2637 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2640 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2641 return;
2646 ULONG OneSecTxNoRetryOKRationCount;
2648 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2649 ratio = 5;
2650 else
2651 ratio = 4;
2653 // downgrade TX quality if PER >= Rate-Down threshold
2654 if (TxErrorRatio >= TrainDown)
2656 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2659 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2661 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2663 // perform DRS - consider TxRate Down first, then rate up.
2664 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2666 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2668 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2669 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2674 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2676 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2680 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2682 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2685 }while (FALSE);
2687 // if rate-up happen, clear all bad history of all TX rates
2688 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2690 pAd->DrsCounters.TxRateUpPenalty = 0;
2691 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2692 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2693 #ifdef RT2870
2694 bTxRateChanged = TRUE;
2695 #endif
2697 // if rate-down happen, only clear DownRate's bad history
2698 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2700 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2702 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2703 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2704 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2705 #ifdef RT2870
2706 bTxRateChanged = TRUE;
2707 #endif
2709 else
2711 bTxRateChanged = FALSE;
2714 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2715 if (bTxRateChanged && pNextTxRate)
2717 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2723 ==========================================================================
2724 Description:
2725 This routine is executed periodically inside MlmePeriodicExec() after
2726 association with an AP.
2727 It checks if StaCfg.Psm is consistent with user policy (recorded in
2728 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2729 there're some conditions to consider:
2730 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2731 the time when Mibss==TRUE
2732 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2733 if outgoing traffic available in TxRing or MgmtRing.
2734 Output:
2735 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2737 IRQL = DISPATCH_LEVEL
2739 ==========================================================================
2741 VOID MlmeCheckPsmChange(
2742 IN PRTMP_ADAPTER pAd,
2743 IN ULONG Now32)
2745 ULONG PowerMode;
2747 // condition -
2748 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2749 // 2. user wants either MAX_PSP or FAST_PSP
2750 // 3. but current psm is not in PWR_SAVE
2751 // 4. CNTL state machine is not doing SCANning
2752 // 5. no TX SUCCESS event for the past 1-sec period
2753 #ifdef NDIS51_MINIPORT
2754 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2755 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2756 else
2757 #endif
2758 PowerMode = pAd->StaCfg.WindowsPowerMode;
2760 if (INFRA_ON(pAd) &&
2761 (PowerMode != Ndis802_11PowerModeCAM) &&
2762 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2763 #ifdef RT2860
2764 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2765 #else
2766 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2767 #endif
2769 #ifdef RT30xx
2770 // add by johnli, use Rx OK data count per second to calculate throughput
2771 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2772 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2773 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2774 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2775 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2776 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2777 #endif
2779 // Get this time
2780 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2781 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2782 MlmeSetPsmBit(pAd, PWR_SAVE);
2783 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2785 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2787 else
2789 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2795 // IRQL = PASSIVE_LEVEL
2796 // IRQL = DISPATCH_LEVEL
2797 VOID MlmeSetPsmBit(
2798 IN PRTMP_ADAPTER pAd,
2799 IN USHORT psm)
2801 AUTO_RSP_CFG_STRUC csr4;
2803 pAd->StaCfg.Psm = psm;
2804 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2805 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2806 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2808 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2811 // IRQL = DISPATCH_LEVEL
2812 VOID MlmeSetTxPreamble(
2813 IN PRTMP_ADAPTER pAd,
2814 IN USHORT TxPreamble)
2816 AUTO_RSP_CFG_STRUC csr4;
2819 // Always use Long preamble before verifiation short preamble functionality works well.
2820 // Todo: remove the following line if short preamble functionality works
2822 //TxPreamble = Rt802_11PreambleLong;
2824 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2825 if (TxPreamble == Rt802_11PreambleLong)
2827 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2828 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2829 csr4.field.AutoResponderPreamble = 0;
2831 else
2833 // NOTE: 1Mbps should always use long preamble
2834 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2835 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2836 csr4.field.AutoResponderPreamble = 1;
2839 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2843 ==========================================================================
2844 Description:
2845 Update basic rate bitmap
2846 ==========================================================================
2849 VOID UpdateBasicRateBitmap(
2850 IN PRTMP_ADAPTER pAdapter)
2852 INT i, j;
2853 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2854 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2855 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2856 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2857 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2860 /* if A mode, always use fix BasicRateBitMap */
2861 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2862 if (pAdapter->CommonCfg.Channel > 14)
2863 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2864 /* End of if */
2866 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2868 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2869 return;
2870 } /* End of if */
2872 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2874 sup_p[i] &= 0x7f;
2875 ext_p[i] &= 0x7f;
2876 } /* End of for */
2878 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2880 if (bitmap & (1 << i))
2882 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2884 if (sup_p[j] == rate[i])
2885 sup_p[j] |= 0x80;
2886 /* End of if */
2887 } /* End of for */
2889 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2891 if (ext_p[j] == rate[i])
2892 ext_p[j] |= 0x80;
2893 /* End of if */
2894 } /* End of for */
2895 } /* End of if */
2896 } /* End of for */
2897 } /* End of UpdateBasicRateBitmap */
2899 // IRQL = PASSIVE_LEVEL
2900 // IRQL = DISPATCH_LEVEL
2901 // bLinkUp is to identify the inital link speed.
2902 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2903 VOID MlmeUpdateTxRates(
2904 IN PRTMP_ADAPTER pAd,
2905 IN BOOLEAN bLinkUp,
2906 IN UCHAR apidx)
2908 int i, num;
2909 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2910 UCHAR MinSupport = RATE_54;
2911 ULONG BasicRateBitmap = 0;
2912 UCHAR CurrBasicRate = RATE_1;
2913 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2914 PHTTRANSMIT_SETTING pHtPhy = NULL;
2915 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2916 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2917 BOOLEAN *auto_rate_cur_p;
2918 UCHAR HtMcs = MCS_AUTO;
2920 // find max desired rate
2921 UpdateBasicRateBitmap(pAd);
2923 num = 0;
2924 auto_rate_cur_p = NULL;
2925 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2927 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2929 case 2: Rate = RATE_1; num++; break;
2930 case 4: Rate = RATE_2; num++; break;
2931 case 11: Rate = RATE_5_5; num++; break;
2932 case 22: Rate = RATE_11; num++; break;
2933 case 12: Rate = RATE_6; num++; break;
2934 case 18: Rate = RATE_9; num++; break;
2935 case 24: Rate = RATE_12; num++; break;
2936 case 36: Rate = RATE_18; num++; break;
2937 case 48: Rate = RATE_24; num++; break;
2938 case 72: Rate = RATE_36; num++; break;
2939 case 96: Rate = RATE_48; num++; break;
2940 case 108: Rate = RATE_54; num++; break;
2941 //default: Rate = RATE_1; break;
2943 if (MaxDesire < Rate) MaxDesire = Rate;
2946 //===========================================================================
2947 //===========================================================================
2949 pHtPhy = &pAd->StaCfg.HTPhyMode;
2950 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2951 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2953 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2954 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2956 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2957 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2958 (MaxDesire > RATE_11))
2960 MaxDesire = RATE_11;
2964 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2965 pMinHtPhy->word = 0;
2966 pMaxHtPhy->word = 0;
2967 pHtPhy->word = 0;
2969 // Auto rate switching is enabled only if more than one DESIRED RATES are
2970 // specified; otherwise disabled
2971 if (num <= 1)
2973 *auto_rate_cur_p = FALSE;
2975 else
2977 *auto_rate_cur_p = TRUE;
2980 #if 1
2981 if (HtMcs != MCS_AUTO)
2983 *auto_rate_cur_p = FALSE;
2985 else
2987 *auto_rate_cur_p = TRUE;
2989 #endif
2991 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2993 pSupRate = &pAd->StaActive.SupRate[0];
2994 pExtRate = &pAd->StaActive.ExtRate[0];
2995 SupRateLen = pAd->StaActive.SupRateLen;
2996 ExtRateLen = pAd->StaActive.ExtRateLen;
2998 else
3000 pSupRate = &pAd->CommonCfg.SupRate[0];
3001 pExtRate = &pAd->CommonCfg.ExtRate[0];
3002 SupRateLen = pAd->CommonCfg.SupRateLen;
3003 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3006 // find max supported rate
3007 for (i=0; i<SupRateLen; i++)
3009 switch (pSupRate[i] & 0x7f)
3011 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3012 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3013 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3014 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3015 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3016 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3017 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3018 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3019 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3020 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3021 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3022 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3023 default: Rate = RATE_1; break;
3025 if (MaxSupport < Rate) MaxSupport = Rate;
3027 if (MinSupport > Rate) MinSupport = Rate;
3030 for (i=0; i<ExtRateLen; i++)
3032 switch (pExtRate[i] & 0x7f)
3034 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3035 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3036 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3037 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3038 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3039 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3040 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3041 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3042 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3043 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3044 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3045 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3046 default: Rate = RATE_1; break;
3048 if (MaxSupport < Rate) MaxSupport = Rate;
3050 if (MinSupport > Rate) MinSupport = Rate;
3053 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3055 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3056 // the DURATION field of outgoing uniicast DATA/MGMT frame
3057 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3059 if (BasicRateBitmap & (0x01 << i))
3060 CurrBasicRate = (UCHAR)i;
3061 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3064 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3065 // max tx rate = min {max desire rate, max supported rate}
3066 if (MaxSupport < MaxDesire)
3067 pAd->CommonCfg.MaxTxRate = MaxSupport;
3068 else
3069 pAd->CommonCfg.MaxTxRate = MaxDesire;
3071 pAd->CommonCfg.MinTxRate = MinSupport;
3072 if (*auto_rate_cur_p)
3074 short dbm = 0;
3076 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3078 if (bLinkUp == TRUE)
3079 pAd->CommonCfg.TxRate = RATE_24;
3080 else
3081 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3083 if (dbm < -75)
3084 pAd->CommonCfg.TxRate = RATE_11;
3085 else if (dbm < -70)
3086 pAd->CommonCfg.TxRate = RATE_24;
3088 // should never exceed MaxTxRate (consider 11B-only mode)
3089 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3090 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3092 pAd->CommonCfg.TxRateIndex = 0;
3094 else
3096 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3097 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3098 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3100 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3101 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3102 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3103 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3106 if (pAd->CommonCfg.TxRate <= RATE_11)
3108 pMaxHtPhy->field.MODE = MODE_CCK;
3109 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3110 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3112 else
3114 pMaxHtPhy->field.MODE = MODE_OFDM;
3115 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3116 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3117 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3118 else
3119 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3122 pHtPhy->word = (pMaxHtPhy->word);
3123 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3125 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3126 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3127 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3129 else
3131 switch (pAd->CommonCfg.PhyMode)
3133 case PHY_11BG_MIXED:
3134 case PHY_11B:
3135 case PHY_11BGN_MIXED:
3136 pAd->CommonCfg.MlmeRate = RATE_1;
3137 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3138 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3139 pAd->CommonCfg.RtsRate = RATE_11;
3140 break;
3141 case PHY_11G:
3142 case PHY_11A:
3143 case PHY_11AGN_MIXED:
3144 case PHY_11GN_MIXED:
3145 case PHY_11N_2_4G:
3146 case PHY_11AN_MIXED:
3147 case PHY_11N_5G:
3148 pAd->CommonCfg.MlmeRate = RATE_6;
3149 pAd->CommonCfg.RtsRate = RATE_6;
3150 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3151 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3152 break;
3153 case PHY_11ABG_MIXED:
3154 case PHY_11ABGN_MIXED:
3155 if (pAd->CommonCfg.Channel <= 14)
3157 pAd->CommonCfg.MlmeRate = RATE_1;
3158 pAd->CommonCfg.RtsRate = RATE_1;
3159 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3160 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3162 else
3164 pAd->CommonCfg.MlmeRate = RATE_6;
3165 pAd->CommonCfg.RtsRate = RATE_6;
3166 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3167 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3169 break;
3170 default: // error
3171 pAd->CommonCfg.MlmeRate = RATE_6;
3172 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3173 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3174 pAd->CommonCfg.RtsRate = RATE_1;
3175 break;
3178 // Keep Basic Mlme Rate.
3180 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3181 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3182 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3183 else
3184 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3185 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3188 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3189 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3190 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3191 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3192 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3193 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3194 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 ));
3198 ==========================================================================
3199 Description:
3200 This function update HT Rate setting.
3201 Input Wcid value is valid for 2 case :
3202 1. it's used for Station in infra mode that copy AP rate to Mactable.
3203 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3205 IRQL = DISPATCH_LEVEL
3207 ==========================================================================
3209 VOID MlmeUpdateHtTxRates(
3210 IN PRTMP_ADAPTER pAd,
3211 IN UCHAR apidx)
3213 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3214 CHAR i; // 3*3
3215 RT_HT_CAPABILITY *pRtHtCap = NULL;
3216 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3217 ULONG BasicMCS;
3218 UCHAR j, bitmask;
3219 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3220 PHTTRANSMIT_SETTING pHtPhy = NULL;
3221 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3222 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3223 BOOLEAN *auto_rate_cur_p;
3225 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3227 auto_rate_cur_p = NULL;
3230 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3231 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3232 pHtPhy = &pAd->StaCfg.HTPhyMode;
3233 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3234 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3236 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3239 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3241 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3242 return;
3244 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3245 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3246 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3247 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3248 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3249 pMaxHtPhy->field.STBC = STBC_USE;
3250 else
3251 pMaxHtPhy->field.STBC = STBC_NONE;
3253 else
3255 if (pDesireHtPhy->bHtEnable == FALSE)
3256 return;
3258 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3259 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3260 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3261 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3262 pMaxHtPhy->field.STBC = STBC_USE;
3263 else
3264 pMaxHtPhy->field.STBC = STBC_NONE;
3267 // Decide MAX ht rate.
3268 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3269 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3270 else
3271 pMaxHtPhy->field.MODE = MODE_HTMIX;
3273 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3274 pMaxHtPhy->field.BW = BW_40;
3275 else
3276 pMaxHtPhy->field.BW = BW_20;
3278 if (pMaxHtPhy->field.BW == BW_20)
3279 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3280 else
3281 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3283 for (i=23; i>=0; i--) // 3*3
3285 j = i/8;
3286 bitmask = (1<<(i-(j*8)));
3288 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3290 pMaxHtPhy->field.MCS = i;
3291 break;
3294 if (i==0)
3295 break;
3298 // Copy MIN ht rate. rt2860???
3299 pMinHtPhy->field.BW = BW_20;
3300 pMinHtPhy->field.MCS = 0;
3301 pMinHtPhy->field.STBC = 0;
3302 pMinHtPhy->field.ShortGI = 0;
3303 //If STA assigns fixed rate. update to fixed here.
3304 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3306 if (pDesireHtPhy->MCSSet[4] != 0)
3308 pMaxHtPhy->field.MCS = 32;
3309 pMinHtPhy->field.MCS = 32;
3310 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3313 for (i=23; (CHAR)i >= 0; i--) // 3*3
3315 j = i/8;
3316 bitmask = (1<<(i-(j*8)));
3317 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3319 pMaxHtPhy->field.MCS = i;
3320 pMinHtPhy->field.MCS = i;
3321 break;
3323 if (i==0)
3324 break;
3328 // Decide ht rate
3329 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3330 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3331 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3332 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3333 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3335 // use default now. rt2860
3336 if (pDesireHtPhy->MCSSet[0] != 0xff)
3337 *auto_rate_cur_p = FALSE;
3338 else
3339 *auto_rate_cur_p = TRUE;
3341 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3342 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3343 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3344 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3347 // IRQL = DISPATCH_LEVEL
3348 VOID MlmeRadioOff(
3349 IN PRTMP_ADAPTER pAd)
3351 RT28XX_MLME_RADIO_OFF(pAd);
3354 // IRQL = DISPATCH_LEVEL
3355 VOID MlmeRadioOn(
3356 IN PRTMP_ADAPTER pAd)
3358 RT28XX_MLME_RADIO_ON(pAd);
3361 // ===========================================================================================
3362 // bss_table.c
3363 // ===========================================================================================
3366 /*! \brief initialize BSS table
3367 * \param p_tab pointer to the table
3368 * \return none
3369 * \pre
3370 * \post
3372 IRQL = PASSIVE_LEVEL
3373 IRQL = DISPATCH_LEVEL
3376 VOID BssTableInit(
3377 IN BSS_TABLE *Tab)
3379 int i;
3381 Tab->BssNr = 0;
3382 Tab->BssOverlapNr = 0;
3383 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3385 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3386 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3390 VOID BATableInit(
3391 IN PRTMP_ADAPTER pAd,
3392 IN BA_TABLE *Tab)
3394 int i;
3396 Tab->numAsOriginator = 0;
3397 Tab->numAsRecipient = 0;
3398 NdisAllocateSpinLock(&pAd->BATabLock);
3399 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3401 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3402 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3404 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3406 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3410 /*! \brief search the BSS table by SSID
3411 * \param p_tab pointer to the bss table
3412 * \param ssid SSID string
3413 * \return index of the table, BSS_NOT_FOUND if not in the table
3414 * \pre
3415 * \post
3416 * \note search by sequential search
3418 IRQL = DISPATCH_LEVEL
3421 ULONG BssTableSearch(
3422 IN BSS_TABLE *Tab,
3423 IN PUCHAR pBssid,
3424 IN UCHAR Channel)
3426 UCHAR i;
3428 for (i = 0; i < Tab->BssNr; i++)
3431 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3432 // We should distinguish this case.
3434 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3435 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3436 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3438 return i;
3441 return (ULONG)BSS_NOT_FOUND;
3444 ULONG BssSsidTableSearch(
3445 IN BSS_TABLE *Tab,
3446 IN PUCHAR pBssid,
3447 IN PUCHAR pSsid,
3448 IN UCHAR SsidLen,
3449 IN UCHAR Channel)
3451 UCHAR i;
3453 for (i = 0; i < Tab->BssNr; i++)
3456 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3457 // We should distinguish this case.
3459 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3460 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3461 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3462 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3464 return i;
3467 return (ULONG)BSS_NOT_FOUND;
3470 ULONG BssTableSearchWithSSID(
3471 IN BSS_TABLE *Tab,
3472 IN PUCHAR Bssid,
3473 IN PUCHAR pSsid,
3474 IN UCHAR SsidLen,
3475 IN UCHAR Channel)
3477 UCHAR i;
3479 for (i = 0; i < Tab->BssNr; i++)
3481 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3482 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3483 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3484 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3485 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3486 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3488 return i;
3491 return (ULONG)BSS_NOT_FOUND;
3494 // IRQL = DISPATCH_LEVEL
3495 VOID BssTableDeleteEntry(
3496 IN OUT BSS_TABLE *Tab,
3497 IN PUCHAR pBssid,
3498 IN UCHAR Channel)
3500 UCHAR i, j;
3502 for (i = 0; i < Tab->BssNr; i++)
3504 if ((Tab->BssEntry[i].Channel == Channel) &&
3505 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3507 for (j = i; j < Tab->BssNr - 1; j++)
3509 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3511 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3512 Tab->BssNr -= 1;
3513 return;
3519 ========================================================================
3520 Routine Description:
3521 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3523 Arguments:
3524 // IRQL = DISPATCH_LEVEL
3525 ========================================================================
3527 VOID BATableDeleteORIEntry(
3528 IN OUT PRTMP_ADAPTER pAd,
3529 IN BA_ORI_ENTRY *pBAORIEntry)
3532 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3534 NdisAcquireSpinLock(&pAd->BATabLock);
3535 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3537 pAd->BATable.numAsOriginator -= 1;
3538 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3539 // Erase Bitmap flag.
3541 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3542 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3543 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3544 pBAORIEntry->Token = 1;
3545 // Not clear Sequence here.
3546 NdisReleaseSpinLock(&pAd->BATabLock);
3550 /*! \brief
3551 * \param
3552 * \return
3553 * \pre
3554 * \post
3556 IRQL = DISPATCH_LEVEL
3559 VOID BssEntrySet(
3560 IN PRTMP_ADAPTER pAd,
3561 OUT BSS_ENTRY *pBss,
3562 IN PUCHAR pBssid,
3563 IN CHAR Ssid[],
3564 IN UCHAR SsidLen,
3565 IN UCHAR BssType,
3566 IN USHORT BeaconPeriod,
3567 IN PCF_PARM pCfParm,
3568 IN USHORT AtimWin,
3569 IN USHORT CapabilityInfo,
3570 IN UCHAR SupRate[],
3571 IN UCHAR SupRateLen,
3572 IN UCHAR ExtRate[],
3573 IN UCHAR ExtRateLen,
3574 IN HT_CAPABILITY_IE *pHtCapability,
3575 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3576 IN UCHAR HtCapabilityLen,
3577 IN UCHAR AddHtInfoLen,
3578 IN UCHAR NewExtChanOffset,
3579 IN UCHAR Channel,
3580 IN CHAR Rssi,
3581 IN LARGE_INTEGER TimeStamp,
3582 IN UCHAR CkipFlag,
3583 IN PEDCA_PARM pEdcaParm,
3584 IN PQOS_CAPABILITY_PARM pQosCapability,
3585 IN PQBSS_LOAD_PARM pQbssLoad,
3586 IN USHORT LengthVIE,
3587 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3589 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3590 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3591 pBss->Hidden = 1;
3592 if (SsidLen > 0)
3594 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3595 // Or send beacon /probe response with SSID len matching real SSID length,
3596 // but SSID is all zero. such as "00-00-00-00" with length 4.
3597 // We have to prevent this case overwrite correct table
3598 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3600 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3601 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3602 pBss->SsidLen = SsidLen;
3603 pBss->Hidden = 0;
3606 else
3607 pBss->SsidLen = 0;
3608 pBss->BssType = BssType;
3609 pBss->BeaconPeriod = BeaconPeriod;
3610 if (BssType == BSS_INFRA)
3612 if (pCfParm->bValid)
3614 pBss->CfpCount = pCfParm->CfpCount;
3615 pBss->CfpPeriod = pCfParm->CfpPeriod;
3616 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3617 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3620 else
3622 pBss->AtimWin = AtimWin;
3625 pBss->CapabilityInfo = CapabilityInfo;
3626 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3627 // Combine with AuthMode, they will decide the connection methods.
3628 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3629 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3630 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3631 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3632 else
3633 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3634 pBss->SupRateLen = SupRateLen;
3635 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3636 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3637 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3638 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3639 pBss->NewExtChanOffset = NewExtChanOffset;
3640 pBss->ExtRateLen = ExtRateLen;
3641 pBss->Channel = Channel;
3642 pBss->CentralChannel = Channel;
3643 pBss->Rssi = Rssi;
3644 // Update CkipFlag. if not exists, the value is 0x0
3645 pBss->CkipFlag = CkipFlag;
3647 // New for microsoft Fixed IEs
3648 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3649 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3650 pBss->FixIEs.Capabilities = CapabilityInfo;
3652 // New for microsoft Variable IEs
3653 if (LengthVIE != 0)
3655 pBss->VarIELen = LengthVIE;
3656 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3658 else
3660 pBss->VarIELen = 0;
3663 pBss->AddHtInfoLen = 0;
3664 pBss->HtCapabilityLen = 0;
3666 if (HtCapabilityLen> 0)
3668 pBss->HtCapabilityLen = HtCapabilityLen;
3669 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3670 if (AddHtInfoLen > 0)
3672 pBss->AddHtInfoLen = AddHtInfoLen;
3673 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3675 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3677 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3679 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3681 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3686 BssCipherParse(pBss);
3688 // new for QOS
3689 if (pEdcaParm)
3690 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3691 else
3692 pBss->EdcaParm.bValid = FALSE;
3693 if (pQosCapability)
3694 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3695 else
3696 pBss->QosCapability.bValid = FALSE;
3697 if (pQbssLoad)
3698 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3699 else
3700 pBss->QbssLoad.bValid = FALSE;
3703 PEID_STRUCT pEid;
3704 USHORT Length = 0;
3707 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3708 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3710 pEid = (PEID_STRUCT) pVIE;
3712 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3714 switch(pEid->Eid)
3716 case IE_WPA:
3717 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3719 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3721 pBss->WpaIE.IELen = 0;
3722 break;
3724 pBss->WpaIE.IELen = pEid->Len + 2;
3725 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3727 break;
3728 case IE_RSN:
3729 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3731 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3733 pBss->RsnIE.IELen = 0;
3734 break;
3736 pBss->RsnIE.IELen = pEid->Len + 2;
3737 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3739 break;
3741 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3742 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3748 * \brief insert an entry into the bss table
3749 * \param p_tab The BSS table
3750 * \param Bssid BSSID
3751 * \param ssid SSID
3752 * \param ssid_len Length of SSID
3753 * \param bss_type
3754 * \param beacon_period
3755 * \param timestamp
3756 * \param p_cf
3757 * \param atim_win
3758 * \param cap
3759 * \param rates
3760 * \param rates_len
3761 * \param channel_idx
3762 * \return none
3763 * \pre
3764 * \post
3765 * \note If SSID is identical, the old entry will be replaced by the new one
3767 IRQL = DISPATCH_LEVEL
3770 ULONG BssTableSetEntry(
3771 IN PRTMP_ADAPTER pAd,
3772 OUT BSS_TABLE *Tab,
3773 IN PUCHAR pBssid,
3774 IN CHAR Ssid[],
3775 IN UCHAR SsidLen,
3776 IN UCHAR BssType,
3777 IN USHORT BeaconPeriod,
3778 IN CF_PARM *CfParm,
3779 IN USHORT AtimWin,
3780 IN USHORT CapabilityInfo,
3781 IN UCHAR SupRate[],
3782 IN UCHAR SupRateLen,
3783 IN UCHAR ExtRate[],
3784 IN UCHAR ExtRateLen,
3785 IN HT_CAPABILITY_IE *pHtCapability,
3786 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3787 IN UCHAR HtCapabilityLen,
3788 IN UCHAR AddHtInfoLen,
3789 IN UCHAR NewExtChanOffset,
3790 IN UCHAR ChannelNo,
3791 IN CHAR Rssi,
3792 IN LARGE_INTEGER TimeStamp,
3793 IN UCHAR CkipFlag,
3794 IN PEDCA_PARM pEdcaParm,
3795 IN PQOS_CAPABILITY_PARM pQosCapability,
3796 IN PQBSS_LOAD_PARM pQbssLoad,
3797 IN USHORT LengthVIE,
3798 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3800 ULONG Idx;
3802 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3803 if (Idx == BSS_NOT_FOUND)
3805 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3808 // It may happen when BSS Table was full.
3809 // The desired AP will not be added into BSS Table
3810 // In this case, if we found the desired AP then overwrite BSS Table.
3812 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3814 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3815 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3817 Idx = Tab->BssOverlapNr;
3818 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3819 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3820 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3821 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3823 return Idx;
3825 else
3827 return BSS_NOT_FOUND;
3830 Idx = Tab->BssNr;
3831 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3832 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3833 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3834 Tab->BssNr++;
3836 else
3838 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3839 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3840 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3842 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3843 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3844 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3848 return Idx;
3851 // IRQL = DISPATCH_LEVEL
3852 VOID BssTableSsidSort(
3853 IN PRTMP_ADAPTER pAd,
3854 OUT BSS_TABLE *OutTab,
3855 IN CHAR Ssid[],
3856 IN UCHAR SsidLen)
3858 INT i;
3859 BssTableInit(OutTab);
3861 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3863 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3864 BOOLEAN bIsHiddenApIncluded = FALSE;
3866 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3867 (pAd->MlmeAux.Channel > 14) &&
3868 RadarChannelCheck(pAd, pInBss->Channel))
3871 if (pInBss->Hidden)
3872 bIsHiddenApIncluded = TRUE;
3875 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3876 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3878 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3880 // 2.4G/5G N only mode
3881 if ((pInBss->HtCapabilityLen == 0) &&
3882 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3884 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3885 continue;
3888 // New for WPA2
3889 // Check the Authmode first
3890 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3892 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3893 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3894 // None matched
3895 continue;
3897 // Check cipher suite, AP must have more secured cipher than station setting
3898 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3900 // If it's not mixed mode, we should only let BSS pass with the same encryption
3901 if (pInBss->WPA.bMixMode == FALSE)
3902 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3903 continue;
3905 // check group cipher
3906 if (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3907 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3908 pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3909 continue;
3911 // check pairwise cipher, skip if none matched
3912 // If profile set to AES, let it pass without question.
3913 // If profile set to TKIP, we must find one mateched
3914 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3915 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3916 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3917 continue;
3919 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3921 // If it's not mixed mode, we should only let BSS pass with the same encryption
3922 if (pInBss->WPA2.bMixMode == FALSE)
3923 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3924 continue;
3926 // check group cipher
3927 if (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3928 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3929 pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3930 continue;
3932 // check pairwise cipher, skip if none matched
3933 // If profile set to AES, let it pass without question.
3934 // If profile set to TKIP, we must find one mateched
3935 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3936 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3937 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3938 continue;
3941 // Bss Type matched, SSID matched.
3942 // We will check wepstatus for qualification Bss
3943 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3945 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3947 // For the SESv2 case, we will not qualify WepStatus.
3949 if (!pInBss->bSES)
3950 continue;
3953 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3954 // It definitely will fail. So, skip it.
3955 // CCX also require not even try to connect it!!
3956 if (SsidLen == 0)
3957 continue;
3959 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3960 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3961 if ((pInBss->CentralChannel != pInBss->Channel) &&
3962 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3964 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3966 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3967 SetCommonHT(pAd);
3968 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3970 else
3972 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3974 SetCommonHT(pAd);
3979 // copy matching BSS from InTab to OutTab
3980 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3982 OutTab->BssNr++;
3984 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3986 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3988 // 2.4G/5G N only mode
3989 if ((pInBss->HtCapabilityLen == 0) &&
3990 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3992 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3993 continue;
3996 // New for WPA2
3997 // Check the Authmode first
3998 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4000 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4001 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4002 // None matched
4003 continue;
4005 // Check cipher suite, AP must have more secured cipher than station setting
4006 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4008 // If it's not mixed mode, we should only let BSS pass with the same encryption
4009 if (pInBss->WPA.bMixMode == FALSE)
4010 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4011 continue;
4013 // check group cipher
4014 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4015 continue;
4017 // check pairwise cipher, skip if none matched
4018 // If profile set to AES, let it pass without question.
4019 // If profile set to TKIP, we must find one mateched
4020 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4021 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4022 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4023 continue;
4025 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4027 // If it's not mixed mode, we should only let BSS pass with the same encryption
4028 if (pInBss->WPA2.bMixMode == FALSE)
4029 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4030 continue;
4032 // check group cipher
4033 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4034 continue;
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->WPA2.PairCipher) &&
4041 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4042 continue;
4045 // Bss Type matched, SSID matched.
4046 // We will check wepstatus for qualification Bss
4047 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4048 continue;
4050 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4051 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4052 if ((pInBss->CentralChannel != pInBss->Channel) &&
4053 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4055 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4057 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4058 SetCommonHT(pAd);
4059 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4063 // copy matching BSS from InTab to OutTab
4064 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4066 OutTab->BssNr++;
4069 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4070 break;
4073 BssTableSortByRssi(OutTab);
4077 // IRQL = DISPATCH_LEVEL
4078 VOID BssTableSortByRssi(
4079 IN OUT BSS_TABLE *OutTab)
4081 INT i, j;
4082 BSS_ENTRY TmpBss;
4084 for (i = 0; i < OutTab->BssNr - 1; i++)
4086 for (j = i+1; j < OutTab->BssNr; j++)
4088 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4090 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4091 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4092 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4098 VOID BssCipherParse(
4099 IN OUT PBSS_ENTRY pBss)
4101 PEID_STRUCT pEid;
4102 PUCHAR pTmp;
4103 PRSN_IE_HEADER_STRUCT pRsnHeader;
4104 PCIPHER_SUITE_STRUCT pCipher;
4105 PAKM_SUITE_STRUCT pAKM;
4106 USHORT Count;
4107 INT Length;
4108 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4111 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4113 if (pBss->Privacy)
4115 pBss->WepStatus = Ndis802_11WEPEnabled;
4117 else
4119 pBss->WepStatus = Ndis802_11WEPDisabled;
4121 // Set default to disable & open authentication before parsing variable IE
4122 pBss->AuthMode = Ndis802_11AuthModeOpen;
4123 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4125 // Init WPA setting
4126 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4127 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4128 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4129 pBss->WPA.RsnCapability = 0;
4130 pBss->WPA.bMixMode = FALSE;
4132 // Init WPA2 setting
4133 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4134 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4135 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4136 pBss->WPA2.RsnCapability = 0;
4137 pBss->WPA2.bMixMode = FALSE;
4140 Length = (INT) pBss->VarIELen;
4142 while (Length > 0)
4144 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4145 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4146 pEid = (PEID_STRUCT) pTmp;
4147 switch (pEid->Eid)
4149 case IE_WPA:
4150 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4151 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4153 pTmp += 11;
4154 switch (*pTmp)
4156 case 1:
4157 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4158 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4159 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4160 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4161 break;
4162 case 2:
4163 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4164 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4165 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4166 break;
4167 case 4:
4168 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4169 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4170 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4171 break;
4172 default:
4173 break;
4176 // if Cisco IE_WPA, break
4177 break;
4179 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4181 pBss->bSES = TRUE;
4182 break;
4184 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4186 // if unsupported vendor specific IE
4187 break;
4189 // Skip OUI, version, and multicast suite
4190 // This part should be improved in the future when AP supported multiple cipher suite.
4191 // For now, it's OK since almost all APs have fixed cipher suite supported.
4192 // pTmp = (PUCHAR) pEid->Octet;
4193 pTmp += 11;
4195 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4196 // Value Meaning
4197 // 0 None
4198 // 1 WEP-40
4199 // 2 Tkip
4200 // 3 WRAP
4201 // 4 AES
4202 // 5 WEP-104
4203 // Parse group cipher
4204 switch (*pTmp)
4206 case 1:
4207 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4208 break;
4209 case 5:
4210 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4211 break;
4212 case 2:
4213 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4214 break;
4215 case 4:
4216 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4217 break;
4218 default:
4219 break;
4221 // number of unicast suite
4222 pTmp += 1;
4224 // skip all unicast cipher suites
4225 //Count = *(PUSHORT) pTmp;
4226 Count = (pTmp[1]<<8) + pTmp[0];
4227 pTmp += sizeof(USHORT);
4229 // Parsing all unicast cipher suite
4230 while (Count > 0)
4232 // Skip OUI
4233 pTmp += 3;
4234 TmpCipher = Ndis802_11WEPDisabled;
4235 switch (*pTmp)
4237 case 1:
4238 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4239 TmpCipher = Ndis802_11Encryption1Enabled;
4240 break;
4241 case 2:
4242 TmpCipher = Ndis802_11Encryption2Enabled;
4243 break;
4244 case 4:
4245 TmpCipher = Ndis802_11Encryption3Enabled;
4246 break;
4247 default:
4248 break;
4250 if (TmpCipher > pBss->WPA.PairCipher)
4252 // Move the lower cipher suite to PairCipherAux
4253 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4254 pBss->WPA.PairCipher = TmpCipher;
4256 else
4258 pBss->WPA.PairCipherAux = TmpCipher;
4260 pTmp++;
4261 Count--;
4264 // 4. get AKM suite counts
4265 //Count = *(PUSHORT) pTmp;
4266 Count = (pTmp[1]<<8) + pTmp[0];
4267 pTmp += sizeof(USHORT);
4268 pTmp += 3;
4270 switch (*pTmp)
4272 case 1:
4273 // Set AP support WPA mode
4274 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4275 pBss->AuthMode = Ndis802_11AuthModeWPA;
4276 else
4277 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4278 break;
4279 case 2:
4280 // Set AP support WPA mode
4281 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4282 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4283 else
4284 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4285 break;
4286 default:
4287 break;
4289 pTmp += 1;
4291 // Fixed for WPA-None
4292 if (pBss->BssType == BSS_ADHOC)
4294 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4295 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4296 pBss->WepStatus = pBss->WPA.GroupCipher;
4297 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4298 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4300 else
4301 pBss->WepStatus = pBss->WPA.PairCipher;
4303 // Check the Pair & Group, if different, turn on mixed mode flag
4304 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4305 pBss->WPA.bMixMode = TRUE;
4307 break;
4309 case IE_RSN:
4310 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4312 // 0. Version must be 1
4313 if (le2cpu16(pRsnHeader->Version) != 1)
4314 break;
4315 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4317 // 1. Check group cipher
4318 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4319 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4320 break;
4322 // Parse group cipher
4323 switch (pCipher->Type)
4325 case 1:
4326 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4327 break;
4328 case 5:
4329 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4330 break;
4331 case 2:
4332 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4333 break;
4334 case 4:
4335 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4336 break;
4337 default:
4338 break;
4340 // set to correct offset for next parsing
4341 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4343 // 2. Get pairwise cipher counts
4344 //Count = *(PUSHORT) pTmp;
4345 Count = (pTmp[1]<<8) + pTmp[0];
4346 pTmp += sizeof(USHORT);
4348 // 3. Get pairwise cipher
4349 // Parsing all unicast cipher suite
4350 while (Count > 0)
4352 // Skip OUI
4353 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4354 TmpCipher = Ndis802_11WEPDisabled;
4355 switch (pCipher->Type)
4357 case 1:
4358 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4359 TmpCipher = Ndis802_11Encryption1Enabled;
4360 break;
4361 case 2:
4362 TmpCipher = Ndis802_11Encryption2Enabled;
4363 break;
4364 case 4:
4365 TmpCipher = Ndis802_11Encryption3Enabled;
4366 break;
4367 default:
4368 break;
4370 if (TmpCipher > pBss->WPA2.PairCipher)
4372 // Move the lower cipher suite to PairCipherAux
4373 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4374 pBss->WPA2.PairCipher = TmpCipher;
4376 else
4378 pBss->WPA2.PairCipherAux = TmpCipher;
4380 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4381 Count--;
4384 // 4. get AKM suite counts
4385 //Count = *(PUSHORT) pTmp;
4386 Count = (pTmp[1]<<8) + pTmp[0];
4387 pTmp += sizeof(USHORT);
4389 // 5. Get AKM ciphers
4390 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4391 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4392 break;
4394 switch (pAKM->Type)
4396 case 1:
4397 // Set AP support WPA mode
4398 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4399 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4400 else
4401 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4402 break;
4403 case 2:
4404 // Set AP support WPA mode
4405 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4406 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4407 else
4408 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4409 break;
4410 default:
4411 break;
4413 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4415 // Fixed for WPA-None
4416 if (pBss->BssType == BSS_ADHOC)
4418 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4419 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4420 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4421 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4422 pBss->WepStatus = pBss->WPA.GroupCipher;
4423 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4424 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4426 pBss->WepStatus = pBss->WPA2.PairCipher;
4428 // 6. Get RSN capability
4429 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4430 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4431 pTmp += sizeof(USHORT);
4433 // Check the Pair & Group, if different, turn on mixed mode flag
4434 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4435 pBss->WPA2.bMixMode = TRUE;
4437 break;
4438 default:
4439 break;
4441 Length -= (pEid->Len + 2);
4445 // ===========================================================================================
4446 // mac_table.c
4447 // ===========================================================================================
4449 /*! \brief generates a random mac address value for IBSS BSSID
4450 * \param Addr the bssid location
4451 * \return none
4452 * \pre
4453 * \post
4455 VOID MacAddrRandomBssid(
4456 IN PRTMP_ADAPTER pAd,
4457 OUT PUCHAR pAddr)
4459 INT i;
4461 for (i = 0; i < MAC_ADDR_LEN; i++)
4463 pAddr[i] = RandomByte(pAd);
4466 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4469 /*! \brief init the management mac frame header
4470 * \param p_hdr mac header
4471 * \param subtype subtype of the frame
4472 * \param p_ds destination address, don't care if it is a broadcast address
4473 * \return none
4474 * \pre the station has the following information in the pAd->StaCfg
4475 * - bssid
4476 * - station address
4477 * \post
4478 * \note this function initializes the following field
4480 IRQL = PASSIVE_LEVEL
4481 IRQL = DISPATCH_LEVEL
4484 VOID MgtMacHeaderInit(
4485 IN PRTMP_ADAPTER pAd,
4486 IN OUT PHEADER_802_11 pHdr80211,
4487 IN UCHAR SubType,
4488 IN UCHAR ToDs,
4489 IN PUCHAR pDA,
4490 IN PUCHAR pBssid)
4492 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4494 pHdr80211->FC.Type = BTYPE_MGMT;
4495 pHdr80211->FC.SubType = SubType;
4496 pHdr80211->FC.ToDs = ToDs;
4497 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4499 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4501 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4504 // ===========================================================================================
4505 // mem_mgmt.c
4506 // ===========================================================================================
4508 /*!***************************************************************************
4509 * This routine build an outgoing frame, and fill all information specified
4510 * in argument list to the frame body. The actual frame size is the summation
4511 * of all arguments.
4512 * input params:
4513 * Buffer - pointer to a pre-allocated memory segment
4514 * args - a list of <int arg_size, arg> pairs.
4515 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4516 * function will FAIL!!!
4517 * return:
4518 * Size of the buffer
4519 * usage:
4520 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4522 IRQL = PASSIVE_LEVEL
4523 IRQL = DISPATCH_LEVEL
4525 ****************************************************************************/
4526 ULONG MakeOutgoingFrame(
4527 OUT CHAR *Buffer,
4528 OUT ULONG *FrameLen, ...)
4530 CHAR *p;
4531 int leng;
4532 ULONG TotLeng;
4533 va_list Args;
4535 // calculates the total length
4536 TotLeng = 0;
4537 va_start(Args, FrameLen);
4540 leng = va_arg(Args, int);
4541 if (leng == END_OF_ARGS)
4543 break;
4545 p = va_arg(Args, PVOID);
4546 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4547 TotLeng = TotLeng + leng;
4548 } while(TRUE);
4550 va_end(Args); /* clean up */
4551 *FrameLen = TotLeng;
4552 return TotLeng;
4555 // ===========================================================================================
4556 // mlme_queue.c
4557 // ===========================================================================================
4559 /*! \brief Initialize The MLME Queue, used by MLME Functions
4560 * \param *Queue The MLME Queue
4561 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4562 * \pre
4563 * \post
4564 * \note Because this is done only once (at the init stage), no need to be locked
4566 IRQL = PASSIVE_LEVEL
4569 NDIS_STATUS MlmeQueueInit(
4570 IN MLME_QUEUE *Queue)
4572 INT i;
4574 NdisAllocateSpinLock(&Queue->Lock);
4576 Queue->Num = 0;
4577 Queue->Head = 0;
4578 Queue->Tail = 0;
4580 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4582 Queue->Entry[i].Occupied = FALSE;
4583 Queue->Entry[i].MsgLen = 0;
4584 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4587 return NDIS_STATUS_SUCCESS;
4590 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4591 * \param *Queue The MLME Queue
4592 * \param Machine The State Machine Id
4593 * \param MsgType The Message Type
4594 * \param MsgLen The Message length
4595 * \param *Msg The message pointer
4596 * \return TRUE if enqueue is successful, FALSE if the queue is full
4597 * \pre
4598 * \post
4599 * \note The message has to be initialized
4601 IRQL = PASSIVE_LEVEL
4602 IRQL = DISPATCH_LEVEL
4605 BOOLEAN MlmeEnqueue(
4606 IN PRTMP_ADAPTER pAd,
4607 IN ULONG Machine,
4608 IN ULONG MsgType,
4609 IN ULONG MsgLen,
4610 IN VOID *Msg)
4612 INT Tail;
4613 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4615 // Do nothing if the driver is starting halt state.
4616 // This might happen when timer already been fired before cancel timer with mlmehalt
4617 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4618 return FALSE;
4620 // First check the size, it MUST not exceed the mlme queue size
4621 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4623 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4624 return FALSE;
4627 if (MlmeQueueFull(Queue))
4629 return FALSE;
4632 NdisAcquireSpinLock(&(Queue->Lock));
4633 Tail = Queue->Tail;
4634 Queue->Tail++;
4635 Queue->Num++;
4636 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4638 Queue->Tail = 0;
4641 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4642 Queue->Entry[Tail].Occupied = TRUE;
4643 Queue->Entry[Tail].Machine = Machine;
4644 Queue->Entry[Tail].MsgType = MsgType;
4645 Queue->Entry[Tail].MsgLen = MsgLen;
4647 if (Msg != NULL)
4649 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4652 NdisReleaseSpinLock(&(Queue->Lock));
4653 return TRUE;
4656 /*! \brief This function is used when Recv gets a MLME message
4657 * \param *Queue The MLME Queue
4658 * \param TimeStampHigh The upper 32 bit of timestamp
4659 * \param TimeStampLow The lower 32 bit of timestamp
4660 * \param Rssi The receiving RSSI strength
4661 * \param MsgLen The length of the message
4662 * \param *Msg The message pointer
4663 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4664 * \pre
4665 * \post
4667 IRQL = DISPATCH_LEVEL
4670 BOOLEAN MlmeEnqueueForRecv(
4671 IN PRTMP_ADAPTER pAd,
4672 IN ULONG Wcid,
4673 IN ULONG TimeStampHigh,
4674 IN ULONG TimeStampLow,
4675 IN UCHAR Rssi0,
4676 IN UCHAR Rssi1,
4677 IN UCHAR Rssi2,
4678 IN ULONG MsgLen,
4679 IN VOID *Msg,
4680 IN UCHAR Signal)
4682 INT Tail, Machine;
4683 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4684 INT MsgType;
4685 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4687 // Do nothing if the driver is starting halt state.
4688 // This might happen when timer already been fired before cancel timer with mlmehalt
4689 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4691 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4692 return FALSE;
4695 // First check the size, it MUST not exceed the mlme queue size
4696 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4698 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4699 return FALSE;
4702 if (MlmeQueueFull(Queue))
4704 return FALSE;
4708 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4710 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4711 return FALSE;
4715 // OK, we got all the informations, it is time to put things into queue
4716 NdisAcquireSpinLock(&(Queue->Lock));
4717 Tail = Queue->Tail;
4718 Queue->Tail++;
4719 Queue->Num++;
4720 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4722 Queue->Tail = 0;
4724 Queue->Entry[Tail].Occupied = TRUE;
4725 Queue->Entry[Tail].Machine = Machine;
4726 Queue->Entry[Tail].MsgType = MsgType;
4727 Queue->Entry[Tail].MsgLen = MsgLen;
4728 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4729 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4730 Queue->Entry[Tail].Rssi0 = Rssi0;
4731 Queue->Entry[Tail].Rssi1 = Rssi1;
4732 Queue->Entry[Tail].Rssi2 = Rssi2;
4733 Queue->Entry[Tail].Signal = Signal;
4734 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4736 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4738 if (Msg != NULL)
4740 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4743 NdisReleaseSpinLock(&(Queue->Lock));
4745 RT28XX_MLME_HANDLER(pAd);
4747 return TRUE;
4751 /*! \brief Dequeue a message from the MLME Queue
4752 * \param *Queue The MLME Queue
4753 * \param *Elem The message dequeued from MLME Queue
4754 * \return TRUE if the Elem contains something, FALSE otherwise
4755 * \pre
4756 * \post
4758 IRQL = DISPATCH_LEVEL
4761 BOOLEAN MlmeDequeue(
4762 IN MLME_QUEUE *Queue,
4763 OUT MLME_QUEUE_ELEM **Elem)
4765 NdisAcquireSpinLock(&(Queue->Lock));
4766 *Elem = &(Queue->Entry[Queue->Head]);
4767 Queue->Num--;
4768 Queue->Head++;
4769 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4771 Queue->Head = 0;
4773 NdisReleaseSpinLock(&(Queue->Lock));
4774 return TRUE;
4777 // IRQL = DISPATCH_LEVEL
4778 VOID MlmeRestartStateMachine(
4779 IN PRTMP_ADAPTER pAd)
4781 #ifdef RT2860
4782 MLME_QUEUE_ELEM *Elem = NULL;
4783 #endif
4784 BOOLEAN Cancelled;
4786 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4788 #ifdef RT2860
4789 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4790 if(pAd->Mlme.bRunning)
4792 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4793 return;
4795 else
4797 pAd->Mlme.bRunning = TRUE;
4799 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4801 // Remove all Mlme queues elements
4802 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4804 //From message type, determine which state machine I should drive
4805 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4807 // free MLME element
4808 Elem->Occupied = FALSE;
4809 Elem->MsgLen = 0;
4812 else {
4813 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4816 #endif /* RT2860 */
4819 // Cancel all timer events
4820 // Be careful to cancel new added timer
4821 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4822 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4823 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4824 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4825 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4826 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4829 // Change back to original channel in case of doing scan
4830 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4831 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4833 // Resume MSDU which is turned off durning scan
4834 RTMPResumeMsduTransmission(pAd);
4837 // Set all state machines back IDLE
4838 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4839 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4840 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4841 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4842 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4843 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4846 #ifdef RT2860
4847 // Remove running state
4848 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4849 pAd->Mlme.bRunning = FALSE;
4850 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4851 #endif
4854 /*! \brief test if the MLME Queue is empty
4855 * \param *Queue The MLME Queue
4856 * \return TRUE if the Queue is empty, FALSE otherwise
4857 * \pre
4858 * \post
4860 IRQL = DISPATCH_LEVEL
4863 BOOLEAN MlmeQueueEmpty(
4864 IN MLME_QUEUE *Queue)
4866 BOOLEAN Ans;
4868 NdisAcquireSpinLock(&(Queue->Lock));
4869 Ans = (Queue->Num == 0);
4870 NdisReleaseSpinLock(&(Queue->Lock));
4872 return Ans;
4875 /*! \brief test if the MLME Queue is full
4876 * \param *Queue The MLME Queue
4877 * \return TRUE if the Queue is empty, FALSE otherwise
4878 * \pre
4879 * \post
4881 IRQL = PASSIVE_LEVEL
4882 IRQL = DISPATCH_LEVEL
4885 BOOLEAN MlmeQueueFull(
4886 IN MLME_QUEUE *Queue)
4888 BOOLEAN Ans;
4890 NdisAcquireSpinLock(&(Queue->Lock));
4891 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4892 NdisReleaseSpinLock(&(Queue->Lock));
4894 return Ans;
4897 /*! \brief The destructor of MLME Queue
4898 * \param
4899 * \return
4900 * \pre
4901 * \post
4902 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4904 IRQL = PASSIVE_LEVEL
4907 VOID MlmeQueueDestroy(
4908 IN MLME_QUEUE *pQueue)
4910 NdisAcquireSpinLock(&(pQueue->Lock));
4911 pQueue->Num = 0;
4912 pQueue->Head = 0;
4913 pQueue->Tail = 0;
4914 NdisReleaseSpinLock(&(pQueue->Lock));
4915 NdisFreeSpinLock(&(pQueue->Lock));
4918 /*! \brief To substitute the message type if the message is coming from external
4919 * \param pFrame The frame received
4920 * \param *Machine The state machine
4921 * \param *MsgType the message type for the state machine
4922 * \return TRUE if the substitution is successful, FALSE otherwise
4923 * \pre
4924 * \post
4926 IRQL = DISPATCH_LEVEL
4929 BOOLEAN MsgTypeSubst(
4930 IN PRTMP_ADAPTER pAd,
4931 IN PFRAME_802_11 pFrame,
4932 OUT INT *Machine,
4933 OUT INT *MsgType)
4935 USHORT Seq;
4936 UCHAR EAPType;
4937 PUCHAR pData;
4939 // Pointer to start of data frames including SNAP header
4940 pData = (PUCHAR) pFrame + LENGTH_802_11;
4942 // The only data type will pass to this function is EAPOL frame
4943 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4945 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4947 // Cisco Aironet SNAP header
4948 *Machine = AIRONET_STATE_MACHINE;
4949 *MsgType = MT2_AIRONET_MSG;
4950 return (TRUE);
4953 *Machine = WPA_PSK_STATE_MACHINE;
4954 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4955 return(WpaMsgTypeSubst(EAPType, MsgType));
4959 switch (pFrame->Hdr.FC.SubType)
4961 case SUBTYPE_ASSOC_REQ:
4962 *Machine = ASSOC_STATE_MACHINE;
4963 *MsgType = MT2_PEER_ASSOC_REQ;
4964 break;
4965 case SUBTYPE_ASSOC_RSP:
4966 *Machine = ASSOC_STATE_MACHINE;
4967 *MsgType = MT2_PEER_ASSOC_RSP;
4968 break;
4969 case SUBTYPE_REASSOC_REQ:
4970 *Machine = ASSOC_STATE_MACHINE;
4971 *MsgType = MT2_PEER_REASSOC_REQ;
4972 break;
4973 case SUBTYPE_REASSOC_RSP:
4974 *Machine = ASSOC_STATE_MACHINE;
4975 *MsgType = MT2_PEER_REASSOC_RSP;
4976 break;
4977 case SUBTYPE_PROBE_REQ:
4978 *Machine = SYNC_STATE_MACHINE;
4979 *MsgType = MT2_PEER_PROBE_REQ;
4980 break;
4981 case SUBTYPE_PROBE_RSP:
4982 *Machine = SYNC_STATE_MACHINE;
4983 *MsgType = MT2_PEER_PROBE_RSP;
4984 break;
4985 case SUBTYPE_BEACON:
4986 *Machine = SYNC_STATE_MACHINE;
4987 *MsgType = MT2_PEER_BEACON;
4988 break;
4989 case SUBTYPE_ATIM:
4990 *Machine = SYNC_STATE_MACHINE;
4991 *MsgType = MT2_PEER_ATIM;
4992 break;
4993 case SUBTYPE_DISASSOC:
4994 *Machine = ASSOC_STATE_MACHINE;
4995 *MsgType = MT2_PEER_DISASSOC_REQ;
4996 break;
4997 case SUBTYPE_AUTH:
4998 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4999 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5000 if (Seq == 1 || Seq == 3)
5002 *Machine = AUTH_RSP_STATE_MACHINE;
5003 *MsgType = MT2_PEER_AUTH_ODD;
5005 else if (Seq == 2 || Seq == 4)
5007 *Machine = AUTH_STATE_MACHINE;
5008 *MsgType = MT2_PEER_AUTH_EVEN;
5010 else
5012 return FALSE;
5014 break;
5015 case SUBTYPE_DEAUTH:
5016 *Machine = AUTH_RSP_STATE_MACHINE;
5017 *MsgType = MT2_PEER_DEAUTH;
5018 break;
5019 case SUBTYPE_ACTION:
5020 *Machine = ACTION_STATE_MACHINE;
5021 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5022 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5024 *MsgType = MT2_ACT_INVALID;
5026 else
5028 *MsgType = (pFrame->Octet[0]&0x7F);
5030 break;
5031 default:
5032 return FALSE;
5033 break;
5036 return TRUE;
5039 // ===========================================================================================
5040 // state_machine.c
5041 // ===========================================================================================
5043 /*! \brief Initialize the state machine.
5044 * \param *S pointer to the state machine
5045 * \param Trans State machine transition function
5046 * \param StNr number of states
5047 * \param MsgNr number of messages
5048 * \param DefFunc default function, when there is invalid state/message combination
5049 * \param InitState initial state of the state machine
5050 * \param Base StateMachine base, internal use only
5051 * \pre p_sm should be a legal pointer
5052 * \post
5054 IRQL = PASSIVE_LEVEL
5057 VOID StateMachineInit(
5058 IN STATE_MACHINE *S,
5059 IN STATE_MACHINE_FUNC Trans[],
5060 IN ULONG StNr,
5061 IN ULONG MsgNr,
5062 IN STATE_MACHINE_FUNC DefFunc,
5063 IN ULONG InitState,
5064 IN ULONG Base)
5066 ULONG i, j;
5068 // set number of states and messages
5069 S->NrState = StNr;
5070 S->NrMsg = MsgNr;
5071 S->Base = Base;
5073 S->TransFunc = Trans;
5075 // init all state transition to default function
5076 for (i = 0; i < StNr; i++)
5078 for (j = 0; j < MsgNr; j++)
5080 S->TransFunc[i * MsgNr + j] = DefFunc;
5084 // set the starting state
5085 S->CurrState = InitState;
5088 /*! \brief This function fills in the function pointer into the cell in the state machine
5089 * \param *S pointer to the state machine
5090 * \param St state
5091 * \param Msg incoming message
5092 * \param f the function to be executed when (state, message) combination occurs at the state machine
5093 * \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
5094 * \post
5096 IRQL = PASSIVE_LEVEL
5099 VOID StateMachineSetAction(
5100 IN STATE_MACHINE *S,
5101 IN ULONG St,
5102 IN ULONG Msg,
5103 IN STATE_MACHINE_FUNC Func)
5105 ULONG MsgIdx;
5107 MsgIdx = Msg - S->Base;
5109 if (St < S->NrState && MsgIdx < S->NrMsg)
5111 // boundary checking before setting the action
5112 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5116 /*! \brief This function does the state transition
5117 * \param *Adapter the NIC adapter pointer
5118 * \param *S the state machine
5119 * \param *Elem the message to be executed
5120 * \return None
5122 IRQL = DISPATCH_LEVEL
5125 VOID StateMachinePerformAction(
5126 IN PRTMP_ADAPTER pAd,
5127 IN STATE_MACHINE *S,
5128 IN MLME_QUEUE_ELEM *Elem)
5130 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5134 ==========================================================================
5135 Description:
5136 The drop function, when machine executes this, the message is simply
5137 ignored. This function does nothing, the message is freed in
5138 StateMachinePerformAction()
5139 ==========================================================================
5141 VOID Drop(
5142 IN PRTMP_ADAPTER pAd,
5143 IN MLME_QUEUE_ELEM *Elem)
5147 // ===========================================================================================
5148 // lfsr.c
5149 // ===========================================================================================
5152 ==========================================================================
5153 Description:
5155 IRQL = PASSIVE_LEVEL
5157 ==========================================================================
5159 VOID LfsrInit(
5160 IN PRTMP_ADAPTER pAd,
5161 IN ULONG Seed)
5163 if (Seed == 0)
5164 pAd->Mlme.ShiftReg = 1;
5165 else
5166 pAd->Mlme.ShiftReg = Seed;
5170 ==========================================================================
5171 Description:
5172 ==========================================================================
5174 UCHAR RandomByte(
5175 IN PRTMP_ADAPTER pAd)
5177 ULONG i;
5178 UCHAR R, Result;
5180 R = 0;
5182 if (pAd->Mlme.ShiftReg == 0)
5183 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5185 for (i = 0; i < 8; i++)
5187 if (pAd->Mlme.ShiftReg & 0x00000001)
5189 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5190 Result = 1;
5192 else
5194 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5195 Result = 0;
5197 R = (R << 1) | Result;
5200 return R;
5203 VOID AsicUpdateAutoFallBackTable(
5204 IN PRTMP_ADAPTER pAd,
5205 IN PUCHAR pRateTable)
5207 UCHAR i;
5208 HT_FBK_CFG0_STRUC HtCfg0;
5209 HT_FBK_CFG1_STRUC HtCfg1;
5210 LG_FBK_CFG0_STRUC LgCfg0;
5211 LG_FBK_CFG1_STRUC LgCfg1;
5212 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5214 // set to initial value
5215 HtCfg0.word = 0x65432100;
5216 HtCfg1.word = 0xedcba988;
5217 LgCfg0.word = 0xedcba988;
5218 LgCfg1.word = 0x00002100;
5220 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5221 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5223 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5224 switch (pCurrTxRate->Mode)
5226 case 0: //CCK
5227 break;
5228 case 1: //OFDM
5230 switch(pCurrTxRate->CurrMCS)
5232 case 0:
5233 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5234 break;
5235 case 1:
5236 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5237 break;
5238 case 2:
5239 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5240 break;
5241 case 3:
5242 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5243 break;
5244 case 4:
5245 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5246 break;
5247 case 5:
5248 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5249 break;
5250 case 6:
5251 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5252 break;
5253 case 7:
5254 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5255 break;
5258 break;
5259 case 2: //HT-MIX
5260 case 3: //HT-GF
5262 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5264 switch(pCurrTxRate->CurrMCS)
5266 case 0:
5267 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5268 break;
5269 case 1:
5270 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5271 break;
5272 case 2:
5273 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5274 break;
5275 case 3:
5276 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5277 break;
5278 case 4:
5279 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5280 break;
5281 case 5:
5282 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5283 break;
5284 case 6:
5285 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5286 break;
5287 case 7:
5288 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5289 break;
5290 case 8:
5291 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5292 break;
5293 case 9:
5294 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5295 break;
5296 case 10:
5297 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5298 break;
5299 case 11:
5300 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5301 break;
5302 case 12:
5303 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5304 break;
5305 case 13:
5306 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5307 break;
5308 case 14:
5309 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5310 break;
5311 case 15:
5312 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5313 break;
5314 default:
5315 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5319 break;
5322 pNextTxRate = pCurrTxRate;
5325 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5326 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5327 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5328 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5332 ========================================================================
5334 Routine Description:
5335 Set MAC register value according operation mode.
5336 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5337 If MM or GF mask is not set, those passing argument doesn't not take effect.
5339 Operation mode meaning:
5340 = 0 : Pure HT, no preotection.
5341 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5342 = 0x10: No Transmission in 40M is protected.
5343 = 0x11: Transmission in both 40M and 20M shall be protected
5344 if (bNonGFExist)
5345 we should choose not to use GF. But still set correct ASIC registers.
5346 ========================================================================
5348 VOID AsicUpdateProtect(
5349 IN PRTMP_ADAPTER pAd,
5350 IN USHORT OperationMode,
5351 IN UCHAR SetMask,
5352 IN BOOLEAN bDisableBGProtect,
5353 IN BOOLEAN bNonGFExist)
5355 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5356 UINT32 Protect[6];
5357 USHORT offset;
5358 UCHAR i;
5359 UINT32 MacReg = 0;
5361 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5363 return;
5366 if (pAd->BATable.numAsOriginator)
5369 // enable the RTS/CTS to avoid channel collision
5371 SetMask = ALLN_SETPROTECT;
5372 OperationMode = 8;
5375 // Config ASIC RTS threshold register
5376 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5377 MacReg &= 0xFF0000FF;
5379 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5380 if ((
5381 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5382 (pAd->CommonCfg.bAggregationCapable == TRUE))
5383 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5385 MacReg |= (0x1000 << 8);
5387 else
5389 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5392 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5394 // Initial common protection settings
5395 RTMPZeroMemory(Protect, sizeof(Protect));
5396 ProtCfg4.word = 0;
5397 ProtCfg.word = 0;
5398 ProtCfg.field.TxopAllowGF40 = 1;
5399 ProtCfg.field.TxopAllowGF20 = 1;
5400 ProtCfg.field.TxopAllowMM40 = 1;
5401 ProtCfg.field.TxopAllowMM20 = 1;
5402 ProtCfg.field.TxopAllowOfdm = 1;
5403 ProtCfg.field.TxopAllowCck = 1;
5404 ProtCfg.field.RTSThEn = 1;
5405 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5407 // update PHY mode and rate
5408 if (pAd->CommonCfg.Channel > 14)
5409 ProtCfg.field.ProtectRate = 0x4000;
5410 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5412 // Handle legacy(B/G) protection
5413 if (bDisableBGProtect)
5415 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5416 ProtCfg.field.ProtectCtrl = 0;
5417 Protect[0] = ProtCfg.word;
5418 Protect[1] = ProtCfg.word;
5420 else
5422 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5423 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5424 Protect[0] = ProtCfg.word;
5425 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5426 Protect[1] = ProtCfg.word;
5429 // Decide HT frame protection.
5430 if ((SetMask & ALLN_SETPROTECT) != 0)
5432 switch(OperationMode)
5434 case 0x0:
5435 // NO PROTECT
5436 // 1.All STAs in the BSS are 20/40 MHz HT
5437 // 2. in ai 20/40MHz BSS
5438 // 3. all STAs are 20MHz in a 20MHz BSS
5439 // Pure HT. no protection.
5441 // MM20_PROT_CFG
5442 // Reserved (31:27)
5443 // PROT_TXOP(25:20) -- 010111
5444 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5445 // PROT_CTRL(17:16) -- 00 (None)
5446 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5447 Protect[2] = 0x01744004;
5449 // MM40_PROT_CFG
5450 // Reserved (31:27)
5451 // PROT_TXOP(25:20) -- 111111
5452 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5453 // PROT_CTRL(17:16) -- 00 (None)
5454 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5455 Protect[3] = 0x03f44084;
5457 // CF20_PROT_CFG
5458 // Reserved (31:27)
5459 // PROT_TXOP(25:20) -- 010111
5460 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5461 // PROT_CTRL(17:16) -- 00 (None)
5462 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5463 Protect[4] = 0x01744004;
5465 // CF40_PROT_CFG
5466 // Reserved (31:27)
5467 // PROT_TXOP(25:20) -- 111111
5468 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5469 // PROT_CTRL(17:16) -- 00 (None)
5470 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5471 Protect[5] = 0x03f44084;
5473 if (bNonGFExist)
5475 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5476 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5477 Protect[4] = 0x01754004;
5478 Protect[5] = 0x03f54084;
5480 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5481 break;
5483 case 1:
5484 // This is "HT non-member protection mode."
5485 // If there may be non-HT STAs my BSS
5486 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5487 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5488 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5490 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5491 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5493 //Assign Protection method for 20&40 MHz packets
5494 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5495 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5496 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5497 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5498 Protect[2] = ProtCfg.word;
5499 Protect[3] = ProtCfg4.word;
5500 Protect[4] = ProtCfg.word;
5501 Protect[5] = ProtCfg4.word;
5502 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5503 break;
5505 case 2:
5506 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5507 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5508 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5510 //Assign Protection method for 40MHz packets
5511 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5512 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5513 Protect[2] = ProtCfg.word;
5514 Protect[3] = ProtCfg4.word;
5515 if (bNonGFExist)
5517 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5518 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5520 Protect[4] = ProtCfg.word;
5521 Protect[5] = ProtCfg4.word;
5523 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5524 break;
5526 case 3:
5527 // HT mixed mode. PROTECT ALL!
5528 // Assign Rate
5529 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5530 ProtCfg4.word = 0x03f44084;
5531 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5532 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5534 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5535 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5537 //Assign Protection method for 20&40 MHz packets
5538 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5539 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5540 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5541 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5542 Protect[2] = ProtCfg.word;
5543 Protect[3] = ProtCfg4.word;
5544 Protect[4] = ProtCfg.word;
5545 Protect[5] = ProtCfg4.word;
5546 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5547 break;
5549 case 8:
5550 // Special on for Atheros problem n chip.
5551 Protect[2] = 0x01754004;
5552 Protect[3] = 0x03f54084;
5553 Protect[4] = 0x01754004;
5554 Protect[5] = 0x03f54084;
5555 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5556 break;
5560 offset = CCK_PROT_CFG;
5561 for (i = 0;i < 6;i++)
5563 if ((SetMask & (1<< i)))
5565 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5570 #ifdef RT30xx
5571 // add by johnli, RF power sequence setup
5573 ==========================================================================
5574 Description:
5576 Load RF normal operation-mode setup
5578 ==========================================================================
5580 VOID RT30xxLoadRFNormalModeSetup(
5581 IN PRTMP_ADAPTER pAd)
5583 UCHAR RFValue;
5585 // 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
5586 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5587 RFValue = (RFValue & (~0x0C)) | 0x31;
5588 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5590 // TX_LO2_en, RF R15 register Bit 3 to 0
5591 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5592 RFValue &= (~0x08);
5593 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5595 // TX_LO1_en, RF R17 register Bit 3 to 0
5596 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5597 RFValue &= (~0x08);
5598 // to fix rx long range issue
5599 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5601 RFValue |= 0x20;
5603 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5605 // RX_LO1_en, RF R20 register Bit 3 to 0
5606 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5607 RFValue &= (~0x08);
5608 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5610 // RX_LO2_en, RF R21 register Bit 3 to 0
5611 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5612 RFValue &= (~0x08);
5613 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5615 // LDORF_VC, RF R27 register Bit 2 to 0
5616 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5617 if ((pAd->MACVersion & 0xffff) < 0x0211)
5618 RFValue = (RFValue & (~0x77)) | 0x3;
5619 else
5620 RFValue = (RFValue & (~0x77));
5621 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5622 /* end johnli */
5626 ==========================================================================
5627 Description:
5629 Load RF sleep-mode setup
5631 ==========================================================================
5633 VOID RT30xxLoadRFSleepModeSetup(
5634 IN PRTMP_ADAPTER pAd)
5636 UCHAR RFValue;
5637 UINT32 MACValue;
5639 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5640 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5641 RFValue &= (~0x01);
5642 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5644 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5645 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5646 RFValue &= (~0x30);
5647 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5649 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5650 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5651 RFValue &= (~0x0E);
5652 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5654 // RX_CTB_en, RF R21 register Bit 7 to 0
5655 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5656 RFValue &= (~0x80);
5657 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5659 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5660 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5661 RFValue |= 0x77;
5662 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5664 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5665 MACValue |= 0x1D000000;
5666 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5670 ==========================================================================
5671 Description:
5673 Reverse RF sleep-mode setup
5675 ==========================================================================
5677 VOID RT30xxReverseRFSleepModeSetup(
5678 IN PRTMP_ADAPTER pAd)
5680 UCHAR RFValue;
5681 UINT32 MACValue;
5683 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5684 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5685 RFValue |= 0x01;
5686 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5688 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5689 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5690 RFValue |= 0x30;
5691 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5693 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5694 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5695 RFValue |= 0x0E;
5696 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5698 // RX_CTB_en, RF R21 register Bit 7 to 1
5699 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5700 RFValue |= 0x80;
5701 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5703 // LDORF_VC, RF R27 register Bit 2 to 0
5704 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5705 if ((pAd->MACVersion & 0xffff) < 0x0211)
5706 RFValue = (RFValue & (~0x77)) | 0x3;
5707 else
5708 RFValue = (RFValue & (~0x77));
5709 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5711 // RT3071 version E has fixed this issue
5712 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5714 // patch tx EVM issue temporarily
5715 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5716 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5717 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5719 else
5721 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5722 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5723 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5726 // end johnli
5727 #endif // RT30xx //
5730 ==========================================================================
5731 Description:
5733 IRQL = PASSIVE_LEVEL
5734 IRQL = DISPATCH_LEVEL
5736 ==========================================================================
5738 VOID AsicSwitchChannel(
5739 IN PRTMP_ADAPTER pAd,
5740 IN UCHAR Channel,
5741 IN BOOLEAN bScan)
5743 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5744 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5745 UCHAR index;
5746 UINT32 Value = 0; //BbpReg, Value;
5747 RTMP_RF_REGS *RFRegTable;
5749 // Search Tx power value
5750 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5751 // in ChannelList, so use TxPower array instead.
5753 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5755 if (Channel == pAd->TxPower[index].Channel)
5757 TxPwer = pAd->TxPower[index].Power;
5758 TxPwer2 = pAd->TxPower[index].Power2;
5759 break;
5763 if (index == MAX_NUM_OF_CHANNELS)
5764 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5766 #ifdef RT2870
5767 // The RF programming sequence is difference between 3xxx and 2xxx
5768 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && (
5769 #ifdef RT30xx
5770 (pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) ||
5771 #endif
5772 (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5774 /* modify by WY for Read RF Reg. error */
5775 UCHAR RFValue;
5777 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5779 if (Channel == FreqItems3020[index].Channel)
5781 // Programming channel parameters
5782 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5783 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5785 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5786 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5787 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5789 // Set Tx0 Power
5790 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5791 RFValue = (RFValue & 0xE0) | TxPwer;
5792 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5794 #ifdef RT30xx
5795 // Set Tx1 Power
5796 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5797 RFValue = (RFValue & 0xE0) | TxPwer2;
5798 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5800 // Tx/Rx Stream setting
5801 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5802 //if (IS_RT3090(pAd))
5803 // RFValue |= 0x01; // Enable RF block.
5804 RFValue &= 0x03; //clear bit[7~2]
5805 if (pAd->Antenna.field.TxPath == 1)
5806 RFValue |= 0xA0;
5807 else if (pAd->Antenna.field.TxPath == 2)
5808 RFValue |= 0x80;
5809 if (pAd->Antenna.field.RxPath == 1)
5810 RFValue |= 0x50;
5811 else if (pAd->Antenna.field.RxPath == 2)
5812 RFValue |= 0x40;
5813 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5814 #endif
5816 // Set RF offset
5817 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5818 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5819 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5821 // Set BW
5822 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5824 RFValue = pAd->Mlme.CaliBW40RfR24;
5825 //DISABLE_11N_CHECK(pAd);
5827 else
5829 RFValue = pAd->Mlme.CaliBW20RfR24;
5831 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5832 #ifdef RT30xx
5833 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5834 #endif
5835 // Enable RF tuning
5836 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5837 RFValue = RFValue | 0x1;
5838 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5840 // latch channel for future usage.
5841 pAd->LatchRfRegs.Channel = Channel;
5843 #ifdef RT30xx
5844 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5845 Channel,
5846 pAd->RfIcType,
5847 TxPwer,
5848 TxPwer2,
5849 pAd->Antenna.field.TxPath,
5850 FreqItems3020[index].N,
5851 FreqItems3020[index].K,
5852 FreqItems3020[index].R));
5853 #endif
5855 break;
5859 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5860 Channel,
5861 pAd->RfIcType,
5862 TxPwer,
5863 TxPwer2,
5864 pAd->Antenna.field.TxPath,
5865 FreqItems3020[index].N,
5866 FreqItems3020[index].K,
5867 FreqItems3020[index].R));
5869 else
5870 #endif // RT2870 //
5872 RFRegTable = RF2850RegTable;
5874 switch (pAd->RfIcType)
5876 case RFIC_2820:
5877 case RFIC_2850:
5878 case RFIC_2720:
5879 case RFIC_2750:
5881 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5883 if (Channel == RFRegTable[index].Channel)
5885 R2 = RFRegTable[index].R2;
5886 if (pAd->Antenna.field.TxPath == 1)
5888 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5891 if (pAd->Antenna.field.RxPath == 2)
5893 R2 |= 0x40; // write 1 to off Rxpath.
5895 else if (pAd->Antenna.field.RxPath == 1)
5897 R2 |= 0x20040; // write 1 to off RxPath
5900 if (Channel > 14)
5902 // initialize R3, R4
5903 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5904 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5906 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5907 // R3
5908 if ((TxPwer >= -7) && (TxPwer < 0))
5910 TxPwer = (7+TxPwer);
5911 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5912 R3 |= (TxPwer << 10);
5913 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5915 else
5917 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5918 R3 |= (TxPwer << 10) | (1 << 9);
5921 // R4
5922 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5924 TxPwer2 = (7+TxPwer2);
5925 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5926 R4 |= (TxPwer2 << 7);
5927 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5929 else
5931 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5932 R4 |= (TxPwer2 << 7) | (1 << 6);
5935 else
5937 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5938 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5941 // Based on BBP current mode before changing RF channel.
5942 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5944 R4 |=0x200000;
5947 // Update variables
5948 pAd->LatchRfRegs.Channel = Channel;
5949 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5950 pAd->LatchRfRegs.R2 = R2;
5951 pAd->LatchRfRegs.R3 = R3;
5952 pAd->LatchRfRegs.R4 = R4;
5954 // Set RF value 1's set R3[bit2] = [0]
5955 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5956 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5957 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5958 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5960 RTMPusecDelay(200);
5962 // Set RF value 2's set R3[bit2] = [1]
5963 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5964 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5965 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5966 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5968 RTMPusecDelay(200);
5970 // Set RF value 3's set R3[bit2] = [0]
5971 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5972 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5973 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5974 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5976 break;
5979 break;
5981 default:
5982 break;
5986 // Change BBP setting during siwtch from a->g, g->a
5987 if (Channel <= 14)
5989 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5991 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5992 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5993 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5994 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.
5995 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5997 // Rx High power VGA offset for LNA select
5998 if (pAd->NicConfig2.field.ExternalLNAForG)
6000 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6001 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6003 else
6005 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6006 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6009 // 5G band selection PIN, bit1 and bit2 are complement
6010 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6011 Value &= (~0x6);
6012 Value |= (0x04);
6013 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6015 // Turn off unused PA or LNA when only 1T or 1R
6016 if (pAd->Antenna.field.TxPath == 1)
6018 TxPinCfg &= 0xFFFFFFF3;
6020 if (pAd->Antenna.field.RxPath == 1)
6022 TxPinCfg &= 0xFFFFF3FF;
6025 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6027 else
6029 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6031 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6032 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6033 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6034 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.
6035 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6037 // Rx High power VGA offset for LNA select
6038 if (pAd->NicConfig2.field.ExternalLNAForA)
6040 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6042 else
6044 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6047 // 5G band selection PIN, bit1 and bit2 are complement
6048 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6049 Value &= (~0x6);
6050 Value |= (0x02);
6051 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6053 // Turn off unused PA or LNA when only 1T or 1R
6054 if (pAd->Antenna.field.TxPath == 1)
6056 TxPinCfg &= 0xFFFFFFF3;
6058 if (pAd->Antenna.field.RxPath == 1)
6060 TxPinCfg &= 0xFFFFF3FF;
6063 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6066 // R66 should be set according to Channel and use 20MHz when scanning
6067 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6068 if (bScan)
6069 RTMPSetAGCInitValue(pAd, BW_20);
6070 else
6071 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6074 // On 11A, We should delay and wait RF/BBP to be stable
6075 // and the appropriate time should be 1000 micro seconds
6076 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6078 RTMPusecDelay(1000);
6080 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",
6081 Channel,
6082 pAd->RfIcType,
6083 (R3 & 0x00003e00) >> 9,
6084 (R4 & 0x000007c0) >> 6,
6085 pAd->Antenna.field.TxPath,
6086 pAd->LatchRfRegs.R1,
6087 pAd->LatchRfRegs.R2,
6088 pAd->LatchRfRegs.R3,
6089 pAd->LatchRfRegs.R4));
6093 ==========================================================================
6094 Description:
6095 This function is required for 2421 only, and should not be used during
6096 site survey. It's only required after NIC decided to stay at a channel
6097 for a longer period.
6098 When this function is called, it's always after AsicSwitchChannel().
6100 IRQL = PASSIVE_LEVEL
6101 IRQL = DISPATCH_LEVEL
6103 ==========================================================================
6105 VOID AsicLockChannel(
6106 IN PRTMP_ADAPTER pAd,
6107 IN UCHAR Channel)
6112 ==========================================================================
6113 Description:
6115 IRQL = PASSIVE_LEVEL
6116 IRQL = DISPATCH_LEVEL
6118 ==========================================================================
6120 VOID AsicAntennaSelect(
6121 IN PRTMP_ADAPTER pAd,
6122 IN UCHAR Channel)
6124 #ifdef RT30xx
6125 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6127 // patch for AsicSetRxAnt failed
6128 pAd->RxAnt.EvaluatePeriod = 0;
6130 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6131 // valid indication of the distance between this AP and its clients.
6132 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6134 SHORT realavgrssi1;
6136 // if no traffic then reset average rssi to trigger evaluation
6137 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6139 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6140 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6141 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6144 pAd->StaCfg.NumOfAvgRssiSample = 0;
6145 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6147 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6149 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6150 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6152 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6153 AsicEvaluateRxAnt(pAd);
6156 else
6158 // if not connected, always switch antenna to try to connect
6159 UCHAR temp;
6161 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6162 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6163 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6165 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6167 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6170 #endif /* RT30xx */
6174 ========================================================================
6176 Routine Description:
6177 Antenna miscellaneous setting.
6179 Arguments:
6180 pAd Pointer to our adapter
6181 BandState Indicate current Band State.
6183 Return Value:
6184 None
6186 IRQL <= DISPATCH_LEVEL
6188 Note:
6189 1.) Frame End type control
6190 only valid for G only (RF_2527 & RF_2529)
6191 0: means DPDT, set BBP R4 bit 5 to 1
6192 1: means SPDT, set BBP R4 bit 5 to 0
6195 ========================================================================
6197 VOID AsicAntennaSetting(
6198 IN PRTMP_ADAPTER pAd,
6199 IN ABGBAND_STATE BandState)
6203 VOID AsicRfTuningExec(
6204 IN PVOID SystemSpecific1,
6205 IN PVOID FunctionContext,
6206 IN PVOID SystemSpecific2,
6207 IN PVOID SystemSpecific3)
6212 ==========================================================================
6213 Description:
6214 Gives CCK TX rate 2 more dB TX power.
6215 This routine works only in LINK UP in INFRASTRUCTURE mode.
6217 calculate desired Tx power in RF R3.Tx0~5, should consider -
6218 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6219 1. TxPowerPercentage
6220 2. auto calibration based on TSSI feedback
6221 3. extra 2 db for CCK
6222 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6224 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6225 it should be called AFTER MlmeDynamicTxRatSwitching()
6226 ==========================================================================
6228 VOID AsicAdjustTxPower(
6229 IN PRTMP_ADAPTER pAd)
6231 INT i, j;
6232 CHAR DeltaPwr = 0;
6233 BOOLEAN bAutoTxAgc = FALSE;
6234 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6235 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6236 PCHAR pTxAgcCompensate;
6237 ULONG TxPwr[5];
6238 CHAR Value;
6240 #ifdef RT2860
6241 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6242 || (pAd->bPCIclkOff == TRUE)
6243 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6244 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6245 return;
6246 #endif
6248 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6250 if (pAd->CommonCfg.CentralChannel > 14)
6252 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6253 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6254 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6255 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6256 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6258 else
6260 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6261 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6262 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6263 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6264 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6267 else
6269 if (pAd->CommonCfg.Channel > 14)
6271 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6272 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6273 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6274 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6275 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6277 else
6279 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6280 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6281 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6282 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6283 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6287 // TX power compensation for temperature variation based on TSSI. try every 4 second
6288 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6290 if (pAd->CommonCfg.Channel <= 14)
6292 /* bg channel */
6293 bAutoTxAgc = pAd->bAutoTxAgcG;
6294 TssiRef = pAd->TssiRefG;
6295 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6296 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6297 TxAgcStep = pAd->TxAgcStepG;
6298 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6300 else
6302 /* a channel */
6303 bAutoTxAgc = pAd->bAutoTxAgcA;
6304 TssiRef = pAd->TssiRefA;
6305 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6306 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6307 TxAgcStep = pAd->TxAgcStepA;
6308 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6311 if (bAutoTxAgc)
6313 /* BbpR1 is unsigned char */
6314 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6316 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6317 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6318 /* step value is defined in pAd->TxAgcStepG for tx power value */
6320 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6321 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6322 above value are examined in mass factory production */
6323 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6325 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6326 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6327 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6329 if (BbpR49 > pTssiMinusBoundary[1])
6331 // Reading is larger than the reference value
6332 // check for how large we need to decrease the Tx power
6333 for (idx = 1; idx < 5; idx++)
6335 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6336 break;
6338 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6339 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6341 DeltaPwr += (*pTxAgcCompensate);
6342 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6343 BbpR49, TssiRef, TxAgcStep, idx-1));
6345 else if (BbpR49 < pTssiPlusBoundary[1])
6347 // Reading is smaller than the reference value
6348 // check for how large we need to increase the Tx power
6349 for (idx = 1; idx < 5; idx++)
6351 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6352 break;
6354 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6355 *pTxAgcCompensate = TxAgcStep * (idx-1);
6356 DeltaPwr += (*pTxAgcCompensate);
6357 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6358 BbpR49, TssiRef, TxAgcStep, idx-1));
6360 else
6362 *pTxAgcCompensate = 0;
6363 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6364 BbpR49, TssiRef, TxAgcStep, 0));
6368 else
6370 if (pAd->CommonCfg.Channel <= 14)
6372 bAutoTxAgc = pAd->bAutoTxAgcG;
6373 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6375 else
6377 bAutoTxAgc = pAd->bAutoTxAgcA;
6378 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6381 if (bAutoTxAgc)
6382 DeltaPwr += (*pTxAgcCompensate);
6385 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6386 BbpR1 &= 0xFC;
6388 /* calculate delta power based on the percentage specified from UI */
6389 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6390 // We lower TX power here according to the percentage specified from UI
6391 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6393 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6395 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6397 DeltaPwr -= 1;
6399 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6401 DeltaPwr -= 3;
6403 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6405 BbpR1 |= 0x01;
6407 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6409 BbpR1 |= 0x01;
6410 DeltaPwr -= 3;
6412 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6414 BbpR1 |= 0x02;
6417 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6419 /* reset different new tx power for different TX rate */
6420 for(i=0; i<5; i++)
6422 if (TxPwr[i] != 0xffffffff)
6424 for (j=0; j<8; j++)
6426 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6428 if ((Value + DeltaPwr) < 0)
6430 Value = 0; /* min */
6432 else if ((Value + DeltaPwr) > 0xF)
6434 Value = 0xF; /* max */
6436 else
6438 Value += DeltaPwr; /* temperature compensation */
6441 /* fill new value to CSR offset */
6442 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6445 /* write tx power value to CSR */
6446 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6447 TX power for OFDM 6M/9M
6448 TX power for CCK5.5M/11M
6449 TX power for CCK1M/2M */
6450 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6451 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6458 ==========================================================================
6459 Description:
6460 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6461 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6462 the wakeup timer timeout. Driver has to issue a separate command to wake
6463 PHY up.
6465 IRQL = DISPATCH_LEVEL
6467 ==========================================================================
6469 VOID AsicSleepThenAutoWakeup(
6470 IN PRTMP_ADAPTER pAd,
6471 IN USHORT TbttNumToNextWakeUp)
6473 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6477 ==========================================================================
6478 Description:
6479 AsicForceWakeup() is used whenever manual wakeup is required
6480 AsicForceSleep() should only be used when not in INFRA BSS. When
6481 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6482 ==========================================================================
6484 VOID AsicForceSleep(
6485 IN PRTMP_ADAPTER pAd)
6491 ==========================================================================
6492 Description:
6493 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6494 expired.
6496 IRQL = PASSIVE_LEVEL
6497 IRQL = DISPATCH_LEVEL
6498 ==========================================================================
6500 VOID AsicForceWakeup(
6501 IN PRTMP_ADAPTER pAd,
6502 #ifdef RT2860
6503 IN UCHAR Level)
6504 #endif
6505 #ifdef RT2870
6506 IN BOOLEAN bFromTx)
6507 #endif
6509 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6510 #ifdef RT2860
6511 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6512 #endif
6513 #ifdef RT2870
6514 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6515 #endif
6519 ==========================================================================
6520 Description:
6521 Set My BSSID
6523 IRQL = DISPATCH_LEVEL
6525 ==========================================================================
6527 VOID AsicSetBssid(
6528 IN PRTMP_ADAPTER pAd,
6529 IN PUCHAR pBssid)
6531 ULONG Addr4;
6532 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6533 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6535 Addr4 = (ULONG)(pBssid[0]) |
6536 (ULONG)(pBssid[1] << 8) |
6537 (ULONG)(pBssid[2] << 16) |
6538 (ULONG)(pBssid[3] << 24);
6539 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6541 Addr4 = 0;
6542 // always one BSSID in STA mode
6543 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6545 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6548 VOID AsicSetMcastWC(
6549 IN PRTMP_ADAPTER pAd)
6551 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6552 USHORT offset;
6554 pEntry->Sst = SST_ASSOC;
6555 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6556 pEntry->PsMode = PWR_ACTIVE;
6557 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6558 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6562 ==========================================================================
6563 Description:
6565 IRQL = DISPATCH_LEVEL
6567 ==========================================================================
6569 VOID AsicDelWcidTab(
6570 IN PRTMP_ADAPTER pAd,
6571 IN UCHAR Wcid)
6573 ULONG Addr0 = 0x0, Addr1 = 0x0;
6574 ULONG offset;
6576 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6577 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6578 RTMP_IO_WRITE32(pAd, offset, Addr0);
6579 offset += 4;
6580 RTMP_IO_WRITE32(pAd, offset, Addr1);
6584 ==========================================================================
6585 Description:
6587 IRQL = DISPATCH_LEVEL
6589 ==========================================================================
6591 VOID AsicEnableRDG(
6592 IN PRTMP_ADAPTER pAd)
6594 TX_LINK_CFG_STRUC TxLinkCfg;
6595 UINT32 Data = 0;
6597 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6598 TxLinkCfg.field.TxRDGEn = 1;
6599 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6601 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6602 Data &= 0xFFFFFF00;
6603 Data |= 0x80;
6604 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6606 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6610 ==========================================================================
6611 Description:
6613 IRQL = DISPATCH_LEVEL
6615 ==========================================================================
6617 VOID AsicDisableRDG(
6618 IN PRTMP_ADAPTER pAd)
6620 TX_LINK_CFG_STRUC TxLinkCfg;
6621 UINT32 Data = 0;
6624 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6625 TxLinkCfg.field.TxRDGEn = 0;
6626 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6628 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6630 Data &= 0xFFFFFF00;
6631 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6632 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6635 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6636 if (pAd->CommonCfg.bEnableTxBurst)
6637 Data |= 0x20;
6639 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6643 ==========================================================================
6644 Description:
6646 IRQL = PASSIVE_LEVEL
6647 IRQL = DISPATCH_LEVEL
6649 ==========================================================================
6651 VOID AsicDisableSync(
6652 IN PRTMP_ADAPTER pAd)
6654 BCN_TIME_CFG_STRUC csr;
6656 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6658 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6659 // that NIC will never wakes up because TSF stops and no more
6660 // TBTT interrupts
6661 pAd->TbttTickCount = 0;
6662 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6663 csr.field.bBeaconGen = 0;
6664 csr.field.bTBTTEnable = 0;
6665 csr.field.TsfSyncMode = 0;
6666 csr.field.bTsfTicking = 0;
6667 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6672 ==========================================================================
6673 Description:
6675 IRQL = DISPATCH_LEVEL
6677 ==========================================================================
6679 VOID AsicEnableBssSync(
6680 IN PRTMP_ADAPTER pAd)
6682 BCN_TIME_CFG_STRUC csr;
6684 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6686 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6689 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6690 csr.field.bTsfTicking = 1;
6691 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6692 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6693 csr.field.bTBTTEnable = 1;
6696 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6700 ==========================================================================
6701 Description:
6702 Note:
6703 BEACON frame in shared memory should be built ok before this routine
6704 can be called. Otherwise, a garbage frame maybe transmitted out every
6705 Beacon period.
6707 IRQL = DISPATCH_LEVEL
6709 ==========================================================================
6711 VOID AsicEnableIbssSync(
6712 IN PRTMP_ADAPTER pAd)
6714 BCN_TIME_CFG_STRUC csr9;
6715 PUCHAR ptr;
6716 UINT i;
6718 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6720 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6721 csr9.field.bBeaconGen = 0;
6722 csr9.field.bTBTTEnable = 0;
6723 csr9.field.bTsfTicking = 0;
6724 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6726 #ifdef RT2860
6727 // move BEACON TXD and frame content to on-chip memory
6728 ptr = (PUCHAR)&pAd->BeaconTxWI;
6729 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6731 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6732 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6733 ptr += 4;
6736 // start right after the 16-byte TXWI field
6737 ptr = pAd->BeaconBuf;
6738 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6740 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6741 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6742 ptr +=4;
6744 #endif
6745 #ifdef RT2870
6746 // move BEACON TXD and frame content to on-chip memory
6747 ptr = (PUCHAR)&pAd->BeaconTxWI;
6748 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6750 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6751 ptr += 2;
6754 // start right after the 16-byte TXWI field
6755 ptr = pAd->BeaconBuf;
6756 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6758 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6759 ptr +=2;
6761 #endif // RT2870 //
6763 // start sending BEACON
6764 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6765 csr9.field.bTsfTicking = 1;
6766 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6767 csr9.field.bTBTTEnable = 1;
6768 csr9.field.bBeaconGen = 1;
6769 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6773 ==========================================================================
6774 Description:
6776 IRQL = PASSIVE_LEVEL
6777 IRQL = DISPATCH_LEVEL
6779 ==========================================================================
6781 VOID AsicSetEdcaParm(
6782 IN PRTMP_ADAPTER pAd,
6783 IN PEDCA_PARM pEdcaParm)
6785 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6786 AC_TXOP_CSR0_STRUC csr0;
6787 AC_TXOP_CSR1_STRUC csr1;
6788 AIFSN_CSR_STRUC AifsnCsr;
6789 CWMIN_CSR_STRUC CwminCsr;
6790 CWMAX_CSR_STRUC CwmaxCsr;
6791 int i;
6793 Ac0Cfg.word = 0;
6794 Ac1Cfg.word = 0;
6795 Ac2Cfg.word = 0;
6796 Ac3Cfg.word = 0;
6797 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6799 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6800 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6801 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6803 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6804 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6807 //========================================================
6808 // MAC Register has a copy .
6809 //========================================================
6810 if( pAd->CommonCfg.bEnableTxBurst )
6812 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6813 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6815 else
6816 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6817 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6818 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6819 Ac0Cfg.field.Aifsn = 2;
6820 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6822 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6823 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6824 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6825 Ac1Cfg.field.Aifsn = 2;
6826 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6828 if (pAd->CommonCfg.PhyMode == PHY_11B)
6830 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6831 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6833 else
6835 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6836 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6838 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6839 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6840 Ac2Cfg.field.Aifsn = 2;
6841 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6842 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6843 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6844 Ac3Cfg.field.Aifsn = 2;
6845 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6847 //========================================================
6848 // DMA Register has a copy too.
6849 //========================================================
6850 csr0.field.Ac0Txop = 0; // QID_AC_BE
6851 csr0.field.Ac1Txop = 0; // QID_AC_BK
6852 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6853 if (pAd->CommonCfg.PhyMode == PHY_11B)
6855 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6856 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6858 else
6860 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6861 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6863 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6865 CwminCsr.word = 0;
6866 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6867 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6868 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6869 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6870 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6872 CwmaxCsr.word = 0;
6873 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6874 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6875 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6876 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6877 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6879 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6881 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6883 else
6885 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6886 //========================================================
6887 // MAC Register has a copy.
6888 //========================================================
6890 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6891 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6893 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6895 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6896 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6897 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6898 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6900 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6901 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6902 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6903 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6905 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6906 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6907 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6908 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6911 // Tuning for Wi-Fi WMM S06
6912 if (pAd->CommonCfg.bWiFiTest &&
6913 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6914 Ac2Cfg.field.Aifsn -= 1;
6916 // Tuning for TGn Wi-Fi 5.2.32
6917 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6918 if (STA_TGN_WIFI_ON(pAd) &&
6919 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6921 Ac0Cfg.field.Aifsn = 3;
6922 Ac2Cfg.field.AcTxop = 5;
6925 #ifdef RT30xx
6926 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6928 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6929 Ac2Cfg.field.Aifsn = 5;
6931 #endif // RT30xx //
6934 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6935 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6936 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6937 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6939 //#ifdef WIFI_TEST
6940 if (pAd->CommonCfg.bWiFiTest)
6942 if (Ac3Cfg.field.AcTxop == 102)
6944 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6945 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6946 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6947 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6948 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6949 } /* End of if */
6951 //#endif // WIFI_TEST //
6953 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6954 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6955 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6956 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6959 //========================================================
6960 // DMA Register has a copy too.
6961 //========================================================
6962 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6963 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6964 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6966 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6967 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6968 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6970 CwminCsr.word = 0;
6971 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6972 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6973 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6975 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6977 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6979 CwmaxCsr.word = 0;
6980 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6981 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6982 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6983 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6984 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6986 AifsnCsr.word = 0;
6987 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6988 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6989 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6992 // Tuning for Wi-Fi WMM S06
6993 if (pAd->CommonCfg.bWiFiTest &&
6994 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6995 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6997 // Tuning for TGn Wi-Fi 5.2.32
6998 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6999 if (STA_TGN_WIFI_ON(pAd) &&
7000 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7002 AifsnCsr.field.Aifsn0 = 3;
7003 AifsnCsr.field.Aifsn2 = 7;
7005 #ifdef RT2870
7006 if (INFRA_ON(pAd))
7007 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7008 #endif
7011 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7012 #ifdef RT30xx
7013 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7014 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7015 #endif // RT30xx //
7017 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7019 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7020 if (!ADHOC_ON(pAd))
7022 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7023 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7024 pEdcaParm->Aifsn[0],
7025 pEdcaParm->Cwmin[0],
7026 pEdcaParm->Cwmax[0],
7027 pEdcaParm->Txop[0]<<5,
7028 pEdcaParm->bACM[0]));
7029 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7030 pEdcaParm->Aifsn[1],
7031 pEdcaParm->Cwmin[1],
7032 pEdcaParm->Cwmax[1],
7033 pEdcaParm->Txop[1]<<5,
7034 pEdcaParm->bACM[1]));
7035 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7036 pEdcaParm->Aifsn[2],
7037 pEdcaParm->Cwmin[2],
7038 pEdcaParm->Cwmax[2],
7039 pEdcaParm->Txop[2]<<5,
7040 pEdcaParm->bACM[2]));
7041 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7042 pEdcaParm->Aifsn[3],
7043 pEdcaParm->Cwmin[3],
7044 pEdcaParm->Cwmax[3],
7045 pEdcaParm->Txop[3]<<5,
7046 pEdcaParm->bACM[3]));
7052 ==========================================================================
7053 Description:
7055 IRQL = PASSIVE_LEVEL
7056 IRQL = DISPATCH_LEVEL
7058 ==========================================================================
7060 VOID AsicSetSlotTime(
7061 IN PRTMP_ADAPTER pAd,
7062 IN BOOLEAN bUseShortSlotTime)
7064 ULONG SlotTime;
7065 UINT32 RegValue = 0;
7067 if (pAd->CommonCfg.Channel > 14)
7068 bUseShortSlotTime = TRUE;
7070 if (bUseShortSlotTime)
7071 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7072 else
7073 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7075 SlotTime = (bUseShortSlotTime)? 9 : 20;
7078 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7079 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7080 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7083 // In this case, we will think it is doing Wi-Fi test
7084 // And we will not set to short slot when bEnableTxBurst is TRUE.
7086 else if (pAd->CommonCfg.bEnableTxBurst)
7087 SlotTime = 9;
7091 // For some reasons, always set it to short slot time.
7093 // ToDo: Should consider capability with 11B
7095 if (pAd->StaCfg.BssType == BSS_ADHOC)
7096 SlotTime = 20;
7098 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7099 RegValue = RegValue & 0xFFFFFF00;
7101 RegValue |= SlotTime;
7103 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7107 ========================================================================
7108 Description:
7109 Add Shared key information into ASIC.
7110 Update shared key, TxMic and RxMic to Asic Shared key table
7111 Update its cipherAlg to Asic Shared key Mode.
7113 Return:
7114 ========================================================================
7116 VOID AsicAddSharedKeyEntry(
7117 IN PRTMP_ADAPTER pAd,
7118 IN UCHAR BssIndex,
7119 IN UCHAR KeyIdx,
7120 IN UCHAR CipherAlg,
7121 IN PUCHAR pKey,
7122 IN PUCHAR pTxMic,
7123 IN PUCHAR pRxMic)
7125 ULONG offset; //, csr0;
7126 SHAREDKEY_MODE_STRUC csr1;
7127 #ifdef RT2860
7128 INT i;
7129 #endif
7131 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7132 //============================================================================================
7134 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7135 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7136 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]));
7137 if (pRxMic)
7139 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7140 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7142 if (pTxMic)
7144 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7145 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7147 //============================================================================================
7149 // fill key material - key + TX MIC + RX MIC
7152 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7153 #ifdef RT2860
7154 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7156 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7158 #endif
7159 #ifdef RT2870
7160 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7161 #endif
7162 offset += MAX_LEN_OF_SHARE_KEY;
7163 if (pTxMic)
7165 #ifdef RT2860
7166 for (i=0; i<8; i++)
7168 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7170 #endif
7171 #ifdef RT2870
7172 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7173 #endif
7176 offset += 8;
7177 if (pRxMic)
7179 #ifdef RT2860
7180 for (i=0; i<8; i++)
7182 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7184 #endif
7185 #ifdef RT2870
7186 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7187 #endif
7192 // Update cipher algorithm. WSTA always use BSS0
7194 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7195 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7196 if ((BssIndex%2) == 0)
7198 if (KeyIdx == 0)
7199 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7200 else if (KeyIdx == 1)
7201 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7202 else if (KeyIdx == 2)
7203 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7204 else
7205 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7207 else
7209 if (KeyIdx == 0)
7210 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7211 else if (KeyIdx == 1)
7212 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7213 else if (KeyIdx == 2)
7214 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7215 else
7216 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7218 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7219 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7223 // IRQL = DISPATCH_LEVEL
7224 VOID AsicRemoveSharedKeyEntry(
7225 IN PRTMP_ADAPTER pAd,
7226 IN UCHAR BssIndex,
7227 IN UCHAR KeyIdx)
7229 //ULONG SecCsr0;
7230 SHAREDKEY_MODE_STRUC csr1;
7232 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7234 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7235 if ((BssIndex%2) == 0)
7237 if (KeyIdx == 0)
7238 csr1.field.Bss0Key0CipherAlg = 0;
7239 else if (KeyIdx == 1)
7240 csr1.field.Bss0Key1CipherAlg = 0;
7241 else if (KeyIdx == 2)
7242 csr1.field.Bss0Key2CipherAlg = 0;
7243 else
7244 csr1.field.Bss0Key3CipherAlg = 0;
7246 else
7248 if (KeyIdx == 0)
7249 csr1.field.Bss1Key0CipherAlg = 0;
7250 else if (KeyIdx == 1)
7251 csr1.field.Bss1Key1CipherAlg = 0;
7252 else if (KeyIdx == 2)
7253 csr1.field.Bss1Key2CipherAlg = 0;
7254 else
7255 csr1.field.Bss1Key3CipherAlg = 0;
7257 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7258 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7259 ASSERT(BssIndex < 4);
7260 ASSERT(KeyIdx < 4);
7265 VOID AsicUpdateWCIDAttribute(
7266 IN PRTMP_ADAPTER pAd,
7267 IN USHORT WCID,
7268 IN UCHAR BssIndex,
7269 IN UCHAR CipherAlg,
7270 IN BOOLEAN bUsePairewiseKeyTable)
7272 ULONG WCIDAttri = 0, offset;
7275 // Update WCID attribute.
7276 // Only TxKey could update WCID attribute.
7278 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7279 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7280 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7283 VOID AsicUpdateWCIDIVEIV(
7284 IN PRTMP_ADAPTER pAd,
7285 IN USHORT WCID,
7286 IN ULONG uIV,
7287 IN ULONG uEIV)
7289 ULONG offset;
7291 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7293 RTMP_IO_WRITE32(pAd, offset, uIV);
7294 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7297 VOID AsicUpdateRxWCIDTable(
7298 IN PRTMP_ADAPTER pAd,
7299 IN USHORT WCID,
7300 IN PUCHAR pAddr)
7302 ULONG offset;
7303 ULONG Addr;
7305 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7306 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7307 RTMP_IO_WRITE32(pAd, offset, Addr);
7308 Addr = pAddr[4] + (pAddr[5] << 8);
7309 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7314 ========================================================================
7316 Routine Description:
7317 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7319 Arguments:
7320 pAd Pointer to our adapter
7321 WCID WCID Entry number.
7322 BssIndex BSSID index, station or none multiple BSSID support
7323 this value should be 0.
7324 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7325 pCipherKey Pointer to Cipher Key.
7326 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7327 otherwise PairewiseKey table
7328 bTxKey This is the transmit key if enabled.
7330 Return Value:
7331 None
7333 Note:
7334 This routine will set the relative key stuff to Asic including WCID attribute,
7335 Cipher Key, Cipher algorithm and IV/EIV.
7337 IV/EIV will be update if this CipherKey is the transmission key because
7338 ASIC will base on IV's KeyID value to select Cipher Key.
7340 If bTxKey sets to FALSE, this is not the TX key, but it could be
7341 RX key
7343 For AP mode bTxKey must be always set to TRUE.
7344 ========================================================================
7346 VOID AsicAddKeyEntry(
7347 IN PRTMP_ADAPTER pAd,
7348 IN USHORT WCID,
7349 IN UCHAR BssIndex,
7350 IN UCHAR KeyIdx,
7351 IN PCIPHER_KEY pCipherKey,
7352 IN BOOLEAN bUsePairewiseKeyTable,
7353 IN BOOLEAN bTxKey)
7355 ULONG offset;
7356 UCHAR IV4 = 0;
7357 PUCHAR pKey = pCipherKey->Key;
7358 PUCHAR pTxMic = pCipherKey->TxMic;
7359 PUCHAR pRxMic = pCipherKey->RxMic;
7360 PUCHAR pTxtsc = pCipherKey->TxTsc;
7361 UCHAR CipherAlg = pCipherKey->CipherAlg;
7362 SHAREDKEY_MODE_STRUC csr1;
7363 #ifdef RT2860
7364 UCHAR i;
7365 #endif
7367 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7369 // 1.) decide key table offset
7371 if (bUsePairewiseKeyTable)
7372 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7373 else
7374 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7377 // 2.) Set Key to Asic
7379 //for (i = 0; i < KeyLen; i++)
7380 #ifdef RT2860
7381 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7383 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7385 #endif
7386 #ifdef RT2870
7387 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7388 #endif
7389 offset += MAX_LEN_OF_PEER_KEY;
7392 // 3.) Set MIC key if available
7394 if (pTxMic)
7396 #ifdef RT2860
7397 for (i = 0; i < 8; i++)
7399 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7401 #endif
7402 #ifdef RT2870
7403 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7404 #endif
7406 offset += LEN_TKIP_TXMICK;
7408 if (pRxMic)
7410 #ifdef RT2860
7411 for (i = 0; i < 8; i++)
7413 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7415 #endif
7416 #ifdef RT2870
7417 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7418 #endif
7423 // 4.) Modify IV/EIV if needs
7424 // This will force Asic to use this key ID by setting IV.
7426 if (bTxKey)
7428 #ifdef RT2860
7429 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7431 // Write IV
7433 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7434 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7435 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7437 IV4 = (KeyIdx << 6);
7438 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7439 IV4 |= 0x20; // turn on extension bit means EIV existence
7441 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7444 // Write EIV
7446 offset += 4;
7447 for (i = 0; i < 4; i++)
7449 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7452 #endif
7453 #ifdef RT2870
7454 UINT32 tmpVal;
7457 // Write IV
7459 IV4 = (KeyIdx << 6);
7460 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7461 IV4 |= 0x20; // turn on extension bit means EIV existence
7463 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7464 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7467 // Write EIV
7469 offset += 4;
7470 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7471 #endif // RT2870 //
7472 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7475 if (!bUsePairewiseKeyTable)
7478 // Only update the shared key security mode
7480 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7481 if ((BssIndex % 2) == 0)
7483 if (KeyIdx == 0)
7484 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7485 else if (KeyIdx == 1)
7486 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7487 else if (KeyIdx == 2)
7488 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7489 else
7490 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7492 else
7494 if (KeyIdx == 0)
7495 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7496 else if (KeyIdx == 1)
7497 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7498 else if (KeyIdx == 2)
7499 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7500 else
7501 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7503 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7506 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7511 ========================================================================
7512 Description:
7513 Add Pair-wise key material into ASIC.
7514 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7516 Return:
7517 ========================================================================
7519 VOID AsicAddPairwiseKeyEntry(
7520 IN PRTMP_ADAPTER pAd,
7521 IN PUCHAR pAddr,
7522 IN UCHAR WCID,
7523 IN CIPHER_KEY *pCipherKey)
7525 INT i;
7526 ULONG offset;
7527 PUCHAR pKey = pCipherKey->Key;
7528 PUCHAR pTxMic = pCipherKey->TxMic;
7529 PUCHAR pRxMic = pCipherKey->RxMic;
7530 #ifdef DBG
7531 UCHAR CipherAlg = pCipherKey->CipherAlg;
7532 #endif // DBG //
7534 // EKEY
7535 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7536 #ifdef RT2860
7537 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7539 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7541 #endif
7542 #ifdef RT2870
7543 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7544 #endif // RT2870 //
7545 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7547 UINT32 Value;
7548 RTMP_IO_READ32(pAd, offset + i, &Value);
7551 offset += MAX_LEN_OF_PEER_KEY;
7553 // MIC KEY
7554 if (pTxMic)
7556 #ifdef RT2860
7557 for (i=0; i<8; i++)
7559 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7561 #endif
7562 #ifdef RT2870
7563 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7564 #endif // RT2870 //
7566 offset += 8;
7567 if (pRxMic)
7569 #ifdef RT2860
7570 for (i=0; i<8; i++)
7572 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7574 #endif
7575 #ifdef RT2870
7576 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7577 #endif // RT2870 //
7580 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7581 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7582 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]));
7583 if (pRxMic)
7585 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7586 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7588 if (pTxMic)
7590 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7591 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7595 ========================================================================
7596 Description:
7597 Remove Pair-wise key material from ASIC.
7599 Return:
7600 ========================================================================
7602 VOID AsicRemovePairwiseKeyEntry(
7603 IN PRTMP_ADAPTER pAd,
7604 IN UCHAR BssIdx,
7605 IN UCHAR Wcid)
7607 ULONG WCIDAttri;
7608 USHORT offset;
7610 // re-set the entry's WCID attribute as OPEN-NONE.
7611 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7612 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7613 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7616 BOOLEAN AsicSendCommandToMcu(
7617 IN PRTMP_ADAPTER pAd,
7618 IN UCHAR Command,
7619 IN UCHAR Token,
7620 IN UCHAR Arg0,
7621 IN UCHAR Arg1)
7623 HOST_CMD_CSR_STRUC H2MCmd;
7624 H2M_MAILBOX_STRUC H2MMailbox;
7625 ULONG i = 0;
7629 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7630 if (H2MMailbox.field.Owner == 0)
7631 break;
7633 RTMPusecDelay(2);
7634 } while(i++ < 100);
7636 if (i > 100)
7639 #ifdef RT2860
7640 UINT32 Data;
7642 // Reset DMA
7643 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7644 Data |= 0x2;
7645 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7647 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7648 // Reset DMA/CPU ring index
7649 RTMPRingCleanUp(pAd, QID_AC_BK);
7650 RTMPRingCleanUp(pAd, QID_AC_BE);
7651 RTMPRingCleanUp(pAd, QID_AC_VI);
7652 RTMPRingCleanUp(pAd, QID_AC_VO);
7653 RTMPRingCleanUp(pAd, QID_HCCA);
7654 RTMPRingCleanUp(pAd, QID_MGMT);
7655 RTMPRingCleanUp(pAd, QID_RX);
7657 // Clear Reset
7658 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7659 Data &= 0xfffffffd;
7660 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7661 #endif /* RT2860 */
7662 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7664 //return FALSE;
7665 #ifdef RT2870
7666 return FALSE;
7667 #endif
7670 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7671 H2MMailbox.field.CmdToken = Token;
7672 H2MMailbox.field.HighByte = Arg1;
7673 H2MMailbox.field.LowByte = Arg0;
7674 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7676 H2MCmd.word = 0;
7677 H2MCmd.field.HostCommand = Command;
7678 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7680 if (Command != 0x80)
7684 return TRUE;
7687 #ifdef RT2860
7688 BOOLEAN AsicCheckCommanOk(
7689 IN PRTMP_ADAPTER pAd,
7690 IN UCHAR Command)
7692 UINT32 CmdStatus = 0, CID = 0, i;
7693 UINT32 ThisCIDMask = 0;
7695 i = 0;
7698 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7699 // Find where the command is. Because this is randomly specified by firmware.
7700 if ((CID & CID0MASK) == Command)
7702 ThisCIDMask = CID0MASK;
7703 break;
7705 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7707 ThisCIDMask = CID1MASK;
7708 break;
7710 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7712 ThisCIDMask = CID2MASK;
7713 break;
7715 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7717 ThisCIDMask = CID3MASK;
7718 break;
7721 RTMPusecDelay(100);
7722 i++;
7723 }while (i < 200);
7725 // Get CommandStatus Value
7726 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7728 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7729 if (i < 200)
7731 // If Status is 1, the comamnd is success.
7732 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7733 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7735 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7736 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7737 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7738 return TRUE;
7740 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7742 else
7744 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7746 // Clear Command and Status.
7747 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7748 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7750 return FALSE;
7752 #endif /* RT8260 */
7755 ========================================================================
7757 Routine Description:
7758 Verify the support rate for different PHY type
7760 Arguments:
7761 pAd Pointer to our adapter
7763 Return Value:
7764 None
7766 IRQL = PASSIVE_LEVEL
7768 ========================================================================
7770 VOID RTMPCheckRates(
7771 IN PRTMP_ADAPTER pAd,
7772 IN OUT UCHAR SupRate[],
7773 IN OUT UCHAR *SupRateLen)
7775 UCHAR RateIdx, i, j;
7776 UCHAR NewRate[12], NewRateLen;
7778 NewRateLen = 0;
7780 if (pAd->CommonCfg.PhyMode == PHY_11B)
7781 RateIdx = 4;
7782 else
7783 RateIdx = 12;
7785 // Check for support rates exclude basic rate bit
7786 for (i = 0; i < *SupRateLen; i++)
7787 for (j = 0; j < RateIdx; j++)
7788 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7789 NewRate[NewRateLen++] = SupRate[i];
7791 *SupRateLen = NewRateLen;
7792 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7795 BOOLEAN RTMPCheckChannel(
7796 IN PRTMP_ADAPTER pAd,
7797 IN UCHAR CentralChannel,
7798 IN UCHAR Channel)
7800 UCHAR k;
7801 UCHAR UpperChannel = 0, LowerChannel = 0;
7802 UCHAR NoEffectChannelinList = 0;
7804 // Find upper and lower channel according to 40MHz current operation.
7805 if (CentralChannel < Channel)
7807 UpperChannel = Channel;
7808 if (CentralChannel > 2)
7809 LowerChannel = CentralChannel - 2;
7810 else
7811 return FALSE;
7813 else if (CentralChannel > Channel)
7815 UpperChannel = CentralChannel + 2;
7816 LowerChannel = Channel;
7819 for (k = 0;k < pAd->ChannelListNum;k++)
7821 if (pAd->ChannelList[k].Channel == UpperChannel)
7823 NoEffectChannelinList ++;
7825 if (pAd->ChannelList[k].Channel == LowerChannel)
7827 NoEffectChannelinList ++;
7831 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7832 if (NoEffectChannelinList == 2)
7833 return TRUE;
7834 else
7835 return FALSE;
7839 ========================================================================
7841 Routine Description:
7842 Verify the support rate for HT phy type
7844 Arguments:
7845 pAd Pointer to our adapter
7847 Return Value:
7848 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7850 IRQL = PASSIVE_LEVEL
7852 ========================================================================
7854 BOOLEAN RTMPCheckHt(
7855 IN PRTMP_ADAPTER pAd,
7856 IN UCHAR Wcid,
7857 IN HT_CAPABILITY_IE *pHtCapability,
7858 IN ADD_HT_INFO_IE *pAddHtInfo)
7860 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7861 return FALSE;
7863 // If use AMSDU, set flag.
7864 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7865 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7866 // Save Peer Capability
7867 if (pHtCapability->HtCapInfo.ShortGIfor20)
7868 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7869 if (pHtCapability->HtCapInfo.ShortGIfor40)
7870 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7871 if (pHtCapability->HtCapInfo.TxSTBC)
7872 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7873 if (pHtCapability->HtCapInfo.RxSTBC)
7874 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7875 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7877 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7880 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7882 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7885 // Will check ChannelWidth for MCSSet[4] below
7886 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7887 switch (pAd->CommonCfg.RxStream)
7889 case 1:
7890 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7891 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7892 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7893 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7894 break;
7895 case 2:
7896 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7897 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7898 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7899 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7900 break;
7901 case 3:
7902 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7903 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7904 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7905 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7906 break;
7909 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7911 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7912 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7913 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7915 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7917 // Send Assoc Req with my HT capability.
7918 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7919 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7920 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7921 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7922 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7923 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7924 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7925 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7926 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7927 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7928 if (pAd->CommonCfg.bRdg)
7930 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7931 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7934 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7935 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7937 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7938 return TRUE;
7942 ========================================================================
7944 Routine Description:
7945 Verify the support rate for different PHY type
7947 Arguments:
7948 pAd Pointer to our adapter
7950 Return Value:
7951 None
7953 IRQL = PASSIVE_LEVEL
7955 ========================================================================
7957 VOID RTMPUpdateMlmeRate(
7958 IN PRTMP_ADAPTER pAd)
7960 UCHAR MinimumRate;
7961 UCHAR ProperMlmeRate; //= RATE_54;
7962 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7963 BOOLEAN bMatch = FALSE;
7965 switch (pAd->CommonCfg.PhyMode)
7967 case PHY_11B:
7968 ProperMlmeRate = RATE_11;
7969 MinimumRate = RATE_1;
7970 break;
7971 case PHY_11BG_MIXED:
7972 case PHY_11ABGN_MIXED:
7973 case PHY_11BGN_MIXED:
7974 if ((pAd->MlmeAux.SupRateLen == 4) &&
7975 (pAd->MlmeAux.ExtRateLen == 0))
7976 // B only AP
7977 ProperMlmeRate = RATE_11;
7978 else
7979 ProperMlmeRate = RATE_24;
7981 if (pAd->MlmeAux.Channel <= 14)
7982 MinimumRate = RATE_1;
7983 else
7984 MinimumRate = RATE_6;
7985 break;
7986 case PHY_11A:
7987 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7988 case PHY_11GN_MIXED:
7989 case PHY_11AGN_MIXED:
7990 case PHY_11AN_MIXED:
7991 case PHY_11N_5G:
7992 ProperMlmeRate = RATE_24;
7993 MinimumRate = RATE_6;
7994 break;
7995 case PHY_11ABG_MIXED:
7996 ProperMlmeRate = RATE_24;
7997 if (pAd->MlmeAux.Channel <= 14)
7998 MinimumRate = RATE_1;
7999 else
8000 MinimumRate = RATE_6;
8001 break;
8002 default: // error
8003 ProperMlmeRate = RATE_1;
8004 MinimumRate = RATE_1;
8005 break;
8008 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8010 for (j = 0; j < RateIdx; j++)
8012 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8014 if (j == ProperMlmeRate)
8016 bMatch = TRUE;
8017 break;
8022 if (bMatch)
8023 break;
8026 if (bMatch == FALSE)
8028 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8030 for (j = 0; j < RateIdx; j++)
8032 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8034 if (j == ProperMlmeRate)
8036 bMatch = TRUE;
8037 break;
8042 if (bMatch)
8043 break;
8047 if (bMatch == FALSE)
8049 ProperMlmeRate = MinimumRate;
8052 pAd->CommonCfg.MlmeRate = MinimumRate;
8053 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8054 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8056 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8057 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8058 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8059 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8061 else
8063 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8064 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8065 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8066 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8069 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8072 CHAR RTMPMaxRssi(
8073 IN PRTMP_ADAPTER pAd,
8074 IN CHAR Rssi0,
8075 IN CHAR Rssi1,
8076 IN CHAR Rssi2)
8078 CHAR larger = -127;
8080 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8082 larger = Rssi0;
8085 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8087 larger = max(Rssi0, Rssi1);
8090 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8092 larger = max(larger, Rssi2);
8095 if (larger == -127)
8096 larger = 0;
8098 return larger;
8101 #ifdef RT30xx
8102 // Antenna divesity use GPIO3 and EESK pin for control
8103 // Antenna and EEPROM access are both using EESK pin,
8104 // Therefor we should avoid accessing EESK at the same time
8105 // Then restore antenna after EEPROM access
8106 VOID AsicSetRxAnt(
8107 IN PRTMP_ADAPTER pAd,
8108 IN UCHAR Ant)
8110 UINT32 Value;
8111 UINT32 x;
8113 if ((pAd->EepromAccess) ||
8114 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8115 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8116 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8117 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8119 return;
8122 // the antenna selection is through firmware and MAC register(GPIO3)
8123 if (Ant == 0)
8125 // Main antenna
8126 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8127 x |= (EESK);
8128 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8130 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8131 Value &= ~(0x0808);
8132 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8133 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8135 else
8137 // Aux antenna
8138 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8139 x &= ~(EESK);
8140 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8142 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8143 Value &= ~(0x0808);
8144 Value |= 0x08;
8145 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8146 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8149 #endif /* RT30xx */
8152 ========================================================================
8153 Routine Description:
8154 Periodic evaluate antenna link status
8156 Arguments:
8157 pAd - Adapter pointer
8159 Return Value:
8160 None
8162 ========================================================================
8164 VOID AsicEvaluateRxAnt(
8165 IN PRTMP_ADAPTER pAd)
8167 UCHAR BBPR3 = 0;
8169 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8170 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8171 fRTMP_ADAPTER_RADIO_OFF |
8172 fRTMP_ADAPTER_NIC_NOT_EXIST |
8173 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
8174 || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8175 #ifdef RT30xx
8176 || (pAd->EepromAccess)
8177 #endif
8179 return;
8181 #ifdef RT30xx
8182 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8183 // one is antenna diversity:there is only one antenna can rx and tx
8184 // the other is failed antenna remove:two physical antenna can rx and tx
8185 if (pAd->NicConfig2.field.AntDiversity)
8187 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8188 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8190 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8192 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8193 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8194 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8196 // a one-shot timer to end the evalution
8197 // dynamic adjust antenna evaluation period according to the traffic
8198 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8199 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8200 else
8201 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8203 else
8204 #endif
8206 if (pAd->StaCfg.Psm == PWR_SAVE)
8207 return;
8209 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8210 BBPR3 &= (~0x18);
8211 if(pAd->Antenna.field.RxPath == 3)
8213 BBPR3 |= (0x10);
8215 else if(pAd->Antenna.field.RxPath == 2)
8217 BBPR3 |= (0x8);
8219 else if(pAd->Antenna.field.RxPath == 1)
8221 BBPR3 |= (0x0);
8223 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8225 #ifdef RT2860
8226 pAd->StaCfg.BBPR3 = BBPR3;
8227 #endif
8230 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8233 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8234 pAd->RalinkCounters.OneSecTxRetryOkCount +
8235 pAd->RalinkCounters.OneSecTxFailCount;
8237 // dynamic adjust antenna evaluation period according to the traffic
8238 if (TxTotalCnt > 50)
8240 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8241 pAd->Mlme.bLowThroughput = FALSE;
8243 else
8245 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8246 pAd->Mlme.bLowThroughput = TRUE;
8252 ========================================================================
8253 Routine Description:
8254 After evaluation, check antenna link status
8256 Arguments:
8257 pAd - Adapter pointer
8259 Return Value:
8260 None
8262 ========================================================================
8264 VOID AsicRxAntEvalTimeout(
8265 IN PVOID SystemSpecific1,
8266 IN PVOID FunctionContext,
8267 IN PVOID SystemSpecific2,
8268 IN PVOID SystemSpecific3)
8270 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8271 UCHAR BBPR3 = 0;
8272 CHAR larger = -127, rssi0, rssi1, rssi2;
8274 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8275 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8276 fRTMP_ADAPTER_RADIO_OFF |
8277 fRTMP_ADAPTER_NIC_NOT_EXIST)
8278 || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8279 #ifdef RT30xx
8280 || (pAd->EepromAccess)
8281 #endif // RT30xx //
8283 return;
8286 #ifdef RT30xx
8287 if (pAd->NicConfig2.field.AntDiversity)
8289 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8291 UCHAR temp;
8294 // select PrimaryRxAntPair
8295 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8296 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8298 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8299 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8300 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8302 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8303 pAd->RxAnt.EvaluateStableCnt = 0;
8305 else
8307 // if the evaluated antenna is not better than original, switch back to original antenna
8308 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8309 pAd->RxAnt.EvaluateStableCnt ++;
8312 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8314 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8315 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8317 else
8318 #endif
8320 if (pAd->StaCfg.Psm == PWR_SAVE)
8321 return;
8323 // if the traffic is low, use average rssi as the criteria
8324 if (pAd->Mlme.bLowThroughput == TRUE)
8326 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8327 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8328 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8330 else
8332 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8333 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8334 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8337 if(pAd->Antenna.field.RxPath == 3)
8339 larger = max(rssi0, rssi1);
8341 if (larger > (rssi2 + 20))
8342 pAd->Mlme.RealRxPath = 2;
8343 else
8344 pAd->Mlme.RealRxPath = 3;
8346 else if(pAd->Antenna.field.RxPath == 2)
8348 if (rssi0 > (rssi1 + 20))
8349 pAd->Mlme.RealRxPath = 1;
8350 else
8351 pAd->Mlme.RealRxPath = 2;
8354 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8355 BBPR3 &= (~0x18);
8356 if(pAd->Mlme.RealRxPath == 3)
8358 BBPR3 |= (0x10);
8360 else if(pAd->Mlme.RealRxPath == 2)
8362 BBPR3 |= (0x8);
8364 else if(pAd->Mlme.RealRxPath == 1)
8366 BBPR3 |= (0x0);
8368 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8369 #ifdef RT2860
8370 pAd->StaCfg.BBPR3 = BBPR3;
8371 #endif
8376 VOID APSDPeriodicExec(
8377 IN PVOID SystemSpecific1,
8378 IN PVOID FunctionContext,
8379 IN PVOID SystemSpecific2,
8380 IN PVOID SystemSpecific3)
8382 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8384 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8385 return;
8387 pAd->CommonCfg.TriggerTimerCount++;
8392 ========================================================================
8393 Routine Description:
8394 Set/reset MAC registers according to bPiggyBack parameter
8396 Arguments:
8397 pAd - Adapter pointer
8398 bPiggyBack - Enable / Disable Piggy-Back
8400 Return Value:
8401 None
8403 ========================================================================
8405 VOID RTMPSetPiggyBack(
8406 IN PRTMP_ADAPTER pAd,
8407 IN BOOLEAN bPiggyBack)
8409 TX_LINK_CFG_STRUC TxLinkCfg;
8411 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8413 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8414 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8418 ========================================================================
8419 Routine Description:
8420 check if this entry need to switch rate automatically
8422 Arguments:
8424 pEntry
8426 Return Value:
8427 TURE
8428 FALSE
8430 ========================================================================
8432 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8433 IN PRTMP_ADAPTER pAd,
8434 IN PMAC_TABLE_ENTRY pEntry)
8436 BOOLEAN result = TRUE;
8439 // only associated STA counts
8440 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8442 result = pAd->StaCfg.bAutoTxRateSwitch;
8444 else
8445 result = FALSE;
8448 return result;
8452 BOOLEAN RTMPAutoRateSwitchCheck(
8453 IN PRTMP_ADAPTER pAd)
8455 if (pAd->StaCfg.bAutoTxRateSwitch)
8456 return TRUE;
8458 return FALSE;
8463 ========================================================================
8464 Routine Description:
8465 check if this entry need to fix tx legacy rate
8467 Arguments:
8469 pEntry
8471 Return Value:
8472 TURE
8473 FALSE
8475 ========================================================================
8477 UCHAR RTMPStaFixedTxMode(
8478 IN PRTMP_ADAPTER pAd,
8479 IN PMAC_TABLE_ENTRY pEntry)
8481 UCHAR tx_mode = FIXED_TXMODE_HT;
8483 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8485 return tx_mode;
8489 ========================================================================
8490 Routine Description:
8491 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8493 Arguments:
8495 pEntry
8497 Return Value:
8498 TURE
8499 FALSE
8501 ========================================================================
8503 VOID RTMPUpdateLegacyTxSetting(
8504 UCHAR fixed_tx_mode,
8505 PMAC_TABLE_ENTRY pEntry)
8507 HTTRANSMIT_SETTING TransmitSetting;
8509 if (fixed_tx_mode == FIXED_TXMODE_HT)
8510 return;
8512 TransmitSetting.word = 0;
8514 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8515 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8517 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8519 TransmitSetting.field.MODE = MODE_CCK;
8520 // CCK mode allow MCS 0~3
8521 if (TransmitSetting.field.MCS > MCS_3)
8522 TransmitSetting.field.MCS = MCS_3;
8524 else
8526 TransmitSetting.field.MODE = MODE_OFDM;
8527 // OFDM mode allow MCS 0~7
8528 if (TransmitSetting.field.MCS > MCS_7)
8529 TransmitSetting.field.MCS = MCS_7;
8532 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8534 pEntry->HTPhyMode.word = TransmitSetting.word;
8535 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8536 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8541 ==========================================================================
8542 Description:
8543 dynamic tune BBP R66 to find a balance between sensibility and
8544 noise isolation
8546 IRQL = DISPATCH_LEVEL
8548 ==========================================================================
8550 VOID AsicStaBbpTuning(
8551 IN PRTMP_ADAPTER pAd)
8553 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8554 CHAR Rssi;
8556 // 2860C did not support Fase CCA, therefore can't tune
8557 if (pAd->MACVersion == 0x28600100)
8558 return;
8561 // work as a STA
8563 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8564 return;
8566 if ((pAd->OpMode == OPMODE_STA)
8567 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8569 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8570 #ifdef RT2860
8571 && (pAd->bPCIclkOff == FALSE))
8572 #endif
8573 #ifdef RT2870
8575 #endif
8577 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8578 R66 = OrigR66Value;
8580 if (pAd->Antenna.field.RxPath > 1)
8581 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8582 else
8583 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8585 if (pAd->LatchRfRegs.Channel <= 14)
8586 { //BG band
8587 #ifdef RT2870
8588 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8589 // Otherwise, it will have some throughput side effect when low RSSI
8590 #ifndef RT30xx
8591 if (IS_RT3070(pAd))
8592 #endif
8593 #ifdef RT30xx
8594 if (IS_RT30xx(pAd))
8595 #endif
8597 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8599 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8600 if (OrigR66Value != R66)
8601 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8603 else
8605 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8606 if (OrigR66Value != R66)
8607 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8610 else
8611 #endif // RT2870 //
8613 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8615 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8616 if (OrigR66Value != R66)
8618 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8621 else
8623 R66 = 0x2E + GET_LNA_GAIN(pAd);
8624 if (OrigR66Value != R66)
8626 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8631 else
8632 { //A band
8633 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8635 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8637 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8638 if (OrigR66Value != R66)
8640 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8643 else
8645 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8646 if (OrigR66Value != R66)
8648 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8652 else
8654 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8656 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8657 if (OrigR66Value != R66)
8659 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8662 else
8664 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8665 if (OrigR66Value != R66)
8667 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8677 #ifdef RT2860
8678 VOID AsicResetFromDMABusy(
8679 IN PRTMP_ADAPTER pAd)
8681 UINT32 Data;
8682 BOOLEAN bCtrl = FALSE;
8684 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8686 // Be sure restore link control value so we can write register.
8687 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8688 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8690 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8691 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8692 RTMPusecDelay(6000);
8693 pAd->bPCIclkOff = FALSE;
8694 bCtrl = TRUE;
8696 // Reset DMA
8697 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8698 Data |= 0x2;
8699 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8701 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8702 // Reset DMA/CPU ring index
8703 RTMPRingCleanUp(pAd, QID_AC_BK);
8704 RTMPRingCleanUp(pAd, QID_AC_BE);
8705 RTMPRingCleanUp(pAd, QID_AC_VI);
8706 RTMPRingCleanUp(pAd, QID_AC_VO);
8707 RTMPRingCleanUp(pAd, QID_HCCA);
8708 RTMPRingCleanUp(pAd, QID_MGMT);
8709 RTMPRingCleanUp(pAd, QID_RX);
8711 // Clear Reset
8712 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8713 Data &= 0xfffffffd;
8714 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8716 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8717 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8718 RTMPPCIeLinkCtrlSetting(pAd, 3);
8720 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8721 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8722 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8725 VOID AsicResetBBP(
8726 IN PRTMP_ADAPTER pAd)
8728 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8730 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8731 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8732 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8734 // After hard-reset BBP, initialize all BBP values.
8735 NICRestoreBBPValue(pAd);
8736 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8739 VOID AsicResetMAC(
8740 IN PRTMP_ADAPTER pAd)
8742 ULONG Data;
8744 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8745 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8746 Data |= 0x4;
8747 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8748 Data &= 0xfffffffb;
8749 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8751 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8754 VOID AsicResetPBF(
8755 IN PRTMP_ADAPTER pAd)
8757 ULONG Value1, Value2;
8758 ULONG Data;
8760 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8761 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8763 Value2 &= 0xff;
8764 // sum should be equals to 0xff, which is the total buffer size.
8765 if ((Value1 + Value2) < 0xff)
8767 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8768 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8769 Data |= 0x8;
8770 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8771 Data &= 0xfffffff7;
8772 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8774 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8777 #endif /* RT2860 */
8779 VOID RTMPSetAGCInitValue(
8780 IN PRTMP_ADAPTER pAd,
8781 IN UCHAR BandWidth)
8783 UCHAR R66 = 0x30;
8785 if (pAd->LatchRfRegs.Channel <= 14)
8786 { // BG band
8787 R66 = 0x2E + GET_LNA_GAIN(pAd);
8788 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8790 else
8791 { //A band
8792 if (BandWidth == BW_20)
8794 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8795 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8797 else
8799 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8800 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8806 VOID AsicTurnOffRFClk(
8807 IN PRTMP_ADAPTER pAd,
8808 IN UCHAR Channel)
8811 // RF R2 bit 18 = 0
8812 UINT32 R1 = 0, R2 = 0, R3 = 0;
8813 UCHAR index;
8814 RTMP_RF_REGS *RFRegTable;
8816 // The RF programming sequence is difference between 3xxx and 2xxx
8817 if (IS_RT3090(pAd))
8819 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8820 return;
8823 RFRegTable = RF2850RegTable;
8825 switch (pAd->RfIcType)
8827 case RFIC_2820:
8828 case RFIC_2850:
8829 case RFIC_2720:
8830 case RFIC_2750:
8832 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8834 if (Channel == RFRegTable[index].Channel)
8836 R1 = RFRegTable[index].R1 & 0xffffdfff;
8837 R2 = RFRegTable[index].R2 & 0xfffbffff;
8838 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8840 RTMP_RF_IO_WRITE32(pAd, R1);
8841 RTMP_RF_IO_WRITE32(pAd, R2);
8843 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8844 // Set RF R2 bit18=0, R3 bit[18:19]=0
8845 //if (pAd->StaCfg.bRadio == FALSE)
8846 if (1)
8848 RTMP_RF_IO_WRITE32(pAd, R3);
8850 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8851 Channel, pAd->RfIcType, R2, R3));
8853 else
8854 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8855 Channel, pAd->RfIcType, R2));
8856 break;
8859 break;
8861 default:
8862 break;
8867 VOID AsicTurnOnRFClk(
8868 IN PRTMP_ADAPTER pAd,
8869 IN UCHAR Channel)
8872 // RF R2 bit 18 = 0
8873 UINT32 R1 = 0, R2 = 0, R3 = 0;
8874 UCHAR index;
8875 RTMP_RF_REGS *RFRegTable;
8877 // The RF programming sequence is difference between 3xxx and 2xxx
8878 if (IS_RT3090(pAd))
8879 return;
8881 RFRegTable = RF2850RegTable;
8883 switch (pAd->RfIcType)
8885 case RFIC_2820:
8886 case RFIC_2850:
8887 case RFIC_2720:
8888 case RFIC_2750:
8890 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8892 if (Channel == RFRegTable[index].Channel)
8894 R3 = pAd->LatchRfRegs.R3;
8895 R3 &= 0xfff3ffff;
8896 R3 |= 0x00080000;
8897 RTMP_RF_IO_WRITE32(pAd, R3);
8899 R1 = RFRegTable[index].R1;
8900 RTMP_RF_IO_WRITE32(pAd, R1);
8902 R2 = RFRegTable[index].R2;
8903 if (pAd->Antenna.field.TxPath == 1)
8905 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8908 if (pAd->Antenna.field.RxPath == 2)
8910 R2 |= 0x40; // write 1 to off Rxpath.
8912 else if (pAd->Antenna.field.RxPath == 1)
8914 R2 |= 0x20040; // write 1 to off RxPath
8916 RTMP_RF_IO_WRITE32(pAd, R2);
8918 break;
8921 break;
8923 default:
8924 break;
8927 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8928 Channel,
8929 pAd->RfIcType,
8930 R2));