blob: d1c0a822c086488a7dc463d7be662ea008a8e025 [file] [log] [blame]
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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 *************************************************************************
26
27 Module Name:
28 mlme.c
29
30 Abstract:
31
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
37*/
38
39#include "../rt_config.h"
40#include <stdarg.h>
41
42UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
43
44UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53#ifdef CONFIG_STA_SUPPORT
54#ifdef DOT11_N_SUPPORT
55UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56#endif // DOT11_N_SUPPORT //
57#endif // CONFIG_STA_SUPPORT //
58
59UCHAR RateSwitchTable[] = {
60// 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)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
72 0x0a, 0x21, 6, 8, 25,
73 0x0b, 0x21, 7, 8, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
79 0x11, 0x00, 0, 0, 0,
80 0x12, 0x00, 0, 0, 0,
81 0x13, 0x00, 0, 0, 0,
82 0x14, 0x00, 0, 0, 0,
83 0x15, 0x00, 0, 0, 0,
84 0x16, 0x00, 0, 0, 0,
85 0x17, 0x00, 0, 0, 0,
86 0x18, 0x00, 0, 0, 0,
87 0x19, 0x00, 0, 0, 0,
88 0x1a, 0x00, 0, 0, 0,
89 0x1b, 0x00, 0, 0, 0,
90 0x1c, 0x00, 0, 0, 0,
91 0x1d, 0x00, 0, 0, 0,
92 0x1e, 0x00, 0, 0, 0,
93 0x1f, 0x00, 0, 0, 0,
94};
95
96UCHAR RateSwitchTable11B[] = {
97// 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)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
103};
104
105UCHAR RateSwitchTable11BG[] = {
106// 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)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
118};
119
120UCHAR RateSwitchTable11G[] = {
121// 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)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
131};
132
133#ifdef DOT11_N_SUPPORT
134UCHAR RateSwitchTable11N1S[] = {
135// 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)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
146};
147
148UCHAR RateSwitchTable11N2S[] = {
149// 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)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
161};
162
163UCHAR RateSwitchTable11N3S[] = {
164// 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)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
176};
177
178UCHAR RateSwitchTable11N2SForABand[] = {
179// 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)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
192};
193
194UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195// 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)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
208};
209
210UCHAR RateSwitchTable11BGN1S[] = {
211// 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)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
226};
227
228UCHAR RateSwitchTable11BGN2S[] = {
229// 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)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
241};
242
243UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244// 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)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
251 0x05, 0x20, 20, 15, 30,
252 0x06, 0x20, 21, 8, 20,
253 0x07, 0x20, 22, 8, 20,
254 0x08, 0x20, 23, 8, 25,
255 0x09, 0x22, 23, 8, 25,
256};
257
258UCHAR RateSwitchTable11BGN2SForABand[] = {
259// 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)
260 0x0b, 0x09, 0, 0, 0, // Initial used item after association
261 0x00, 0x21, 0, 30,101, //50
262 0x01, 0x21, 1, 20, 50,
263 0x02, 0x21, 2, 20, 50,
264 0x03, 0x21, 3, 15, 50,
265 0x04, 0x21, 4, 15, 30,
266 0x05, 0x21, 5, 15, 30,
267 0x06, 0x20, 12, 15, 30,
268 0x07, 0x20, 13, 8, 20,
269 0x08, 0x20, 14, 8, 20,
270 0x09, 0x20, 15, 8, 25,
271 0x0a, 0x22, 15, 8, 25,
272};
273
274UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
275// 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)
276 0x0c, 0x09, 0, 0, 0, // Initial used item after association
277 0x00, 0x21, 0, 30,101, //50
278 0x01, 0x21, 1, 20, 50,
279 0x02, 0x21, 2, 20, 50,
280 0x03, 0x21, 3, 15, 50,
281 0x04, 0x21, 4, 15, 30,
282 0x05, 0x21, 5, 15, 30,
283 0x06, 0x21, 12, 15, 30,
284 0x07, 0x20, 20, 15, 30,
285 0x08, 0x20, 21, 8, 20,
286 0x09, 0x20, 22, 8, 20,
287 0x0a, 0x20, 23, 8, 25,
288 0x0b, 0x22, 23, 8, 25,
289};
290#endif // DOT11_N_SUPPORT //
291
292PUCHAR ReasonString[] = {
293 /* 0 */ "Reserved",
294 /* 1 */ "Unspecified Reason",
295 /* 2 */ "Previous Auth no longer valid",
296 /* 3 */ "STA is leaving / has left",
297 /* 4 */ "DIS-ASSOC due to inactivity",
298 /* 5 */ "AP unable to hanle all associations",
299 /* 6 */ "class 2 error",
300 /* 7 */ "class 3 error",
301 /* 8 */ "STA is leaving / has left",
302 /* 9 */ "require auth before assoc/re-assoc",
303 /* 10 */ "Reserved",
304 /* 11 */ "Reserved",
305 /* 12 */ "Reserved",
306 /* 13 */ "invalid IE",
307 /* 14 */ "MIC error",
308 /* 15 */ "4-way handshake timeout",
309 /* 16 */ "2-way (group key) handshake timeout",
310 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
311 /* 18 */
312};
313
314extern UCHAR OfdmRateToRxwiMCS[];
315// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
316// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
317ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
318 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
319 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
320
321UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
322UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
323UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
324
325// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
326// this value, then it's quaranteed capable of operating in 36 mbps TX rate in
327// clean environment.
328// TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
329CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
330
331UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
332USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
333
334UCHAR SsidIe = IE_SSID;
335UCHAR SupRateIe = IE_SUPP_RATES;
336UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
337#ifdef DOT11_N_SUPPORT
338UCHAR HtCapIe = IE_HT_CAP;
339UCHAR AddHtInfoIe = IE_ADD_HT;
340UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
341#ifdef DOT11N_DRAFT3
342UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
343#endif // DOT11N_DRAFT3 //
344#endif // DOT11_N_SUPPORT //
345UCHAR ErpIe = IE_ERP;
346UCHAR DsIe = IE_DS_PARM;
347UCHAR TimIe = IE_TIM;
348UCHAR WpaIe = IE_WPA;
349UCHAR Wpa2Ie = IE_WPA2;
350UCHAR IbssIe = IE_IBSS_PARM;
351UCHAR Ccx2Ie = IE_CCX_V2;
352
353extern UCHAR WPA_OUI[];
354
355UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
356
357UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
358 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
359
360// Reset the RFIC setting to new series
361RTMP_RF_REGS RF2850RegTable[] = {
362// ch R1 R2 R3(TX0~4=0) R4
363 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
364 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
365 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
366 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
367 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
368 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
369 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
370 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
371 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
372 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
373 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
374 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
375 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
376 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
377
378 // 802.11 UNI / HyperLan 2
379 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
380 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
381 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
382 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
383 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
384 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
385 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
386 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
387 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
388 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
389 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
390 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
391
392 // 802.11 HyperLan 2
393 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
394
395 // 2008.04.30 modified
396 // The system team has AN to improve the EVM value
397 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
398 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
399 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
400 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
401
402 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
403 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
404 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
405 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
406 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
407 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
408 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
409 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
410 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
411 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
412 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
413 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
414
415 // 802.11 UNII
416 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
417 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
418 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
419 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
420 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
421 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
422 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
423
424 // Japan
425 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
426 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
427 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
428 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
429 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
430 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
431 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
432
433 // still lack of MMAC(Japan) ch 34,38,42,46
434};
435UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
436
437FREQUENCY_ITEM FreqItems3020[] =
438{
439 /**************************************************/
440 // ISM : 2.4 to 2.483 GHz //
441 /**************************************************/
442 // 11g
443 /**************************************************/
444 //-CH---N-------R---K-----------
445 {1, 241, 2, 2},
446 {2, 241, 2, 7},
447 {3, 242, 2, 2},
448 {4, 242, 2, 7},
449 {5, 243, 2, 2},
450 {6, 243, 2, 7},
451 {7, 244, 2, 2},
452 {8, 244, 2, 7},
453 {9, 245, 2, 2},
454 {10, 245, 2, 7},
455 {11, 246, 2, 2},
456 {12, 246, 2, 7},
457 {13, 247, 2, 2},
458 {14, 248, 2, 4},
459};
460#define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
461
462/*
463 ==========================================================================
464 Description:
465 initialize the MLME task and its data structure (queue, spinlock,
466 timer, state machines).
467
468 IRQL = PASSIVE_LEVEL
469
470 Return:
471 always return NDIS_STATUS_SUCCESS
472
473 ==========================================================================
474*/
475NDIS_STATUS MlmeInit(
476 IN PRTMP_ADAPTER pAd)
477{
478 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
479
480 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
481
482 do
483 {
484 Status = MlmeQueueInit(&pAd->Mlme.Queue);
485 if(Status != NDIS_STATUS_SUCCESS)
486 break;
487
488 pAd->Mlme.bRunning = FALSE;
489 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
490
491#ifdef CONFIG_STA_SUPPORT
492 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
493 {
494 BssTableInit(&pAd->ScanTab);
495
496 // init STA state machines
497 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
498 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
499 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
500 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
501 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
502 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
503
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700504 // Since we are using switch/case to implement it, the init is different from the above
505 // state machine init
506 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
507 }
508#endif // CONFIG_STA_SUPPORT //
509
510
511
512 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
513
514 // Init mlme periodic timer
515 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
516
517 // Set mlme periodic timer
518 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
519
520 // software-based RX Antenna diversity
521 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
522
523
524#ifdef CONFIG_STA_SUPPORT
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700525 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
526 {
527 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
528 {
529 // only PCIe cards need these two timers
530 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
531 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
532 }
533 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700534#endif // CONFIG_STA_SUPPORT //
535
536 } while (FALSE);
537
538 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
539
540 return Status;
541}
542
543/*
544 ==========================================================================
545 Description:
546 main loop of the MLME
547 Pre:
548 Mlme has to be initialized, and there are something inside the queue
549 Note:
550 This function is invoked from MPSetInformation and MPReceive;
551 This task guarantee only one MlmeHandler will run.
552
553 IRQL = DISPATCH_LEVEL
554
555 ==========================================================================
556 */
557VOID MlmeHandler(
558 IN PRTMP_ADAPTER pAd)
559{
560 MLME_QUEUE_ELEM *Elem = NULL;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700561
562 // Only accept MLME and Frame from peer side, no other (control/data) frame should
563 // get into this state machine
564
565 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
566 if(pAd->Mlme.bRunning)
567 {
568 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
569 return;
570 }
571 else
572 {
573 pAd->Mlme.bRunning = TRUE;
574 }
575 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
576
577 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
578 {
579 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
580 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
581 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
582 {
583 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
584 break;
585 }
586
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700587 //From message type, determine which state machine I should drive
588 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
589 {
590
591 // if dequeue success
592 switch (Elem->Machine)
593 {
594 // STA state machines
595#ifdef CONFIG_STA_SUPPORT
596 case ASSOC_STATE_MACHINE:
597 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
598 break;
599 case AUTH_STATE_MACHINE:
600 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
601 break;
602 case AUTH_RSP_STATE_MACHINE:
603 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
604 break;
605 case SYNC_STATE_MACHINE:
606 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
607 break;
608 case MLME_CNTL_STATE_MACHINE:
609 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
610 break;
611 case WPA_PSK_STATE_MACHINE:
612 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
613 break;
614#ifdef LEAP_SUPPORT
615 case LEAP_STATE_MACHINE:
616 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
617 break;
618#endif
619 case AIRONET_STATE_MACHINE:
620 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
621 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700622#endif // CONFIG_STA_SUPPORT //
623
624 case ACTION_STATE_MACHINE:
625 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
626 break;
627
628
629
630
631 default:
632 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
633 break;
634 } // end of switch
635
636 // free MLME element
637 Elem->Occupied = FALSE;
638 Elem->MsgLen = 0;
639
640 }
641 else {
642 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
643 }
644 }
645
646 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
647 pAd->Mlme.bRunning = FALSE;
648 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
649}
650
651/*
652 ==========================================================================
653 Description:
654 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
655 Parameters:
656 Adapter - NIC Adapter pointer
657 Post:
658 The MLME task will no longer work properly
659
660 IRQL = PASSIVE_LEVEL
661
662 ==========================================================================
663 */
664VOID MlmeHalt(
665 IN PRTMP_ADAPTER pAd)
666{
667 BOOLEAN Cancelled;
668
669 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
670
671 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
672 {
673 // disable BEACON generation and other BEACON related hardware timers
674 AsicDisableSync(pAd);
675 }
676
677#ifdef CONFIG_STA_SUPPORT
678 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
679 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700680 // Cancel pending timers
681 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
682 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
683 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
684 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
685 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
686 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700687 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
688 {
689 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
690 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
691 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700692 }
693#endif // CONFIG_STA_SUPPORT //
694
695 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
696 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
697
698
699
700 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
701 {
702 // Set LED
703 RTMPSetLED(pAd, LED_HALT);
704 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
705 }
706
707 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
708
709 MlmeQueueDestroy(&pAd->Mlme.Queue);
710 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
711
712 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
713}
714
715VOID MlmeResetRalinkCounters(
716 IN PRTMP_ADAPTER pAd)
717{
718 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
719 // clear all OneSecxxx counters.
720 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
721 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
722 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
723 pAd->RalinkCounters.OneSecRxOkCnt = 0;
724 pAd->RalinkCounters.OneSecTxFailCount = 0;
725 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
726 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
727 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
728
729 // TODO: for debug only. to be removed
730 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
731 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
732 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
733 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
734 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
735 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
736 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
737 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
738 pAd->RalinkCounters.OneSecTxDoneCount = 0;
739 pAd->RalinkCounters.OneSecRxCount = 0;
740 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
741 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
742
743 return;
744}
745
746unsigned long rx_AMSDU;
747unsigned long rx_Total;
748
749/*
750 ==========================================================================
751 Description:
752 This routine is executed periodically to -
753 1. Decide if it's a right time to turn on PwrMgmt bit of all
754 outgoiing frames
755 2. Calculate ChannelQuality based on statistics of the last
756 period, so that TX rate won't toggling very frequently between a
757 successful TX and a failed TX.
758 3. If the calculated ChannelQuality indicated current connection not
759 healthy, then a ROAMing attempt is tried here.
760
761 IRQL = DISPATCH_LEVEL
762
763 ==========================================================================
764 */
765#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
766VOID MlmePeriodicExec(
767 IN PVOID SystemSpecific1,
768 IN PVOID FunctionContext,
769 IN PVOID SystemSpecific2,
770 IN PVOID SystemSpecific3)
771{
772 ULONG TxTotalCnt;
773 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
774
Adam McDanieled291e82009-02-23 08:01:07 -0700775 //Baron 2008/07/10
776 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
777 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
778 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
779 if(pAd->StaCfg.WepStatus<2)
780 {
781 pAd->StaCfg.WpaSupplicantUP = 0;
782 }
783 else
784 {
785 pAd->StaCfg.WpaSupplicantUP = 1;
786 }
787
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700788#ifdef CONFIG_STA_SUPPORT
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700789 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
790 {
791 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
792 // Move code to here, because following code will return when radio is off
Adam McDanieled291e82009-02-23 08:01:07 -0700793 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
794 (pAd->StaCfg.bHardwareRadio == TRUE) &&
795 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700796 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
Adam McDanieled291e82009-02-23 08:01:07 -0700797 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700798 {
799 UINT32 data = 0;
800
801 // Read GPIO pin2 as Hardware controlled radio state
Adam McDanieled291e82009-02-23 08:01:07 -0700802 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700803 if (data & 0x04)
804 {
805 pAd->StaCfg.bHwRadio = TRUE;
806 }
807 else
808 {
809 pAd->StaCfg.bHwRadio = FALSE;
810 }
811 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
812 {
813 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
814 if (pAd->StaCfg.bRadio == TRUE)
815 {
816 MlmeRadioOn(pAd);
817 // Update extra information
818 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
819 }
820 else
821 {
822 MlmeRadioOff(pAd);
823 // Update extra information
824 pAd->ExtraInfo = HW_RADIO_OFF;
825 }
826 }
827 }
828 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700829#endif // CONFIG_STA_SUPPORT //
830
831 // Do nothing if the driver is starting halt state.
832 // This might happen when timer already been fired before cancel timer with mlmehalt
833 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
834 fRTMP_ADAPTER_RADIO_OFF |
835 fRTMP_ADAPTER_RADIO_MEASUREMENT |
836 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
837 return;
838
Adam McDanieled291e82009-02-23 08:01:07 -0700839 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
840 {
841 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
842 {
843 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
844 pAd->SameRxByteCount++;
845 }
846 else
847 pAd->SameRxByteCount = 0;
848
849 // If after BBP, still not work...need to check to reset PBF&MAC.
850 if (pAd->SameRxByteCount == 702)
851 {
852 pAd->SameRxByteCount = 0;
853 AsicResetPBF(pAd);
854 AsicResetMAC(pAd);
855 }
856
857 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
858 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
859 {
860 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
861 {
Mark Einonf72c4bf2009-03-11 22:51:41 +0000862 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
Adam McDanieled291e82009-02-23 08:01:07 -0700863 pAd->SameRxByteCount = 700;
864 AsicResetBBP(pAd);
865 }
866 }
867
868 // Update lastReceiveByteCount.
869 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
870
871 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
872 {
873 pAd->CheckDmaBusyCount = 0;
874 AsicResetFromDMABusy(pAd);
875 }
876 }
877
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700878 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
879
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700880#ifdef CONFIG_STA_SUPPORT
881 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
882 {
883 // Do nothing if monitor mode is on
884 if (MONITOR_ON(pAd))
885 return;
886
887 if (pAd->Mlme.PeriodicRound & 0x1)
888 {
889 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
890 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
891 (STA_TGN_WIFI_ON(pAd)) &&
892 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
893
894 {
895 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
896 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
897 }
898 else if ((STA_TGN_WIFI_ON(pAd)) &&
899 ((pAd->MACVersion & 0xffff) == 0x0101))
900 {
901 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
902 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
903 }
904 }
905 }
906#endif // CONFIG_STA_SUPPORT //
907
908 pAd->bUpdateBcnCntDone = FALSE;
909
910// RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
911 pAd->Mlme.PeriodicRound ++;
912
913 // execute every 500ms
914 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
915 {
916#ifdef CONFIG_STA_SUPPORT
917 // perform dynamic tx rate switching based on past TX history
918 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
919 {
920 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
921 )
922 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
923 MlmeDynamicTxRateSwitching(pAd);
924 }
925#endif // CONFIG_STA_SUPPORT //
926 }
927
928 // Normal 1 second Mlme PeriodicExec.
929 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
930 {
931 pAd->Mlme.OneSecPeriodicRound ++;
932
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700933 if (rx_Total)
934 {
935
936 // reset counters
937 rx_AMSDU = 0;
938 rx_Total = 0;
939 }
940
941 // Media status changed, report to NDIS
942 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
943 {
944 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
945 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
946 {
947 pAd->IndicateMediaState = NdisMediaStateConnected;
948 RTMP_IndicateMediaState(pAd);
949
950 }
951 else
952 {
953 pAd->IndicateMediaState = NdisMediaStateDisconnected;
954 RTMP_IndicateMediaState(pAd);
955 }
956 }
957
958 NdisGetSystemUpTime(&pAd->Mlme.Now32);
959
960 // add the most up-to-date h/w raw counters into software variable, so that
961 // the dynamic tuning mechanism below are based on most up-to-date information
962 NICUpdateRawCounters(pAd);
963
964
965#ifdef DOT11_N_SUPPORT
966 // Need statistics after read counter. So put after NICUpdateRawCounters
967 ORIBATimerTimeout(pAd);
968#endif // DOT11_N_SUPPORT //
969
970
971 // The time period for checking antenna is according to traffic
972 if (pAd->Mlme.bEnableAutoAntennaCheck)
973 {
974 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
975 pAd->RalinkCounters.OneSecTxRetryOkCount +
976 pAd->RalinkCounters.OneSecTxFailCount;
977
978 if (TxTotalCnt > 50)
979 {
980 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
981 {
982 AsicEvaluateRxAnt(pAd);
983 }
984 }
985 else
986 {
987 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
988 {
989 AsicEvaluateRxAnt(pAd);
990 }
991 }
992 }
993
994#ifdef CONFIG_STA_SUPPORT
995 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
996 STAMlmePeriodicExec(pAd);
997#endif // CONFIG_STA_SUPPORT //
998
999 MlmeResetRalinkCounters(pAd);
1000
1001#ifdef CONFIG_STA_SUPPORT
1002 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1003 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001004 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001005 {
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.
1012
1013 UINT32 MacReg = 0;
1014
1015 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1016 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1017 {
1018 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1019 RTMPusecDelay(1);
1020 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1021
1022 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1023 }
1024 }
1025 }
1026#endif // CONFIG_STA_SUPPORT //
1027
1028 RT28XX_MLME_HANDLER(pAd);
1029 }
1030
1031
1032 pAd->bUpdateBcnCntDone = FALSE;
1033}
1034
1035#ifdef CONFIG_STA_SUPPORT
1036VOID STAMlmePeriodicExec(
1037 PRTMP_ADAPTER pAd)
1038{
1039 ULONG TxTotalCnt;
1040
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001041#ifdef WPA_SUPPLICANT_SUPPORT
1042 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1043#endif // WPA_SUPPLICANT_SUPPORT //
1044 {
1045 // WPA MIC error should block association attempt for 60 seconds
1046 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1047 pAd->StaCfg.bBlockAssoc = FALSE;
1048 }
1049
Adam McDanieled291e82009-02-23 08:01:07 -07001050 //Baron 2008/07/10
1051 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1052 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1053 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1054 if(pAd->StaCfg.WepStatus<2)
1055 {
1056 pAd->StaCfg.WpaSupplicantUP = 0;
1057 }
1058 else
1059 {
1060 pAd->StaCfg.WpaSupplicantUP = 1;
1061 }
1062
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001063 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1064 {
1065 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1066 {
1067 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1068 }
1069 pAd->PreMediaState = pAd->IndicateMediaState;
1070 }
1071
Adam McDanieled291e82009-02-23 08:01:07 -07001072 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1073 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1074 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1075 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1076 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1077 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1078 {
1079 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1080 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001081
1082
1083
1084 AsicStaBbpTuning(pAd);
1085
1086 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1087 pAd->RalinkCounters.OneSecTxRetryOkCount +
1088 pAd->RalinkCounters.OneSecTxFailCount;
1089
1090 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1091 {
1092 // update channel quality for Roaming and UI LinkQuality display
1093 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1094 }
1095
1096 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1097 // Radio is currently in noisy environment
1098 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1099 AsicAdjustTxPower(pAd);
1100
1101 if (INFRA_ON(pAd))
1102 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001103 // Is PSM bit consistent with user power management policy?
1104 // This is the only place that will set PSM bit ON.
1105 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1106 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1107
1108 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1109
1110 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1111 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1112 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1113 {
1114 RTMPSetAGCInitValue(pAd, BW_20);
1115 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1116 }
1117
1118 {
1119 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1120 {
1121 // When APSD is enabled, the period changes as 20 sec
1122 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1123 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1124 }
1125 else
1126 {
1127 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1128 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1129 {
1130 if (pAd->CommonCfg.bWmmCapable)
1131 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1132 else
1133 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1134 }
1135 }
1136 }
1137
1138 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1139 {
1140 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1141 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1142 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1143
1144 // Lost AP, send disconnect & link down event
1145 LinkDown(pAd, FALSE);
1146
1147#ifdef WPA_SUPPLICANT_SUPPORT
1148#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1149 if (pAd->StaCfg.WpaSupplicantUP)
1150 {
1151 union iwreq_data wrqu;
1152 //send disassociate event to wpa_supplicant
1153 memset(&wrqu, 0, sizeof(wrqu));
1154 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1155 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1156 }
1157#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1158#endif // WPA_SUPPLICANT_SUPPORT //
1159
1160#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1161 {
1162 union iwreq_data wrqu;
1163 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1164 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1165 }
1166#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1167
1168 MlmeAutoReconnectLastSSID(pAd);
1169 }
1170 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1171 {
1172 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1173 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1174 MlmeAutoReconnectLastSSID(pAd);
1175 }
1176
1177 // Add auto seamless roaming
1178 if (pAd->StaCfg.bFastRoaming)
1179 {
1180 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1181
1182 DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
1183
1184 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1185 {
1186 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1187 }
1188 }
1189 }
1190 else if (ADHOC_ON(pAd))
1191 {
1192 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1193 // the "TX BEACON competition" for the entire past 1 sec.
1194 // So that even when ASIC's BEACONgen engine been blocked
1195 // by peer's BEACON due to slower system clock, this STA still can send out
1196 // minimum BEACON to tell the peer I'm alive.
1197 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1198 // EnqueueBeaconFrame(pAd); // software send BEACON
1199
1200 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1201 // restore outgoing BEACON to support B/G-mixed mode
1202 if ((pAd->CommonCfg.Channel <= 14) &&
1203 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1204 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1205 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1206 {
1207 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1208 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1209 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1210 MlmeUpdateTxRates(pAd, FALSE, 0);
1211 MakeIbssBeacon(pAd); // re-build BEACON frame
1212 AsicEnableIbssSync(pAd); // copy to on-chip memory
1213 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1214 }
1215
1216#ifdef DOT11_N_SUPPORT
1217 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1218 {
1219 if ((pAd->StaCfg.AdhocBGJoined) &&
1220 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1221 {
1222 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1223 pAd->StaCfg.AdhocBGJoined = FALSE;
1224 }
1225
1226 if ((pAd->StaCfg.Adhoc20NJoined) &&
1227 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1228 {
1229 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1230 pAd->StaCfg.Adhoc20NJoined = FALSE;
1231 }
1232 }
1233#endif // DOT11_N_SUPPORT //
1234
1235 //radar detect
1236 if ((pAd->CommonCfg.Channel > 14)
1237 && (pAd->CommonCfg.bIEEE80211H == 1)
1238 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1239 {
1240 RadarDetectPeriodic(pAd);
1241 }
1242
1243 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1244 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1245 // join later.
1246 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1247 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1248 {
1249 MLME_START_REQ_STRUCT StartReq;
1250
1251 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1252 LinkDown(pAd, FALSE);
1253
1254 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1255 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1256 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1257 }
1258 }
1259 else // no INFRA nor ADHOC connection
1260 {
1261
1262 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1263 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1264 goto SKIP_AUTO_SCAN_CONN;
1265 else
1266 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1267
1268 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1269 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1270 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1271 {
1272 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1273 {
1274 MLME_SCAN_REQ_STRUCT ScanReq;
1275
1276 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1277 {
1278 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1279 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1280 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1281 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1282 // Reset Missed scan number
1283 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1284 }
1285 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1286 MlmeAutoReconnectLastSSID(pAd);
1287 }
1288 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1289 {
1290 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1291 {
1292 MlmeAutoScan(pAd);
1293 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1294 }
1295 else
1296 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001297 MlmeAutoReconnectLastSSID(pAd);
1298 }
1299 }
1300 }
1301 }
1302
1303SKIP_AUTO_SCAN_CONN:
1304
1305#ifdef DOT11_N_SUPPORT
1306 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1307 {
1308 pAd->MacTab.fAnyBASession = TRUE;
1309 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1310 }
1311 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1312 {
1313 pAd->MacTab.fAnyBASession = FALSE;
1314 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1315 }
1316#endif // DOT11_N_SUPPORT //
1317
1318
1319#ifdef DOT11_N_SUPPORT
1320#ifdef DOT11N_DRAFT3
1321 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1322 TriEventCounterMaintenance(pAd);
1323#endif // DOT11N_DRAFT3 //
1324#endif // DOT11_N_SUPPORT //
1325
1326 return;
1327}
1328
1329// Link down report
1330VOID LinkDownExec(
1331 IN PVOID SystemSpecific1,
1332 IN PVOID FunctionContext,
1333 IN PVOID SystemSpecific2,
1334 IN PVOID SystemSpecific3)
1335{
1336
1337 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1338
1339 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1340 RTMP_IndicateMediaState(pAd);
1341 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1342}
1343
1344// IRQL = DISPATCH_LEVEL
1345VOID MlmeAutoScan(
1346 IN PRTMP_ADAPTER pAd)
1347{
1348 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1349 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1350 {
1351 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1352 MlmeEnqueue(pAd,
1353 MLME_CNTL_STATE_MACHINE,
1354 OID_802_11_BSSID_LIST_SCAN,
1355 0,
1356 NULL);
1357 RT28XX_MLME_HANDLER(pAd);
1358 }
1359}
1360
1361// IRQL = DISPATCH_LEVEL
1362VOID MlmeAutoReconnectLastSSID(
1363 IN PRTMP_ADAPTER pAd)
1364{
1365
1366
1367 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1368 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1369 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1370 {
1371 NDIS_802_11_SSID OidSsid;
1372 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1373 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1374
1375 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1376 MlmeEnqueue(pAd,
1377 MLME_CNTL_STATE_MACHINE,
1378 OID_802_11_SSID,
1379 sizeof(NDIS_802_11_SSID),
1380 &OidSsid);
1381 RT28XX_MLME_HANDLER(pAd);
1382 }
1383}
1384#endif // CONFIG_STA_SUPPORT //
1385
1386/*
1387 ==========================================================================
1388 Validate SSID for connection try and rescan purpose
1389 Valid SSID will have visible chars only.
1390 The valid length is from 0 to 32.
1391 IRQL = DISPATCH_LEVEL
1392 ==========================================================================
1393 */
1394BOOLEAN MlmeValidateSSID(
1395 IN PUCHAR pSsid,
1396 IN UCHAR SsidLen)
1397{
1398 int index;
1399
1400 if (SsidLen > MAX_LEN_OF_SSID)
1401 return (FALSE);
1402
1403 // Check each character value
1404 for (index = 0; index < SsidLen; index++)
1405 {
1406 if (pSsid[index] < 0x20)
1407 return (FALSE);
1408 }
1409
1410 // All checked
1411 return (TRUE);
1412}
1413
1414VOID MlmeSelectTxRateTable(
1415 IN PRTMP_ADAPTER pAd,
1416 IN PMAC_TABLE_ENTRY pEntry,
1417 IN PUCHAR *ppTable,
1418 IN PUCHAR pTableSize,
1419 IN PUCHAR pInitTxRateIdx)
1420{
1421 do
1422 {
1423 // decide the rate table for tuning
1424 if (pAd->CommonCfg.TxRateTableSize > 0)
1425 {
1426 *ppTable = RateSwitchTable;
1427 *pTableSize = RateSwitchTable[0];
1428 *pInitTxRateIdx = RateSwitchTable[1];
1429
1430 break;
1431 }
1432
1433#ifdef CONFIG_STA_SUPPORT
1434 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1435 {
1436#ifdef DOT11_N_SUPPORT
1437 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1438 !pAd->StaCfg.AdhocBOnlyJoined &&
1439 !pAd->StaCfg.AdhocBGJoined &&
1440 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1441 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1442 {// 11N 1S Adhoc
1443 *ppTable = RateSwitchTable11N1S;
1444 *pTableSize = RateSwitchTable11N1S[0];
1445 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1446
1447 }
1448 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1449 !pAd->StaCfg.AdhocBOnlyJoined &&
1450 !pAd->StaCfg.AdhocBGJoined &&
1451 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1452 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1453 (pAd->Antenna.field.TxPath == 2))
1454 {// 11N 2S Adhoc
1455 if (pAd->LatchRfRegs.Channel <= 14)
1456 {
1457 *ppTable = RateSwitchTable11N2S;
1458 *pTableSize = RateSwitchTable11N2S[0];
1459 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1460 }
1461 else
1462 {
1463 *ppTable = RateSwitchTable11N2SForABand;
1464 *pTableSize = RateSwitchTable11N2SForABand[0];
1465 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1466 }
1467
1468 }
1469 else
1470#endif // DOT11_N_SUPPORT //
1471 if (pAd->CommonCfg.PhyMode == PHY_11B)
1472 {
1473 *ppTable = RateSwitchTable11B;
1474 *pTableSize = RateSwitchTable11B[0];
1475 *pInitTxRateIdx = RateSwitchTable11B[1];
1476
1477 }
1478 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1479 {
1480 // USe B Table when Only b-only Station in my IBSS .
1481 *ppTable = RateSwitchTable11B;
1482 *pTableSize = RateSwitchTable11B[0];
1483 *pInitTxRateIdx = RateSwitchTable11B[1];
1484
1485 }
1486 else if (pAd->LatchRfRegs.Channel <= 14)
1487 {
1488 *ppTable = RateSwitchTable11BG;
1489 *pTableSize = RateSwitchTable11BG[0];
1490 *pInitTxRateIdx = RateSwitchTable11BG[1];
1491
1492 }
1493 else
1494 {
1495 *ppTable = RateSwitchTable11G;
1496 *pTableSize = RateSwitchTable11G[0];
1497 *pInitTxRateIdx = RateSwitchTable11G[1];
1498
1499 }
1500 break;
1501 }
1502#endif // CONFIG_STA_SUPPORT //
1503
1504#ifdef DOT11_N_SUPPORT
1505 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1506 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1507 {// 11BGN 1S AP
1508 *ppTable = RateSwitchTable11BGN1S;
1509 *pTableSize = RateSwitchTable11BGN1S[0];
1510 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1511
1512 break;
1513 }
1514
1515 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1516 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1517 {// 11BGN 2S AP
1518 if (pAd->LatchRfRegs.Channel <= 14)
1519 {
1520 *ppTable = RateSwitchTable11BGN2S;
1521 *pTableSize = RateSwitchTable11BGN2S[0];
1522 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1523
1524 }
1525 else
1526 {
1527 *ppTable = RateSwitchTable11BGN2SForABand;
1528 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1529 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1530
1531 }
1532 break;
1533 }
1534
1535 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1536 {// 11N 1S AP
1537 *ppTable = RateSwitchTable11N1S;
1538 *pTableSize = RateSwitchTable11N1S[0];
1539 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1540
1541 break;
1542 }
1543
1544 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1545 {// 11N 2S AP
1546 if (pAd->LatchRfRegs.Channel <= 14)
1547 {
1548 *ppTable = RateSwitchTable11N2S;
1549 *pTableSize = RateSwitchTable11N2S[0];
1550 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1551 }
1552 else
1553 {
1554 *ppTable = RateSwitchTable11N2SForABand;
1555 *pTableSize = RateSwitchTable11N2SForABand[0];
1556 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1557 }
1558
1559 break;
1560 }
1561#endif // DOT11_N_SUPPORT //
1562 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1563 if ((pEntry->RateLen == 4)
1564#ifdef DOT11_N_SUPPORT
1565 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1566#endif // DOT11_N_SUPPORT //
1567 )
1568 {// B only AP
1569 *ppTable = RateSwitchTable11B;
1570 *pTableSize = RateSwitchTable11B[0];
1571 *pInitTxRateIdx = RateSwitchTable11B[1];
1572
1573 break;
1574 }
1575
1576 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1577 if ((pEntry->RateLen > 8)
1578#ifdef DOT11_N_SUPPORT
1579 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1580#endif // DOT11_N_SUPPORT //
1581 )
1582 {// B/G mixed AP
1583 *ppTable = RateSwitchTable11BG;
1584 *pTableSize = RateSwitchTable11BG[0];
1585 *pInitTxRateIdx = RateSwitchTable11BG[1];
1586
1587 break;
1588 }
1589
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#ifdef DOT11_N_SUPPORT
1593 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1594#endif // DOT11_N_SUPPORT //
1595 )
1596 {// G only AP
1597 *ppTable = RateSwitchTable11G;
1598 *pTableSize = RateSwitchTable11G[0];
1599 *pInitTxRateIdx = RateSwitchTable11G[1];
1600
1601 break;
1602 }
1603#ifdef DOT11_N_SUPPORT
1604#endif // DOT11_N_SUPPORT //
1605
1606#ifdef CONFIG_STA_SUPPORT
1607 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1608 {
1609#ifdef DOT11_N_SUPPORT
1610 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1611 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1612#endif // DOT11_N_SUPPORT //
1613 { // Legacy mode
1614 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1615 {
1616 *ppTable = RateSwitchTable11B;
1617 *pTableSize = RateSwitchTable11B[0];
1618 *pInitTxRateIdx = RateSwitchTable11B[1];
1619 }
1620 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1621 {
1622 *ppTable = RateSwitchTable11G;
1623 *pTableSize = RateSwitchTable11G[0];
1624 *pInitTxRateIdx = RateSwitchTable11G[1];
1625
1626 }
1627 else
1628 {
1629 *ppTable = RateSwitchTable11BG;
1630 *pTableSize = RateSwitchTable11BG[0];
1631 *pInitTxRateIdx = RateSwitchTable11BG[1];
1632 }
1633 break;
1634 }
1635#ifdef DOT11_N_SUPPORT
1636 if (pAd->LatchRfRegs.Channel <= 14)
1637 {
1638 if (pAd->CommonCfg.TxStream == 1)
1639 {
1640 *ppTable = RateSwitchTable11N1S;
1641 *pTableSize = RateSwitchTable11N1S[0];
1642 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1643 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1644 }
1645 else
1646 {
1647 *ppTable = RateSwitchTable11N2S;
1648 *pTableSize = RateSwitchTable11N2S[0];
1649 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1650 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1651 }
1652 }
1653 else
1654 {
1655 if (pAd->CommonCfg.TxStream == 1)
1656 {
1657 *ppTable = RateSwitchTable11N1S;
1658 *pTableSize = RateSwitchTable11N1S[0];
1659 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1660 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1661 }
1662 else
1663 {
1664 *ppTable = RateSwitchTable11N2SForABand;
1665 *pTableSize = RateSwitchTable11N2SForABand[0];
1666 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1667 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1668 }
1669 }
1670#endif // DOT11_N_SUPPORT //
1671 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1672 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1673 }
1674#endif // CONFIG_STA_SUPPORT //
1675 } while(FALSE);
1676}
1677
1678#ifdef CONFIG_STA_SUPPORT
1679/*
1680 ==========================================================================
1681 Description:
1682 This routine checks if there're other APs out there capable for
1683 roaming. Caller should call this routine only when Link up in INFRA mode
1684 and channel quality is below CQI_GOOD_THRESHOLD.
1685
1686 IRQL = DISPATCH_LEVEL
1687
1688 Output:
1689 ==========================================================================
1690 */
1691VOID MlmeCheckForRoaming(
1692 IN PRTMP_ADAPTER pAd,
1693 IN ULONG Now32)
1694{
1695 USHORT i;
1696 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1697 BSS_ENTRY *pBss;
1698
1699 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1700 // put all roaming candidates into RoamTab, and sort in RSSI order
1701 BssTableInit(pRoamTab);
1702 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1703 {
1704 pBss = &pAd->ScanTab.BssEntry[i];
1705
1706 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1707 continue; // AP disappear
1708 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1709 continue; // RSSI too weak. forget it.
1710 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1711 continue; // skip current AP
1712 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1713 continue; // only AP with stronger RSSI is eligible for roaming
1714
1715 // AP passing all above rules is put into roaming candidate table
1716 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1717 pRoamTab->BssNr += 1;
1718 }
1719
1720 if (pRoamTab->BssNr > 0)
1721 {
1722 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1723 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1724 {
1725 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1726 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1727 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1728 RT28XX_MLME_HANDLER(pAd);
1729 }
1730 }
1731 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1732}
1733
1734/*
1735 ==========================================================================
1736 Description:
1737 This routine checks if there're other APs out there capable for
1738 roaming. Caller should call this routine only when link up in INFRA mode
1739 and channel quality is below CQI_GOOD_THRESHOLD.
1740
1741 IRQL = DISPATCH_LEVEL
1742
1743 Output:
1744 ==========================================================================
1745 */
1746VOID MlmeCheckForFastRoaming(
1747 IN PRTMP_ADAPTER pAd,
1748 IN ULONG Now)
1749{
1750 USHORT i;
1751 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1752 BSS_ENTRY *pBss;
1753
1754 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1755 // put all roaming candidates into RoamTab, and sort in RSSI order
1756 BssTableInit(pRoamTab);
1757 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1758 {
1759 pBss = &pAd->ScanTab.BssEntry[i];
1760
1761 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1762 continue; // RSSI too weak. forget it.
1763 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1764 continue; // skip current AP
1765 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1766 continue; // skip different SSID
1767 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1768 continue; // skip AP without better RSSI
1769
1770 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));
1771 // AP passing all above rules is put into roaming candidate table
1772 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1773 pRoamTab->BssNr += 1;
1774 }
1775
1776 if (pRoamTab->BssNr > 0)
1777 {
1778 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1779 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1780 {
1781 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1782 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1783 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1784 RT28XX_MLME_HANDLER(pAd);
1785 }
1786 }
1787 // Maybe site survey required
1788 else
1789 {
1790 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1791 {
1792 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1793 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1794 pAd->StaCfg.ScanCnt = 2;
1795 pAd->StaCfg.LastScanTime = Now;
1796 MlmeAutoScan(pAd);
1797 }
1798 }
1799
1800 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1801}
1802
1803/*
1804 ==========================================================================
1805 Description:
1806 This routine calculates TxPER, RxPER of the past N-sec period. And
1807 according to the calculation result, ChannelQuality is calculated here
1808 to decide if current AP is still doing the job.
1809
1810 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1811 Output:
1812 StaCfg.ChannelQuality - 0..100
1813
1814 IRQL = DISPATCH_LEVEL
1815
1816 NOTE: This routine decide channle quality based on RX CRC error ratio.
1817 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1818 is performed right before this routine, so that this routine can decide
1819 channel quality based on the most up-to-date information
1820 ==========================================================================
1821 */
1822VOID MlmeCalculateChannelQuality(
1823 IN PRTMP_ADAPTER pAd,
1824 IN ULONG Now32)
1825{
1826 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1827 ULONG RxCnt, RxPER;
1828 UCHAR NorRssi;
1829 CHAR MaxRssi;
1830 ULONG BeaconLostTime = BEACON_LOST_TIME;
1831
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001832 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1833
1834 //
1835 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1836 //
1837 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1838 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1839 if (TxCnt < 5)
1840 {
1841 TxPER = 0;
1842 TxPRR = 0;
1843 }
1844 else
1845 {
1846 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1847 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1848 }
1849
1850 //
1851 // calculate RX PER - don't take RxPER into consideration if too few sample
1852 //
1853 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1854 if (RxCnt < 5)
1855 RxPER = 0;
1856 else
1857 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1858
1859 //
1860 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1861 //
1862 if (INFRA_ON(pAd) &&
1863 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1864 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1865 {
1866 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1867 pAd->Mlme.ChannelQuality = 0;
1868 }
1869 else
1870 {
1871 // Normalize Rssi
1872 if (MaxRssi > -40)
1873 NorRssi = 100;
1874 else if (MaxRssi < -90)
1875 NorRssi = 0;
1876 else
1877 NorRssi = (MaxRssi + 90) * 2;
1878
1879 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1880 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1881 TX_WEIGHTING * (100 - TxPRR) +
1882 RX_WEIGHTING* (100 - RxPER)) / 100;
1883 if (pAd->Mlme.ChannelQuality >= 100)
1884 pAd->Mlme.ChannelQuality = 100;
1885 }
1886
1887}
1888
1889VOID MlmeSetTxRate(
1890 IN PRTMP_ADAPTER pAd,
1891 IN PMAC_TABLE_ENTRY pEntry,
1892 IN PRTMP_TX_RATE_SWITCH pTxRate)
1893{
1894 UCHAR MaxMode = MODE_OFDM;
1895
1896#ifdef DOT11_N_SUPPORT
1897 MaxMode = MODE_HTGREENFIELD;
1898
1899 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1900 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1901 else
1902#endif // DOT11_N_SUPPORT //
1903 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1904
1905 if (pTxRate->CurrMCS < MCS_AUTO)
1906 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1907
1908 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1909 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1910
1911 if (ADHOC_ON(pAd))
1912 {
1913 // If peer adhoc is b-only mode, we can't send 11g rate.
1914 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1915 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1916
1917 //
1918 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1919 //
1920 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1921 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1922 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1923
1924 // Patch speed error in status page
1925 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1926 }
1927 else
1928 {
1929 if (pTxRate->Mode <= MaxMode)
1930 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1931
1932#ifdef DOT11_N_SUPPORT
1933 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1934 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1935 else
1936#endif // DOT11_N_SUPPORT //
1937 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1938
1939#ifdef DOT11_N_SUPPORT
1940 // Reexam each bandwidth's SGI support.
1941 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1942 {
1943 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1944 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1945 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1946 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1947 }
1948
1949 // Turn RTS/CTS rate to 6Mbps.
1950 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1951 {
1952 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1953 if (pAd->MacTab.fAnyBASession)
1954 {
1955 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1956 }
1957 else
1958 {
1959 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1960 }
1961 }
1962 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1963 {
1964 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1965 if (pAd->MacTab.fAnyBASession)
1966 {
1967 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1968 }
1969 else
1970 {
1971 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1972 }
1973 }
1974 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1975 {
1976 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1977
1978 }
1979 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1980 {
1981 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1982 }
1983#endif // DOT11_N_SUPPORT //
1984
1985 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1986 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1987 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1988 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1989#ifdef DOT11_N_SUPPORT
1990 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1991 pAd->WIFItestbed.bGreenField)
1992 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1993#endif // DOT11_N_SUPPORT //
1994 }
1995
1996 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1997}
1998
1999/*
2000 ==========================================================================
2001 Description:
2002 This routine calculates the acumulated TxPER of eaxh TxRate. And
2003 according to the calculation result, change CommonCfg.TxRate which
2004 is the stable TX Rate we expect the Radio situation could sustained.
2005
2006 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2007 Output:
2008 CommonCfg.TxRate -
2009
2010 IRQL = DISPATCH_LEVEL
2011
2012 NOTE:
2013 call this routine every second
2014 ==========================================================================
2015 */
2016VOID MlmeDynamicTxRateSwitching(
2017 IN PRTMP_ADAPTER pAd)
2018{
2019 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2020 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2021 ULONG TxErrorRatio = 0;
2022 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2023 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2024 PUCHAR pTable;
2025 UCHAR TableSize = 0;
2026 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2027 CHAR Rssi, RssiOffset = 0;
2028 TX_STA_CNT1_STRUC StaTx1;
2029 TX_STA_CNT0_STRUC TxStaCnt0;
2030 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2031 MAC_TABLE_ENTRY *pEntry;
2032
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002033 /*if (pAd->Antenna.field.RxPath > 1)
2034 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2035 else
2036 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2037
2038 //
2039 // walk through MAC table, see if need to change AP's TX rate toward each entry
2040 //
2041 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2042 {
2043 pEntry = &pAd->MacTab.Content[i];
2044
2045 // check if this entry need to switch rate automatically
2046 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2047 continue;
2048
2049 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2050 {
2051 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2052
2053 // Update statistic counter
2054 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2055 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2056 pAd->bUpdateBcnCntDone = TRUE;
2057 TxRetransmit = StaTx1.field.TxRetransmit;
2058 TxSuccess = StaTx1.field.TxSuccess;
2059 TxFailCount = TxStaCnt0.field.TxFailCount;
2060 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2061
2062 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2063 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2064 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2065 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2066 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2067 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2068
2069 // if no traffic in the past 1-sec period, don't change TX rate,
2070 // but clear all bad history. because the bad history may affect the next
2071 // Chariot throughput test
2072 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2073 pAd->RalinkCounters.OneSecTxRetryOkCount +
2074 pAd->RalinkCounters.OneSecTxFailCount;
2075
2076 if (TxTotalCnt)
2077 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2078 }
2079 else
2080 {
2081 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2082
2083 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2084 pEntry->OneSecTxRetryOkCount +
2085 pEntry->OneSecTxFailCount;
2086
2087 if (TxTotalCnt)
2088 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2089 }
2090
2091 CurrRateIdx = pEntry->CurrTxRateIndex;
2092
2093 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2094
2095 if (CurrRateIdx >= TableSize)
2096 {
2097 CurrRateIdx = TableSize - 1;
2098 }
2099
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)
2105 )
2106 {
2107
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);
2113
2114 // reset all OneSecTx counters
2115 RESET_ONE_SEC_TX_CNT(pEntry);
2116 continue;
2117 }
2118
2119 // decide the next upgrade rate and downgrade rate, if any
2120 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2121 {
2122 UpRateIdx = CurrRateIdx + 1;
2123 DownRateIdx = CurrRateIdx -1;
2124 }
2125 else if (CurrRateIdx == 0)
2126 {
2127 UpRateIdx = CurrRateIdx + 1;
2128 DownRateIdx = CurrRateIdx;
2129 }
2130 else if (CurrRateIdx == (TableSize - 1))
2131 {
2132 UpRateIdx = CurrRateIdx;
2133 DownRateIdx = CurrRateIdx - 1;
2134 }
2135
2136 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2137
2138#ifdef DOT11_N_SUPPORT
2139 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2140 {
2141 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2142 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2143 }
2144 else
2145#endif // DOT11_N_SUPPORT //
2146 {
2147 TrainUp = pCurrTxRate->TrainUp;
2148 TrainDown = pCurrTxRate->TrainDown;
2149 }
2150
2151 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2152
2153 //
2154 // Keep the last time TxRateChangeAction status.
2155 //
2156 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2157
2158
2159
2160 //
2161 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2162 // (criteria copied from RT2500 for Netopia case)
2163 //
2164 if (TxTotalCnt <= 15)
2165 {
2166 CHAR idx = 0;
2167 UCHAR TxRateIdx;
2168 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2169 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2170 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2171 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2172
2173 // check the existence and index of each needed MCS
2174 while (idx < pTable[0])
2175 {
2176 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2177
2178 if (pCurrTxRate->CurrMCS == MCS_0)
2179 {
2180 MCS0 = idx;
2181 }
2182 else if (pCurrTxRate->CurrMCS == MCS_1)
2183 {
2184 MCS1 = idx;
2185 }
2186 else if (pCurrTxRate->CurrMCS == MCS_2)
2187 {
2188 MCS2 = idx;
2189 }
2190 else if (pCurrTxRate->CurrMCS == MCS_3)
2191 {
2192 MCS3 = idx;
2193 }
2194 else if (pCurrTxRate->CurrMCS == MCS_4)
2195 {
2196 MCS4 = idx;
2197 }
2198 else if (pCurrTxRate->CurrMCS == MCS_5)
2199 {
2200 MCS5 = idx;
2201 }
2202 else if (pCurrTxRate->CurrMCS == MCS_6)
2203 {
2204 MCS6 = idx;
2205 }
2206 //else if (pCurrTxRate->CurrMCS == MCS_7)
2207 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2208 {
2209 MCS7 = idx;
2210 }
2211 else if (pCurrTxRate->CurrMCS == MCS_12)
2212 {
2213 MCS12 = idx;
2214 }
2215 else if (pCurrTxRate->CurrMCS == MCS_13)
2216 {
2217 MCS13 = idx;
2218 }
2219 else if (pCurrTxRate->CurrMCS == MCS_14)
2220 {
2221 MCS14 = idx;
2222 }
2223 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2224 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
2225 {
2226 MCS15 = idx;
2227 }
2228 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2229 {
2230 MCS20 = idx;
2231 }
2232 else if (pCurrTxRate->CurrMCS == MCS_21)
2233 {
2234 MCS21 = idx;
2235 }
2236 else if (pCurrTxRate->CurrMCS == MCS_22)
2237 {
2238 MCS22 = idx;
2239 }
2240 else if (pCurrTxRate->CurrMCS == MCS_23)
2241 {
2242 MCS23 = idx;
2243 }
2244 idx ++;
2245 }
2246
2247 if (pAd->LatchRfRegs.Channel <= 14)
2248 {
2249 if (pAd->NicConfig2.field.ExternalLNAForG)
2250 {
2251 RssiOffset = 2;
2252 }
2253 else
2254 {
2255 RssiOffset = 5;
2256 }
2257 }
2258 else
2259 {
2260 if (pAd->NicConfig2.field.ExternalLNAForA)
2261 {
2262 RssiOffset = 5;
2263 }
2264 else
2265 {
2266 RssiOffset = 8;
2267 }
2268 }
2269#ifdef DOT11_N_SUPPORT
2270 /*if (MCS15)*/
2271 if ((pTable == RateSwitchTable11BGN3S) ||
2272 (pTable == RateSwitchTable11N3S) ||
2273 (pTable == RateSwitchTable))
2274 {// N mode with 3 stream // 3*3
2275 if (MCS23 && (Rssi >= -70))
2276 TxRateIdx = MCS15;
2277 else if (MCS22 && (Rssi >= -72))
2278 TxRateIdx = MCS14;
2279 else if (MCS21 && (Rssi >= -76))
2280 TxRateIdx = MCS13;
2281 else if (MCS20 && (Rssi >= -78))
2282 TxRateIdx = MCS12;
2283 else if (MCS4 && (Rssi >= -82))
2284 TxRateIdx = MCS4;
2285 else if (MCS3 && (Rssi >= -84))
2286 TxRateIdx = MCS3;
2287 else if (MCS2 && (Rssi >= -86))
2288 TxRateIdx = MCS2;
2289 else if (MCS1 && (Rssi >= -88))
2290 TxRateIdx = MCS1;
2291 else
2292 TxRateIdx = MCS0;
2293 }
2294 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2295 {// N mode with 2 stream
2296 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2297 TxRateIdx = MCS15;
2298 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2299 TxRateIdx = MCS14;
2300 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2301 TxRateIdx = MCS13;
2302 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2303 TxRateIdx = MCS12;
2304 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2305 TxRateIdx = MCS4;
2306 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2307 TxRateIdx = MCS3;
2308 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2309 TxRateIdx = MCS2;
2310 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2311 TxRateIdx = MCS1;
2312 else
2313 TxRateIdx = MCS0;
2314 }
2315 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2316 {// N mode with 1 stream
2317 if (MCS7 && (Rssi > (-72+RssiOffset)))
2318 TxRateIdx = MCS7;
2319 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2320 TxRateIdx = MCS6;
2321 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2322 TxRateIdx = MCS5;
2323 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2324 TxRateIdx = MCS4;
2325 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2326 TxRateIdx = MCS3;
2327 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2328 TxRateIdx = MCS2;
2329 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2330 TxRateIdx = MCS1;
2331 else
2332 TxRateIdx = MCS0;
2333 }
2334 else
2335#endif // DOT11_N_SUPPORT //
2336 {// Legacy mode
2337 if (MCS7 && (Rssi > -70))
2338 TxRateIdx = MCS7;
2339 else if (MCS6 && (Rssi > -74))
2340 TxRateIdx = MCS6;
2341 else if (MCS5 && (Rssi > -78))
2342 TxRateIdx = MCS5;
2343 else if (MCS4 && (Rssi > -82))
2344 TxRateIdx = MCS4;
2345 else if (MCS4 == 0) // for B-only mode
2346 TxRateIdx = MCS3;
2347 else if (MCS3 && (Rssi > -85))
2348 TxRateIdx = MCS3;
2349 else if (MCS2 && (Rssi > -87))
2350 TxRateIdx = MCS2;
2351 else if (MCS1 && (Rssi > -90))
2352 TxRateIdx = MCS1;
2353 else
2354 TxRateIdx = MCS0;
2355 }
2356
2357 {
2358 pEntry->CurrTxRateIndex = TxRateIdx;
2359 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2360 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2361 }
2362
2363 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2364 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2365 pEntry->fLastSecAccordingRSSI = TRUE;
2366 // reset all OneSecTx counters
2367 RESET_ONE_SEC_TX_CNT(pEntry);
2368
2369 continue;
2370 }
2371
2372 if (pEntry->fLastSecAccordingRSSI == TRUE)
2373 {
2374 pEntry->fLastSecAccordingRSSI = FALSE;
2375 pEntry->LastSecTxRateChangeAction = 0;
2376 // reset all OneSecTx counters
2377 RESET_ONE_SEC_TX_CNT(pEntry);
2378
2379 continue;
2380 }
2381
2382 do
2383 {
2384 BOOLEAN bTrainUpDown = FALSE;
2385
2386 pEntry->CurrTxRateStableTime ++;
2387
2388 // downgrade TX quality if PER >= Rate-Down threshold
2389 if (TxErrorRatio >= TrainDown)
2390 {
2391 bTrainUpDown = TRUE;
2392 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2393 }
2394 // upgrade TX quality if PER <= Rate-Up threshold
2395 else if (TxErrorRatio <= TrainUp)
2396 {
2397 bTrainUpDown = TRUE;
2398 bUpgradeQuality = TRUE;
2399 if (pEntry->TxQuality[CurrRateIdx])
2400 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2401
2402 if (pEntry->TxRateUpPenalty)
2403 pEntry->TxRateUpPenalty --;
2404 else if (pEntry->TxQuality[UpRateIdx])
2405 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2406 }
2407
2408 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2409
2410 if (bTrainUpDown)
2411 {
2412 // perform DRS - consider TxRate Down first, then rate up.
2413 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2414 {
2415 pEntry->CurrTxRateIndex = DownRateIdx;
2416 }
2417 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2418 {
2419 pEntry->CurrTxRateIndex = UpRateIdx;
2420 }
2421 }
2422 } while (FALSE);
2423
2424 // if rate-up happen, clear all bad history of all TX rates
2425 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2426 {
2427 pEntry->CurrTxRateStableTime = 0;
2428 pEntry->TxRateUpPenalty = 0;
2429 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2430 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2431 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2432
2433 //
2434 // For TxRate fast train up
2435 //
2436 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2437 {
2438 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2439
2440 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2441 }
2442 bTxRateChanged = TRUE;
2443 }
2444 // if rate-down happen, only clear DownRate's bad history
2445 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2446 {
2447 pEntry->CurrTxRateStableTime = 0;
2448 pEntry->TxRateUpPenalty = 0; // no penalty
2449 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2450 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2451 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2452
2453 //
2454 // For TxRate fast train down
2455 //
2456 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2457 {
2458 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2459
2460 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2461 }
2462 bTxRateChanged = TRUE;
2463 }
2464 else
2465 {
2466 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2467 bTxRateChanged = FALSE;
2468 }
2469
2470 pEntry->LastTxOkCount = TxSuccess;
2471
2472 // reset all OneSecTx counters
2473 RESET_ONE_SEC_TX_CNT(pEntry);
2474
2475 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2476 if (bTxRateChanged && pNextTxRate)
2477 {
2478 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2479 }
2480 }
2481}
2482
2483/*
2484 ========================================================================
2485 Routine Description:
2486 Station side, Auto TxRate faster train up timer call back function.
2487
2488 Arguments:
2489 SystemSpecific1 - Not used.
2490 FunctionContext - Pointer to our Adapter context.
2491 SystemSpecific2 - Not used.
2492 SystemSpecific3 - Not used.
2493
2494 Return Value:
2495 None
2496
2497 ========================================================================
2498*/
2499VOID StaQuickResponeForRateUpExec(
2500 IN PVOID SystemSpecific1,
2501 IN PVOID FunctionContext,
2502 IN PVOID SystemSpecific2,
2503 IN PVOID SystemSpecific3)
2504{
2505 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2506 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2507 ULONG TxTotalCnt;
2508 ULONG TxErrorRatio = 0;
2509 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2510 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2511 PUCHAR pTable;
2512 UCHAR TableSize = 0;
2513 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2514 TX_STA_CNT1_STRUC StaTx1;
2515 TX_STA_CNT0_STRUC TxStaCnt0;
2516 CHAR Rssi, ratio;
2517 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2518 MAC_TABLE_ENTRY *pEntry;
2519 ULONG i;
2520
2521 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2522
2523 //
2524 // walk through MAC table, see if need to change AP's TX rate toward each entry
2525 //
2526 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2527 {
2528 pEntry = &pAd->MacTab.Content[i];
2529
2530 // check if this entry need to switch rate automatically
2531 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2532 continue;
2533
2534 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2535 if (pAd->Antenna.field.TxPath > 1)
2536 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2537 else
2538 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2539
2540 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2541
2542 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2543
2544 // decide the next upgrade rate and downgrade rate, if any
2545 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2546 {
2547 UpRateIdx = CurrRateIdx + 1;
2548 DownRateIdx = CurrRateIdx -1;
2549 }
2550 else if (CurrRateIdx == 0)
2551 {
2552 UpRateIdx = CurrRateIdx + 1;
2553 DownRateIdx = CurrRateIdx;
2554 }
2555 else if (CurrRateIdx == (TableSize - 1))
2556 {
2557 UpRateIdx = CurrRateIdx;
2558 DownRateIdx = CurrRateIdx - 1;
2559 }
2560
2561 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2562
2563#ifdef DOT11_N_SUPPORT
2564 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2565 {
2566 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2567 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2568 }
2569 else
2570#endif // DOT11_N_SUPPORT //
2571 {
2572 TrainUp = pCurrTxRate->TrainUp;
2573 TrainDown = pCurrTxRate->TrainDown;
2574 }
2575
2576 if (pAd->MacTab.Size == 1)
2577 {
2578 // Update statistic counter
2579 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2580 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2581
2582 TxRetransmit = StaTx1.field.TxRetransmit;
2583 TxSuccess = StaTx1.field.TxSuccess;
2584 TxFailCount = TxStaCnt0.field.TxFailCount;
2585 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2586
2587 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2588 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2589 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2590 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2591 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2592 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2593
2594 if (TxTotalCnt)
2595 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2596 }
2597 else
2598 {
2599 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2600 pEntry->OneSecTxRetryOkCount +
2601 pEntry->OneSecTxFailCount;
2602
2603 if (TxTotalCnt)
2604 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2605 }
2606
2607
2608 //
2609 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2610 // (criteria copied from RT2500 for Netopia case)
2611 //
2612 if (TxTotalCnt <= 12)
2613 {
2614 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2615 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2616
2617 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2618 {
2619 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2620 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2621 }
2622 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2623 {
2624 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2625 }
2626
2627 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2628 return;
2629 }
2630
2631 do
2632 {
2633 ULONG OneSecTxNoRetryOKRationCount;
2634
2635 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2636 ratio = 5;
2637 else
2638 ratio = 4;
2639
2640 // downgrade TX quality if PER >= Rate-Down threshold
2641 if (TxErrorRatio >= TrainDown)
2642 {
2643 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2644 }
2645
2646 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2647
2648 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2649
2650 // perform DRS - consider TxRate Down first, then rate up.
2651 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2652 {
2653 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2654 {
2655 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2656 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2657
2658 }
2659
2660 }
2661 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2662 {
2663 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2664 {
2665
2666 }
2667 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2668 {
2669 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2670 }
2671 }
2672 }while (FALSE);
2673
2674 // if rate-up happen, clear all bad history of all TX rates
2675 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2676 {
2677 pAd->DrsCounters.TxRateUpPenalty = 0;
2678 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2679 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2680 }
2681 // if rate-down happen, only clear DownRate's bad history
2682 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2683 {
2684 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2685
2686 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2687 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2688 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2689 }
2690 else
2691 {
2692 bTxRateChanged = FALSE;
2693 }
2694
2695 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2696 if (bTxRateChanged && pNextTxRate)
2697 {
2698 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2699 }
2700 }
2701}
2702
2703/*
2704 ==========================================================================
2705 Description:
2706 This routine is executed periodically inside MlmePeriodicExec() after
2707 association with an AP.
2708 It checks if StaCfg.Psm is consistent with user policy (recorded in
2709 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2710 there're some conditions to consider:
2711 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2712 the time when Mibss==TRUE
2713 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2714 if outgoing traffic available in TxRing or MgmtRing.
2715 Output:
2716 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2717
2718 IRQL = DISPATCH_LEVEL
2719
2720 ==========================================================================
2721 */
2722VOID MlmeCheckPsmChange(
2723 IN PRTMP_ADAPTER pAd,
2724 IN ULONG Now32)
2725{
2726 ULONG PowerMode;
2727
2728 // condition -
2729 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2730 // 2. user wants either MAX_PSP or FAST_PSP
2731 // 3. but current psm is not in PWR_SAVE
2732 // 4. CNTL state machine is not doing SCANning
2733 // 5. no TX SUCCESS event for the past 1-sec period
2734#ifdef NDIS51_MINIPORT
2735 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2736 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2737 else
2738#endif
2739 PowerMode = pAd->StaCfg.WindowsPowerMode;
2740
2741 if (INFRA_ON(pAd) &&
2742 (PowerMode != Ndis802_11PowerModeCAM) &&
2743 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
Adam McDanieled291e82009-02-23 08:01:07 -07002744 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002745 {
2746 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2747 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2748 MlmeSetPsmBit(pAd, PWR_SAVE);
2749 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2750 {
2751 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2752 }
2753 else
2754 {
2755 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2756 }
2757 }
2758}
2759
2760// IRQL = PASSIVE_LEVEL
2761// IRQL = DISPATCH_LEVEL
2762VOID MlmeSetPsmBit(
2763 IN PRTMP_ADAPTER pAd,
2764 IN USHORT psm)
2765{
2766 AUTO_RSP_CFG_STRUC csr4;
2767
2768 pAd->StaCfg.Psm = psm;
2769 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2770 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2771 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2772 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2773}
2774#endif // CONFIG_STA_SUPPORT //
2775
2776
2777// IRQL = DISPATCH_LEVEL
2778VOID MlmeSetTxPreamble(
2779 IN PRTMP_ADAPTER pAd,
2780 IN USHORT TxPreamble)
2781{
2782 AUTO_RSP_CFG_STRUC csr4;
2783
2784 //
2785 // Always use Long preamble before verifiation short preamble functionality works well.
2786 // Todo: remove the following line if short preamble functionality works
2787 //
2788 //TxPreamble = Rt802_11PreambleLong;
2789
2790 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2791 if (TxPreamble == Rt802_11PreambleLong)
2792 {
2793 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2794 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2795 csr4.field.AutoResponderPreamble = 0;
2796 }
2797 else
2798 {
2799 // NOTE: 1Mbps should always use long preamble
2800 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2801 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2802 csr4.field.AutoResponderPreamble = 1;
2803 }
2804
2805 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2806}
2807
2808/*
2809 ==========================================================================
2810 Description:
2811 Update basic rate bitmap
2812 ==========================================================================
2813 */
2814
2815VOID UpdateBasicRateBitmap(
2816 IN PRTMP_ADAPTER pAdapter)
2817{
2818 INT i, j;
2819 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2820 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2821 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2822 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2823 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2824
2825
2826 /* if A mode, always use fix BasicRateBitMap */
2827 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2828 if (pAdapter->CommonCfg.Channel > 14)
2829 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2830 /* End of if */
2831
2832 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2833 {
2834 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2835 return;
2836 } /* End of if */
2837
2838 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2839 {
2840 sup_p[i] &= 0x7f;
2841 ext_p[i] &= 0x7f;
2842 } /* End of for */
2843
2844 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2845 {
2846 if (bitmap & (1 << i))
2847 {
2848 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2849 {
2850 if (sup_p[j] == rate[i])
2851 sup_p[j] |= 0x80;
2852 /* End of if */
2853 } /* End of for */
2854
2855 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2856 {
2857 if (ext_p[j] == rate[i])
2858 ext_p[j] |= 0x80;
2859 /* End of if */
2860 } /* End of for */
2861 } /* End of if */
2862 } /* End of for */
2863} /* End of UpdateBasicRateBitmap */
2864
2865// IRQL = PASSIVE_LEVEL
2866// IRQL = DISPATCH_LEVEL
2867// bLinkUp is to identify the inital link speed.
2868// TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2869VOID MlmeUpdateTxRates(
2870 IN PRTMP_ADAPTER pAd,
2871 IN BOOLEAN bLinkUp,
2872 IN UCHAR apidx)
2873{
2874 int i, num;
2875 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2876 UCHAR MinSupport = RATE_54;
2877 ULONG BasicRateBitmap = 0;
2878 UCHAR CurrBasicRate = RATE_1;
2879 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2880 PHTTRANSMIT_SETTING pHtPhy = NULL;
2881 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2882 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2883 BOOLEAN *auto_rate_cur_p;
2884 UCHAR HtMcs = MCS_AUTO;
2885
2886 // find max desired rate
2887 UpdateBasicRateBitmap(pAd);
2888
2889 num = 0;
2890 auto_rate_cur_p = NULL;
2891 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2892 {
2893 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2894 {
2895 case 2: Rate = RATE_1; num++; break;
2896 case 4: Rate = RATE_2; num++; break;
2897 case 11: Rate = RATE_5_5; num++; break;
2898 case 22: Rate = RATE_11; num++; break;
2899 case 12: Rate = RATE_6; num++; break;
2900 case 18: Rate = RATE_9; num++; break;
2901 case 24: Rate = RATE_12; num++; break;
2902 case 36: Rate = RATE_18; num++; break;
2903 case 48: Rate = RATE_24; num++; break;
2904 case 72: Rate = RATE_36; num++; break;
2905 case 96: Rate = RATE_48; num++; break;
2906 case 108: Rate = RATE_54; num++; break;
2907 //default: Rate = RATE_1; break;
2908 }
2909 if (MaxDesire < Rate) MaxDesire = Rate;
2910 }
2911
2912//===========================================================================
2913//===========================================================================
2914
2915#ifdef CONFIG_STA_SUPPORT
2916 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2917 {
2918 pHtPhy = &pAd->StaCfg.HTPhyMode;
2919 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2920 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2921
2922 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2923 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2924
2925 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2926 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2927 (MaxDesire > RATE_11))
2928 {
2929 MaxDesire = RATE_11;
2930 }
2931 }
2932#endif // CONFIG_STA_SUPPORT //
2933
2934 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2935 pMinHtPhy->word = 0;
2936 pMaxHtPhy->word = 0;
2937 pHtPhy->word = 0;
2938
2939 // Auto rate switching is enabled only if more than one DESIRED RATES are
2940 // specified; otherwise disabled
2941 if (num <= 1)
2942 {
2943 *auto_rate_cur_p = FALSE;
2944 }
2945 else
2946 {
2947 *auto_rate_cur_p = TRUE;
2948 }
2949
2950#if 1
2951 if (HtMcs != MCS_AUTO)
2952 {
2953 *auto_rate_cur_p = FALSE;
2954 }
2955 else
2956 {
2957 *auto_rate_cur_p = TRUE;
2958 }
2959#endif
2960
2961#ifdef CONFIG_STA_SUPPORT
2962 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2963 {
2964 pSupRate = &pAd->StaActive.SupRate[0];
2965 pExtRate = &pAd->StaActive.ExtRate[0];
2966 SupRateLen = pAd->StaActive.SupRateLen;
2967 ExtRateLen = pAd->StaActive.ExtRateLen;
2968 }
2969 else
2970#endif // CONFIG_STA_SUPPORT //
2971 {
2972 pSupRate = &pAd->CommonCfg.SupRate[0];
2973 pExtRate = &pAd->CommonCfg.ExtRate[0];
2974 SupRateLen = pAd->CommonCfg.SupRateLen;
2975 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2976 }
2977
2978 // find max supported rate
2979 for (i=0; i<SupRateLen; i++)
2980 {
2981 switch (pSupRate[i] & 0x7f)
2982 {
2983 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2984 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2985 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2986 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2987 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2988 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2989 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2990 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2991 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2992 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2993 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2994 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2995 default: Rate = RATE_1; break;
2996 }
2997 if (MaxSupport < Rate) MaxSupport = Rate;
2998
2999 if (MinSupport > Rate) MinSupport = Rate;
3000 }
3001
3002 for (i=0; i<ExtRateLen; i++)
3003 {
3004 switch (pExtRate[i] & 0x7f)
3005 {
3006 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3007 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3008 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3009 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3010 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3011 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3012 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3013 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3014 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3015 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3016 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3017 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3018 default: Rate = RATE_1; break;
3019 }
3020 if (MaxSupport < Rate) MaxSupport = Rate;
3021
3022 if (MinSupport > Rate) MinSupport = Rate;
3023 }
3024
3025 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3026
3027 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3028 // the DURATION field of outgoing uniicast DATA/MGMT frame
3029 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3030 {
3031 if (BasicRateBitmap & (0x01 << i))
3032 CurrBasicRate = (UCHAR)i;
3033 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3034 }
3035
3036 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3037 // max tx rate = min {max desire rate, max supported rate}
3038 if (MaxSupport < MaxDesire)
3039 pAd->CommonCfg.MaxTxRate = MaxSupport;
3040 else
3041 pAd->CommonCfg.MaxTxRate = MaxDesire;
3042
3043 pAd->CommonCfg.MinTxRate = MinSupport;
3044 if (*auto_rate_cur_p)
3045 {
3046 short dbm = 0;
3047#ifdef CONFIG_STA_SUPPORT
3048 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3049 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3050#endif // CONFIG_STA_SUPPORT //
3051 if (bLinkUp == TRUE)
3052 pAd->CommonCfg.TxRate = RATE_24;
3053 else
3054 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3055
3056 if (dbm < -75)
3057 pAd->CommonCfg.TxRate = RATE_11;
3058 else if (dbm < -70)
3059 pAd->CommonCfg.TxRate = RATE_24;
3060
3061 // should never exceed MaxTxRate (consider 11B-only mode)
3062 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3063 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3064
3065 pAd->CommonCfg.TxRateIndex = 0;
3066 }
3067 else
3068 {
3069 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3070 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3071 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3072
3073 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3074 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3075 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3076 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3077 }
3078
3079 if (pAd->CommonCfg.TxRate <= RATE_11)
3080 {
3081 pMaxHtPhy->field.MODE = MODE_CCK;
3082 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3083 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3084 }
3085 else
3086 {
3087 pMaxHtPhy->field.MODE = MODE_OFDM;
3088 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3089 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3090 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3091 else
3092 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3093 }
3094
3095 pHtPhy->word = (pMaxHtPhy->word);
3096 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3097 {
3098 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3099 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3100 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3101 }
3102 else
3103 {
3104 switch (pAd->CommonCfg.PhyMode)
3105 {
3106 case PHY_11BG_MIXED:
3107 case PHY_11B:
3108#ifdef DOT11_N_SUPPORT
3109 case PHY_11BGN_MIXED:
3110#endif // DOT11_N_SUPPORT //
3111 pAd->CommonCfg.MlmeRate = RATE_1;
3112 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3113 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3114 pAd->CommonCfg.RtsRate = RATE_11;
3115 break;
3116 case PHY_11G:
3117 case PHY_11A:
3118#ifdef DOT11_N_SUPPORT
3119 case PHY_11AGN_MIXED:
3120 case PHY_11GN_MIXED:
3121 case PHY_11N_2_4G:
3122 case PHY_11AN_MIXED:
3123 case PHY_11N_5G:
3124#endif // DOT11_N_SUPPORT //
3125 pAd->CommonCfg.MlmeRate = RATE_6;
3126 pAd->CommonCfg.RtsRate = RATE_6;
3127 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3128 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3129 break;
3130 case PHY_11ABG_MIXED:
3131#ifdef DOT11_N_SUPPORT
3132 case PHY_11ABGN_MIXED:
3133#endif // DOT11_N_SUPPORT //
3134 if (pAd->CommonCfg.Channel <= 14)
3135 {
3136 pAd->CommonCfg.MlmeRate = RATE_1;
3137 pAd->CommonCfg.RtsRate = RATE_1;
3138 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3139 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3140 }
3141 else
3142 {
3143 pAd->CommonCfg.MlmeRate = RATE_6;
3144 pAd->CommonCfg.RtsRate = RATE_6;
3145 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3146 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3147 }
3148 break;
3149 default: // error
3150 pAd->CommonCfg.MlmeRate = RATE_6;
3151 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3152 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3153 pAd->CommonCfg.RtsRate = RATE_1;
3154 break;
3155 }
3156 //
3157 // Keep Basic Mlme Rate.
3158 //
3159 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3160 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3161 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3162 else
3163 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3164 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3165 }
3166
3167 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3168 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3169 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3170 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3171 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3172 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3173 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 ));
3174}
3175
3176#ifdef DOT11_N_SUPPORT
3177/*
3178 ==========================================================================
3179 Description:
3180 This function update HT Rate setting.
3181 Input Wcid value is valid for 2 case :
3182 1. it's used for Station in infra mode that copy AP rate to Mactable.
3183 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3184
3185 IRQL = DISPATCH_LEVEL
3186
3187 ==========================================================================
3188 */
3189VOID MlmeUpdateHtTxRates(
3190 IN PRTMP_ADAPTER pAd,
3191 IN UCHAR apidx)
3192{
3193 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3194 CHAR i; // 3*3
3195 RT_HT_CAPABILITY *pRtHtCap = NULL;
3196 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3197 ULONG BasicMCS;
3198 UCHAR j, bitmask;
3199 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3200 PHTTRANSMIT_SETTING pHtPhy = NULL;
3201 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3202 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3203 BOOLEAN *auto_rate_cur_p;
3204
3205 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3206
3207 auto_rate_cur_p = NULL;
3208
3209#ifdef CONFIG_STA_SUPPORT
3210 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3211 {
3212 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3213 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3214 pHtPhy = &pAd->StaCfg.HTPhyMode;
3215 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3216 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3217
3218 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3219 }
3220#endif // CONFIG_STA_SUPPORT //
3221
3222#ifdef CONFIG_STA_SUPPORT
3223 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3224 {
3225 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3226 return;
3227
3228 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3229 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3230 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3231 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3232 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3233 pMaxHtPhy->field.STBC = STBC_USE;
3234 else
3235 pMaxHtPhy->field.STBC = STBC_NONE;
3236 }
3237 else
3238#endif // CONFIG_STA_SUPPORT //
3239 {
3240 if (pDesireHtPhy->bHtEnable == FALSE)
3241 return;
3242
3243 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3244 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3245 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3246 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3247 pMaxHtPhy->field.STBC = STBC_USE;
3248 else
3249 pMaxHtPhy->field.STBC = STBC_NONE;
3250 }
3251
3252 // Decide MAX ht rate.
3253 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3254 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3255 else
3256 pMaxHtPhy->field.MODE = MODE_HTMIX;
3257
3258 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3259 pMaxHtPhy->field.BW = BW_40;
3260 else
3261 pMaxHtPhy->field.BW = BW_20;
3262
3263 if (pMaxHtPhy->field.BW == BW_20)
3264 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3265 else
3266 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3267
3268 for (i=23; i>=0; i--) // 3*3
3269 {
3270 j = i/8;
3271 bitmask = (1<<(i-(j*8)));
3272
3273 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3274 {
3275 pMaxHtPhy->field.MCS = i;
3276 break;
3277 }
3278
3279 if (i==0)
3280 break;
3281 }
3282
3283 // Copy MIN ht rate. rt2860???
3284 pMinHtPhy->field.BW = BW_20;
3285 pMinHtPhy->field.MCS = 0;
3286 pMinHtPhy->field.STBC = 0;
3287 pMinHtPhy->field.ShortGI = 0;
3288 //If STA assigns fixed rate. update to fixed here.
3289#ifdef CONFIG_STA_SUPPORT
3290 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3291 {
3292 if (pDesireHtPhy->MCSSet[4] != 0)
3293 {
3294 pMaxHtPhy->field.MCS = 32;
3295 pMinHtPhy->field.MCS = 32;
3296 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3297 }
3298
3299 for (i=23; (CHAR)i >= 0; i--) // 3*3
3300 {
3301 j = i/8;
3302 bitmask = (1<<(i-(j*8)));
3303 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3304 {
3305 pMaxHtPhy->field.MCS = i;
3306 pMinHtPhy->field.MCS = i;
3307 break;
3308 }
3309 if (i==0)
3310 break;
3311 }
3312 }
3313#endif // CONFIG_STA_SUPPORT //
3314
3315
3316 // Decide ht rate
3317 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3318 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3319 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3320 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3321 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3322
3323 // use default now. rt2860
3324 if (pDesireHtPhy->MCSSet[0] != 0xff)
3325 *auto_rate_cur_p = FALSE;
3326 else
3327 *auto_rate_cur_p = TRUE;
3328
3329 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3330 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3331 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3332 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3333}
3334#endif // DOT11_N_SUPPORT //
3335
3336// IRQL = DISPATCH_LEVEL
3337VOID MlmeRadioOff(
3338 IN PRTMP_ADAPTER pAd)
3339{
3340 RT28XX_MLME_RADIO_OFF(pAd);
3341}
3342
3343// IRQL = DISPATCH_LEVEL
3344VOID MlmeRadioOn(
3345 IN PRTMP_ADAPTER pAd)
3346{
3347 RT28XX_MLME_RADIO_ON(pAd);
3348}
3349
3350// ===========================================================================================
3351// bss_table.c
3352// ===========================================================================================
3353
3354
3355/*! \brief initialize BSS table
3356 * \param p_tab pointer to the table
3357 * \return none
3358 * \pre
3359 * \post
3360
3361 IRQL = PASSIVE_LEVEL
3362 IRQL = DISPATCH_LEVEL
3363
3364 */
3365VOID BssTableInit(
3366 IN BSS_TABLE *Tab)
3367{
3368 int i;
3369
3370 Tab->BssNr = 0;
3371 Tab->BssOverlapNr = 0;
3372 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3373 {
3374 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3375 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3376 }
3377}
3378
3379#ifdef DOT11_N_SUPPORT
3380VOID BATableInit(
3381 IN PRTMP_ADAPTER pAd,
3382 IN BA_TABLE *Tab)
3383{
3384 int i;
3385
3386 Tab->numAsOriginator = 0;
3387 Tab->numAsRecipient = 0;
3388 NdisAllocateSpinLock(&pAd->BATabLock);
3389 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3390 {
3391 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3392 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3393 }
3394 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3395 {
3396 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3397 }
3398}
3399#endif // DOT11_N_SUPPORT //
3400
3401/*! \brief search the BSS table by SSID
3402 * \param p_tab pointer to the bss table
3403 * \param ssid SSID string
3404 * \return index of the table, BSS_NOT_FOUND if not in the table
3405 * \pre
3406 * \post
3407 * \note search by sequential search
3408
3409 IRQL = DISPATCH_LEVEL
3410
3411 */
3412ULONG BssTableSearch(
3413 IN BSS_TABLE *Tab,
3414 IN PUCHAR pBssid,
3415 IN UCHAR Channel)
3416{
3417 UCHAR i;
3418
3419 for (i = 0; i < Tab->BssNr; i++)
3420 {
3421 //
3422 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3423 // We should distinguish this case.
3424 //
3425 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3426 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3427 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3428 {
3429 return i;
3430 }
3431 }
3432 return (ULONG)BSS_NOT_FOUND;
3433}
3434
3435ULONG BssSsidTableSearch(
3436 IN BSS_TABLE *Tab,
3437 IN PUCHAR pBssid,
3438 IN PUCHAR pSsid,
3439 IN UCHAR SsidLen,
3440 IN UCHAR Channel)
3441{
3442 UCHAR i;
3443
3444 for (i = 0; i < Tab->BssNr; i++)
3445 {
3446 //
3447 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3448 // We should distinguish this case.
3449 //
3450 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3451 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3452 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3453 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3454 {
3455 return i;
3456 }
3457 }
3458 return (ULONG)BSS_NOT_FOUND;
3459}
3460
3461ULONG BssTableSearchWithSSID(
3462 IN BSS_TABLE *Tab,
3463 IN PUCHAR Bssid,
3464 IN PUCHAR pSsid,
3465 IN UCHAR SsidLen,
3466 IN UCHAR Channel)
3467{
3468 UCHAR i;
3469
3470 for (i = 0; i < Tab->BssNr; i++)
3471 {
3472 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3473 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3474 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3475 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3476 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3477 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3478 {
3479 return i;
3480 }
3481 }
3482 return (ULONG)BSS_NOT_FOUND;
3483}
3484
3485// IRQL = DISPATCH_LEVEL
3486VOID BssTableDeleteEntry(
3487 IN OUT BSS_TABLE *Tab,
3488 IN PUCHAR pBssid,
3489 IN UCHAR Channel)
3490{
3491 UCHAR i, j;
3492
3493 for (i = 0; i < Tab->BssNr; i++)
3494 {
3495 if ((Tab->BssEntry[i].Channel == Channel) &&
3496 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3497 {
3498 for (j = i; j < Tab->BssNr - 1; j++)
3499 {
3500 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3501 }
3502 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3503 Tab->BssNr -= 1;
3504 return;
3505 }
3506 }
3507}
3508
3509#ifdef DOT11_N_SUPPORT
3510/*
3511 ========================================================================
3512 Routine Description:
3513 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3514
3515 Arguments:
3516 // IRQL = DISPATCH_LEVEL
3517 ========================================================================
3518*/
3519VOID BATableDeleteORIEntry(
3520 IN OUT PRTMP_ADAPTER pAd,
3521 IN BA_ORI_ENTRY *pBAORIEntry)
3522{
3523
3524 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3525 {
3526 NdisAcquireSpinLock(&pAd->BATabLock);
3527 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3528 {
3529 pAd->BATable.numAsOriginator -= 1;
3530 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3531 // Erase Bitmap flag.
3532 }
3533 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3534 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3535 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3536 pBAORIEntry->Token = 1;
3537 // Not clear Sequence here.
3538 NdisReleaseSpinLock(&pAd->BATabLock);
3539 }
3540}
3541#endif // DOT11_N_SUPPORT //
3542
3543/*! \brief
3544 * \param
3545 * \return
3546 * \pre
3547 * \post
3548
3549 IRQL = DISPATCH_LEVEL
3550
3551 */
3552VOID BssEntrySet(
3553 IN PRTMP_ADAPTER pAd,
3554 OUT BSS_ENTRY *pBss,
3555 IN PUCHAR pBssid,
3556 IN CHAR Ssid[],
3557 IN UCHAR SsidLen,
3558 IN UCHAR BssType,
3559 IN USHORT BeaconPeriod,
3560 IN PCF_PARM pCfParm,
3561 IN USHORT AtimWin,
3562 IN USHORT CapabilityInfo,
3563 IN UCHAR SupRate[],
3564 IN UCHAR SupRateLen,
3565 IN UCHAR ExtRate[],
3566 IN UCHAR ExtRateLen,
3567 IN HT_CAPABILITY_IE *pHtCapability,
3568 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3569 IN UCHAR HtCapabilityLen,
3570 IN UCHAR AddHtInfoLen,
3571 IN UCHAR NewExtChanOffset,
3572 IN UCHAR Channel,
3573 IN CHAR Rssi,
3574 IN LARGE_INTEGER TimeStamp,
3575 IN UCHAR CkipFlag,
3576 IN PEDCA_PARM pEdcaParm,
3577 IN PQOS_CAPABILITY_PARM pQosCapability,
3578 IN PQBSS_LOAD_PARM pQbssLoad,
3579 IN USHORT LengthVIE,
3580 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3581{
3582 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3583 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3584 pBss->Hidden = 1;
3585 if (SsidLen > 0)
3586 {
3587 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3588 // Or send beacon /probe response with SSID len matching real SSID length,
3589 // but SSID is all zero. such as "00-00-00-00" with length 4.
3590 // We have to prevent this case overwrite correct table
3591 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3592 {
3593 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3594 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3595 pBss->SsidLen = SsidLen;
3596 pBss->Hidden = 0;
3597 }
3598 }
3599 else
3600 pBss->SsidLen = 0;
3601 pBss->BssType = BssType;
3602 pBss->BeaconPeriod = BeaconPeriod;
3603 if (BssType == BSS_INFRA)
3604 {
3605 if (pCfParm->bValid)
3606 {
3607 pBss->CfpCount = pCfParm->CfpCount;
3608 pBss->CfpPeriod = pCfParm->CfpPeriod;
3609 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3610 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3611 }
3612 }
3613 else
3614 {
3615 pBss->AtimWin = AtimWin;
3616 }
3617
3618 pBss->CapabilityInfo = CapabilityInfo;
3619 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3620 // Combine with AuthMode, they will decide the connection methods.
3621 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3622 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3623 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3624 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3625 else
3626 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3627 pBss->SupRateLen = SupRateLen;
3628 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3629 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3630 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3631 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3632 pBss->NewExtChanOffset = NewExtChanOffset;
3633 pBss->ExtRateLen = ExtRateLen;
3634 pBss->Channel = Channel;
3635 pBss->CentralChannel = Channel;
3636 pBss->Rssi = Rssi;
3637 // Update CkipFlag. if not exists, the value is 0x0
3638 pBss->CkipFlag = CkipFlag;
3639
3640 // New for microsoft Fixed IEs
3641 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3642 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3643 pBss->FixIEs.Capabilities = CapabilityInfo;
3644
3645 // New for microsoft Variable IEs
3646 if (LengthVIE != 0)
3647 {
3648 pBss->VarIELen = LengthVIE;
3649 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3650 }
3651 else
3652 {
3653 pBss->VarIELen = 0;
3654 }
3655
3656 pBss->AddHtInfoLen = 0;
3657 pBss->HtCapabilityLen = 0;
3658#ifdef DOT11_N_SUPPORT
3659 if (HtCapabilityLen> 0)
3660 {
3661 pBss->HtCapabilityLen = HtCapabilityLen;
3662 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3663 if (AddHtInfoLen > 0)
3664 {
3665 pBss->AddHtInfoLen = AddHtInfoLen;
3666 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3667
3668 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3669 {
3670 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3671 }
3672 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3673 {
3674 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3675 }
3676 }
3677 }
3678#endif // DOT11_N_SUPPORT //
3679
3680 BssCipherParse(pBss);
3681
3682 // new for QOS
3683 if (pEdcaParm)
3684 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3685 else
3686 pBss->EdcaParm.bValid = FALSE;
3687 if (pQosCapability)
3688 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3689 else
3690 pBss->QosCapability.bValid = FALSE;
3691 if (pQbssLoad)
3692 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3693 else
3694 pBss->QbssLoad.bValid = FALSE;
3695
3696#ifdef CONFIG_STA_SUPPORT
3697 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3698 {
3699 PEID_STRUCT pEid;
3700 USHORT Length = 0;
3701
3702
3703 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3704 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3705#ifdef EXT_BUILD_CHANNEL_LIST
3706 NdisZeroMemory(&pBss->CountryString[0], 3);
3707 pBss->bHasCountryIE = FALSE;
3708#endif // EXT_BUILD_CHANNEL_LIST //
3709 pEid = (PEID_STRUCT) pVIE;
3710 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3711 {
3712 switch(pEid->Eid)
3713 {
3714 case IE_WPA:
3715 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3716 {
3717 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3718 {
3719 pBss->WpaIE.IELen = 0;
3720 break;
3721 }
3722 pBss->WpaIE.IELen = pEid->Len + 2;
3723 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3724 }
3725 break;
3726 case IE_RSN:
3727 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3728 {
3729 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3730 {
3731 pBss->RsnIE.IELen = 0;
3732 break;
3733 }
3734 pBss->RsnIE.IELen = pEid->Len + 2;
3735 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3736 }
3737 break;
3738#ifdef EXT_BUILD_CHANNEL_LIST
3739 case IE_COUNTRY:
3740 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3741 pBss->bHasCountryIE = TRUE;
3742 break;
3743#endif // EXT_BUILD_CHANNEL_LIST //
3744 }
3745 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3746 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3747 }
3748 }
3749#endif // CONFIG_STA_SUPPORT //
3750}
3751
3752/*!
3753 * \brief insert an entry into the bss table
3754 * \param p_tab The BSS table
3755 * \param Bssid BSSID
3756 * \param ssid SSID
3757 * \param ssid_len Length of SSID
3758 * \param bss_type
3759 * \param beacon_period
3760 * \param timestamp
3761 * \param p_cf
3762 * \param atim_win
3763 * \param cap
3764 * \param rates
3765 * \param rates_len
3766 * \param channel_idx
3767 * \return none
3768 * \pre
3769 * \post
3770 * \note If SSID is identical, the old entry will be replaced by the new one
3771
3772 IRQL = DISPATCH_LEVEL
3773
3774 */
3775ULONG BssTableSetEntry(
3776 IN PRTMP_ADAPTER pAd,
3777 OUT BSS_TABLE *Tab,
3778 IN PUCHAR pBssid,
3779 IN CHAR Ssid[],
3780 IN UCHAR SsidLen,
3781 IN UCHAR BssType,
3782 IN USHORT BeaconPeriod,
3783 IN CF_PARM *CfParm,
3784 IN USHORT AtimWin,
3785 IN USHORT CapabilityInfo,
3786 IN UCHAR SupRate[],
3787 IN UCHAR SupRateLen,
3788 IN UCHAR ExtRate[],
3789 IN UCHAR ExtRateLen,
3790 IN HT_CAPABILITY_IE *pHtCapability,
3791 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3792 IN UCHAR HtCapabilityLen,
3793 IN UCHAR AddHtInfoLen,
3794 IN UCHAR NewExtChanOffset,
3795 IN UCHAR ChannelNo,
3796 IN CHAR Rssi,
3797 IN LARGE_INTEGER TimeStamp,
3798 IN UCHAR CkipFlag,
3799 IN PEDCA_PARM pEdcaParm,
3800 IN PQOS_CAPABILITY_PARM pQosCapability,
3801 IN PQBSS_LOAD_PARM pQbssLoad,
3802 IN USHORT LengthVIE,
3803 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3804{
3805 ULONG Idx;
3806
3807 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3808 if (Idx == BSS_NOT_FOUND)
3809 {
3810 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3811 {
3812 //
3813 // It may happen when BSS Table was full.
3814 // The desired AP will not be added into BSS Table
3815 // In this case, if we found the desired AP then overwrite BSS Table.
3816 //
3817 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3818 {
3819 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3820 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3821 {
3822 Idx = Tab->BssOverlapNr;
3823 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3824 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3825 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3826 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3827 }
3828 return Idx;
3829 }
3830 else
3831 {
3832 return BSS_NOT_FOUND;
3833 }
3834 }
3835 Idx = Tab->BssNr;
3836 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3837 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3838 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3839 Tab->BssNr++;
3840 }
3841 else
3842 {
3843 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3844 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3845 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3846 }
3847
3848 return Idx;
3849}
3850
3851#ifdef CONFIG_STA_SUPPORT
3852#ifdef DOT11_N_SUPPORT
3853#ifdef DOT11N_DRAFT3
3854VOID TriEventInit(
3855 IN PRTMP_ADAPTER pAd)
3856{
3857 UCHAR i;
3858
3859 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3860 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3861
3862 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3863 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3864}
3865
3866ULONG TriEventTableSetEntry(
3867 IN PRTMP_ADAPTER pAd,
3868 OUT TRIGGER_EVENT_TAB *Tab,
3869 IN PUCHAR pBssid,
3870 IN HT_CAPABILITY_IE *pHtCapability,
3871 IN UCHAR HtCapabilityLen,
3872 IN UCHAR RegClass,
3873 IN UCHAR ChannelNo)
3874{
3875 // Event A
3876 if (HtCapabilityLen == 0)
3877 {
3878 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3879 {
3880 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3881 Tab->EventA[Tab->EventANo].bValid = TRUE;
3882 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3883 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3884 if (RegClass != 0)
3885 {
3886 // Beacon has Regulatory class IE. So use beacon's
3887 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3888 }
3889 else
3890 {
3891 // Use Station's Regulatory class instead.
3892 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3893 {
3894 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3895 {
3896 Tab->EventA[Tab->EventANo].RegClass = 32;
3897 }
3898 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3899 Tab->EventA[Tab->EventANo].RegClass = 33;
3900 }
3901 else
3902 Tab->EventA[Tab->EventANo].RegClass = ??;
3903
3904 }
3905
3906 Tab->EventANo ++;
3907 }
3908 }
3909 else if (pHtCapability->HtCapInfo.Intolerant40)
3910 {
3911 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3912 }
3913
3914}
3915
3916/*
3917 ========================================================================
3918 Routine Description:
3919 Trigger Event table Maintainence called once every second.
3920
3921 Arguments:
3922 // IRQL = DISPATCH_LEVEL
3923 ========================================================================
3924*/
3925VOID TriEventCounterMaintenance(
3926 IN PRTMP_ADAPTER pAd)
3927{
3928 UCHAR i;
3929 BOOLEAN bNotify = FALSE;
3930 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3931 {
3932 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3933 {
3934 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3935 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3936 {
3937 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3938 pAd->CommonCfg.TriggerEventTab.EventANo --;
3939 // Need to send 20/40 Coexistence Notify frame if has status change.
3940 bNotify = TRUE;
3941 }
3942 }
3943 }
3944 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3945 {
3946 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3947 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3948 bNotify = TRUE;
3949 }
3950
3951 if (bNotify == TRUE)
3952 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3953}
3954#endif // DOT11N_DRAFT3 //
3955#endif // DOT11_N_SUPPORT //
3956
3957// IRQL = DISPATCH_LEVEL
3958VOID BssTableSsidSort(
3959 IN PRTMP_ADAPTER pAd,
3960 OUT BSS_TABLE *OutTab,
3961 IN CHAR Ssid[],
3962 IN UCHAR SsidLen)
3963{
3964 INT i;
3965 BssTableInit(OutTab);
3966
3967 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3968 {
3969 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3970 BOOLEAN bIsHiddenApIncluded = FALSE;
3971
3972 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3973 (pAd->MlmeAux.Channel > 14) &&
3974 RadarChannelCheck(pAd, pInBss->Channel))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003975 )
3976 {
3977 if (pInBss->Hidden)
3978 bIsHiddenApIncluded = TRUE;
3979 }
3980
3981 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3982 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3983 {
3984 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3985
3986
3987#ifdef EXT_BUILD_CHANNEL_LIST
3988 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
3989 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
3990 (pInBss->bHasCountryIE == FALSE))
3991 {
3992 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
3993 continue;
3994 }
3995#endif // EXT_BUILD_CHANNEL_LIST //
3996
3997#ifdef DOT11_N_SUPPORT
3998 // 2.4G/5G N only mode
3999 if ((pInBss->HtCapabilityLen == 0) &&
4000 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4001 {
4002 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4003 continue;
4004 }
4005#endif // DOT11_N_SUPPORT //
4006
4007 // New for WPA2
4008 // Check the Authmode first
4009 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4010 {
4011 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4012 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4013 // None matched
4014 continue;
4015
4016 // Check cipher suite, AP must have more secured cipher than station setting
4017 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4018 {
4019 // If it's not mixed mode, we should only let BSS pass with the same encryption
4020 if (pInBss->WPA.bMixMode == FALSE)
4021 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4022 continue;
4023
4024 // check group cipher
Adam McDanieled291e82009-02-23 08:01:07 -07004025 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4026 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4027 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004028 continue;
4029
4030 // check pairwise cipher, skip if none matched
4031 // If profile set to AES, let it pass without question.
4032 // If profile set to TKIP, we must find one mateched
4033 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4034 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4035 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4036 continue;
4037 }
4038 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4039 {
4040 // If it's not mixed mode, we should only let BSS pass with the same encryption
4041 if (pInBss->WPA2.bMixMode == FALSE)
4042 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4043 continue;
4044
4045 // check group cipher
Adam McDanieled291e82009-02-23 08:01:07 -07004046 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4047 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4048 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004049 continue;
4050
4051 // check pairwise cipher, skip if none matched
4052 // If profile set to AES, let it pass without question.
4053 // If profile set to TKIP, we must find one mateched
4054 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4055 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4056 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4057 continue;
4058 }
4059 }
4060 // Bss Type matched, SSID matched.
4061 // We will check wepstatus for qualification Bss
4062 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4063 {
4064 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4065 //
4066 // For the SESv2 case, we will not qualify WepStatus.
4067 //
4068 if (!pInBss->bSES)
4069 continue;
4070 }
4071
4072 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4073 // It definitely will fail. So, skip it.
4074 // CCX also require not even try to connect it!!
4075 if (SsidLen == 0)
4076 continue;
4077
4078#ifdef DOT11_N_SUPPORT
4079 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4080 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4081 if ((pInBss->CentralChannel != pInBss->Channel) &&
4082 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4083 {
4084 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4085 {
4086 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4087 SetCommonHT(pAd);
4088 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4089 }
4090 else
4091 {
4092 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4093 {
4094 SetCommonHT(pAd);
4095 }
4096 }
4097 }
4098#endif // DOT11_N_SUPPORT //
4099
4100 // copy matching BSS from InTab to OutTab
4101 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4102
4103 OutTab->BssNr++;
4104 }
4105 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4106 {
4107 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4108
4109
4110#ifdef DOT11_N_SUPPORT
4111 // 2.4G/5G N only mode
4112 if ((pInBss->HtCapabilityLen == 0) &&
4113 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4114 {
4115 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4116 continue;
4117 }
4118#endif // DOT11_N_SUPPORT //
4119
4120 // New for WPA2
4121 // Check the Authmode first
4122 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4123 {
4124 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4125 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4126 // None matched
4127 continue;
4128
4129 // Check cipher suite, AP must have more secured cipher than station setting
4130 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4131 {
4132 // If it's not mixed mode, we should only let BSS pass with the same encryption
4133 if (pInBss->WPA.bMixMode == FALSE)
4134 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4135 continue;
4136
4137 // check group cipher
4138 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4139 continue;
4140
4141 // check pairwise cipher, skip if none matched
4142 // If profile set to AES, let it pass without question.
4143 // If profile set to TKIP, we must find one mateched
4144 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4145 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4146 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4147 continue;
4148 }
4149 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4150 {
4151 // If it's not mixed mode, we should only let BSS pass with the same encryption
4152 if (pInBss->WPA2.bMixMode == FALSE)
4153 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4154 continue;
4155
4156 // check group cipher
4157 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4158 continue;
4159
4160 // check pairwise cipher, skip if none matched
4161 // If profile set to AES, let it pass without question.
4162 // If profile set to TKIP, we must find one mateched
4163 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4164 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4165 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4166 continue;
4167 }
4168 }
4169 // Bss Type matched, SSID matched.
4170 // We will check wepstatus for qualification Bss
4171 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4172 continue;
4173
4174#ifdef DOT11_N_SUPPORT
4175 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4176 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4177 if ((pInBss->CentralChannel != pInBss->Channel) &&
4178 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4179 {
4180 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4181 {
4182 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4183 SetCommonHT(pAd);
4184 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4185 }
4186 }
4187#endif // DOT11_N_SUPPORT //
4188
4189 // copy matching BSS from InTab to OutTab
4190 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4191
4192 OutTab->BssNr++;
4193 }
4194
4195 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4196 break;
4197 }
4198
4199 BssTableSortByRssi(OutTab);
4200}
4201
4202
4203// IRQL = DISPATCH_LEVEL
4204VOID BssTableSortByRssi(
4205 IN OUT BSS_TABLE *OutTab)
4206{
4207 INT i, j;
4208 BSS_ENTRY TmpBss;
4209
4210 for (i = 0; i < OutTab->BssNr - 1; i++)
4211 {
4212 for (j = i+1; j < OutTab->BssNr; j++)
4213 {
4214 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4215 {
4216 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4217 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4218 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4219 }
4220 }
4221 }
4222}
4223#endif // CONFIG_STA_SUPPORT //
4224
4225
4226VOID BssCipherParse(
4227 IN OUT PBSS_ENTRY pBss)
4228{
4229 PEID_STRUCT pEid;
4230 PUCHAR pTmp;
4231 PRSN_IE_HEADER_STRUCT pRsnHeader;
4232 PCIPHER_SUITE_STRUCT pCipher;
4233 PAKM_SUITE_STRUCT pAKM;
4234 USHORT Count;
4235 INT Length;
4236 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4237
4238 //
4239 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4240 //
4241 if (pBss->Privacy)
4242 {
4243 pBss->WepStatus = Ndis802_11WEPEnabled;
4244 }
4245 else
4246 {
4247 pBss->WepStatus = Ndis802_11WEPDisabled;
4248 }
4249 // Set default to disable & open authentication before parsing variable IE
4250 pBss->AuthMode = Ndis802_11AuthModeOpen;
4251 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4252
4253 // Init WPA setting
4254 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4255 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4256 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4257 pBss->WPA.RsnCapability = 0;
4258 pBss->WPA.bMixMode = FALSE;
4259
4260 // Init WPA2 setting
4261 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4262 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4263 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4264 pBss->WPA2.RsnCapability = 0;
4265 pBss->WPA2.bMixMode = FALSE;
4266
4267
4268 Length = (INT) pBss->VarIELen;
4269
4270 while (Length > 0)
4271 {
4272 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4273 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4274 pEid = (PEID_STRUCT) pTmp;
4275 switch (pEid->Eid)
4276 {
4277 case IE_WPA:
4278 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4279 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4280 {
4281 pTmp += 11;
4282 switch (*pTmp)
4283 {
4284 case 1:
4285 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4286 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4287 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4288 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4289 break;
4290 case 2:
4291 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4292 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4293 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4294 break;
4295 case 4:
4296 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4297 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4298 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4299 break;
4300 default:
4301 break;
4302 }
4303
4304 // if Cisco IE_WPA, break
4305 break;
4306 }
4307 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4308 {
4309 pBss->bSES = TRUE;
4310 break;
4311 }
4312 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4313 {
4314 // if unsupported vendor specific IE
4315 break;
4316 }
4317 // Skip OUI, version, and multicast suite
4318 // This part should be improved in the future when AP supported multiple cipher suite.
4319 // For now, it's OK since almost all APs have fixed cipher suite supported.
4320 // pTmp = (PUCHAR) pEid->Octet;
4321 pTmp += 11;
4322
4323 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4324 // Value Meaning
4325 // 0 None
4326 // 1 WEP-40
4327 // 2 Tkip
4328 // 3 WRAP
4329 // 4 AES
4330 // 5 WEP-104
4331 // Parse group cipher
4332 switch (*pTmp)
4333 {
4334 case 1:
Adam McDanieled291e82009-02-23 08:01:07 -07004335 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4336 break;
4337 case 5:
4338 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004339 break;
4340 case 2:
4341 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4342 break;
4343 case 4:
4344 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4345 break;
4346 default:
4347 break;
4348 }
4349 // number of unicast suite
4350 pTmp += 1;
4351
4352 // skip all unicast cipher suites
4353 //Count = *(PUSHORT) pTmp;
4354 Count = (pTmp[1]<<8) + pTmp[0];
4355 pTmp += sizeof(USHORT);
4356
4357 // Parsing all unicast cipher suite
4358 while (Count > 0)
4359 {
4360 // Skip OUI
4361 pTmp += 3;
4362 TmpCipher = Ndis802_11WEPDisabled;
4363 switch (*pTmp)
4364 {
4365 case 1:
4366 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4367 TmpCipher = Ndis802_11Encryption1Enabled;
4368 break;
4369 case 2:
4370 TmpCipher = Ndis802_11Encryption2Enabled;
4371 break;
4372 case 4:
4373 TmpCipher = Ndis802_11Encryption3Enabled;
4374 break;
4375 default:
4376 break;
4377 }
4378 if (TmpCipher > pBss->WPA.PairCipher)
4379 {
4380 // Move the lower cipher suite to PairCipherAux
4381 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4382 pBss->WPA.PairCipher = TmpCipher;
4383 }
4384 else
4385 {
4386 pBss->WPA.PairCipherAux = TmpCipher;
4387 }
4388 pTmp++;
4389 Count--;
4390 }
4391
4392 // 4. get AKM suite counts
4393 //Count = *(PUSHORT) pTmp;
4394 Count = (pTmp[1]<<8) + pTmp[0];
4395 pTmp += sizeof(USHORT);
4396 pTmp += 3;
4397
4398 switch (*pTmp)
4399 {
4400 case 1:
4401 // Set AP support WPA mode
4402 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4403 pBss->AuthMode = Ndis802_11AuthModeWPA;
4404 else
4405 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4406 break;
4407 case 2:
4408 // Set AP support WPA mode
4409 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4410 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4411 else
4412 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4413 break;
4414 default:
4415 break;
4416 }
4417 pTmp += 1;
4418
4419 // Fixed for WPA-None
4420 if (pBss->BssType == BSS_ADHOC)
4421 {
4422 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4423 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4424 pBss->WepStatus = pBss->WPA.GroupCipher;
4425 // Patched bugs for old driver
4426 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4427 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4428 }
4429 else
4430 pBss->WepStatus = pBss->WPA.PairCipher;
4431
4432 // Check the Pair & Group, if different, turn on mixed mode flag
4433 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4434 pBss->WPA.bMixMode = TRUE;
4435
4436 break;
4437
4438 case IE_RSN:
4439 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4440
4441 // 0. Version must be 1
4442 if (le2cpu16(pRsnHeader->Version) != 1)
4443 break;
4444 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4445
4446 // 1. Check group cipher
4447 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4448 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4449 break;
4450
4451 // Parse group cipher
4452 switch (pCipher->Type)
4453 {
4454 case 1:
Adam McDanieled291e82009-02-23 08:01:07 -07004455 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4456 break;
4457 case 5:
4458 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004459 break;
4460 case 2:
4461 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4462 break;
4463 case 4:
4464 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4465 break;
4466 default:
4467 break;
4468 }
4469 // set to correct offset for next parsing
4470 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4471
4472 // 2. Get pairwise cipher counts
4473 //Count = *(PUSHORT) pTmp;
4474 Count = (pTmp[1]<<8) + pTmp[0];
4475 pTmp += sizeof(USHORT);
4476
4477 // 3. Get pairwise cipher
4478 // Parsing all unicast cipher suite
4479 while (Count > 0)
4480 {
4481 // Skip OUI
4482 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4483 TmpCipher = Ndis802_11WEPDisabled;
4484 switch (pCipher->Type)
4485 {
4486 case 1:
4487 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4488 TmpCipher = Ndis802_11Encryption1Enabled;
4489 break;
4490 case 2:
4491 TmpCipher = Ndis802_11Encryption2Enabled;
4492 break;
4493 case 4:
4494 TmpCipher = Ndis802_11Encryption3Enabled;
4495 break;
4496 default:
4497 break;
4498 }
4499 if (TmpCipher > pBss->WPA2.PairCipher)
4500 {
4501 // Move the lower cipher suite to PairCipherAux
4502 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4503 pBss->WPA2.PairCipher = TmpCipher;
4504 }
4505 else
4506 {
4507 pBss->WPA2.PairCipherAux = TmpCipher;
4508 }
4509 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4510 Count--;
4511 }
4512
4513 // 4. get AKM suite counts
4514 //Count = *(PUSHORT) pTmp;
4515 Count = (pTmp[1]<<8) + pTmp[0];
4516 pTmp += sizeof(USHORT);
4517
4518 // 5. Get AKM ciphers
4519 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4520 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4521 break;
4522
4523 switch (pAKM->Type)
4524 {
4525 case 1:
4526 // Set AP support WPA mode
4527 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4528 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4529 else
4530 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4531 break;
4532 case 2:
4533 // Set AP support WPA mode
4534 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4535 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4536 else
4537 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4538 break;
4539 default:
4540 break;
4541 }
4542 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4543
4544 // Fixed for WPA-None
4545 if (pBss->BssType == BSS_ADHOC)
4546 {
4547 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4548 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4549 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4550 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4551 pBss->WepStatus = pBss->WPA.GroupCipher;
4552 // Patched bugs for old driver
4553 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4554 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4555 }
4556 pBss->WepStatus = pBss->WPA2.PairCipher;
4557
4558 // 6. Get RSN capability
4559 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4560 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4561 pTmp += sizeof(USHORT);
4562
4563 // Check the Pair & Group, if different, turn on mixed mode flag
4564 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4565 pBss->WPA2.bMixMode = TRUE;
4566
4567 break;
4568 default:
4569 break;
4570 }
4571 Length -= (pEid->Len + 2);
4572 }
4573}
4574
4575// ===========================================================================================
4576// mac_table.c
4577// ===========================================================================================
4578
4579/*! \brief generates a random mac address value for IBSS BSSID
4580 * \param Addr the bssid location
4581 * \return none
4582 * \pre
4583 * \post
4584 */
4585VOID MacAddrRandomBssid(
4586 IN PRTMP_ADAPTER pAd,
4587 OUT PUCHAR pAddr)
4588{
4589 INT i;
4590
4591 for (i = 0; i < MAC_ADDR_LEN; i++)
4592 {
4593 pAddr[i] = RandomByte(pAd);
4594 }
4595
4596 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4597}
4598
4599/*! \brief init the management mac frame header
4600 * \param p_hdr mac header
4601 * \param subtype subtype of the frame
4602 * \param p_ds destination address, don't care if it is a broadcast address
4603 * \return none
4604 * \pre the station has the following information in the pAd->StaCfg
4605 * - bssid
4606 * - station address
4607 * \post
4608 * \note this function initializes the following field
4609
4610 IRQL = PASSIVE_LEVEL
4611 IRQL = DISPATCH_LEVEL
4612
4613 */
4614VOID MgtMacHeaderInit(
4615 IN PRTMP_ADAPTER pAd,
4616 IN OUT PHEADER_802_11 pHdr80211,
4617 IN UCHAR SubType,
4618 IN UCHAR ToDs,
4619 IN PUCHAR pDA,
4620 IN PUCHAR pBssid)
4621{
4622 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4623
4624 pHdr80211->FC.Type = BTYPE_MGMT;
4625 pHdr80211->FC.SubType = SubType;
4626 pHdr80211->FC.ToDs = ToDs;
4627 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4628#ifdef CONFIG_STA_SUPPORT
4629 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4630 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4631#endif // CONFIG_STA_SUPPORT //
4632 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4633}
4634
4635// ===========================================================================================
4636// mem_mgmt.c
4637// ===========================================================================================
4638
4639/*!***************************************************************************
4640 * This routine build an outgoing frame, and fill all information specified
4641 * in argument list to the frame body. The actual frame size is the summation
4642 * of all arguments.
4643 * input params:
4644 * Buffer - pointer to a pre-allocated memory segment
4645 * args - a list of <int arg_size, arg> pairs.
4646 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4647 * function will FAIL!!!
4648 * return:
4649 * Size of the buffer
4650 * usage:
4651 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4652
4653 IRQL = PASSIVE_LEVEL
4654 IRQL = DISPATCH_LEVEL
4655
4656 ****************************************************************************/
4657ULONG MakeOutgoingFrame(
4658 OUT CHAR *Buffer,
4659 OUT ULONG *FrameLen, ...)
4660{
4661 CHAR *p;
4662 int leng;
4663 ULONG TotLeng;
4664 va_list Args;
4665
4666 // calculates the total length
4667 TotLeng = 0;
4668 va_start(Args, FrameLen);
4669 do
4670 {
4671 leng = va_arg(Args, int);
4672 if (leng == END_OF_ARGS)
4673 {
4674 break;
4675 }
4676 p = va_arg(Args, PVOID);
4677 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4678 TotLeng = TotLeng + leng;
4679 } while(TRUE);
4680
4681 va_end(Args); /* clean up */
4682 *FrameLen = TotLeng;
4683 return TotLeng;
4684}
4685
4686// ===========================================================================================
4687// mlme_queue.c
4688// ===========================================================================================
4689
4690/*! \brief Initialize The MLME Queue, used by MLME Functions
4691 * \param *Queue The MLME Queue
4692 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4693 * \pre
4694 * \post
4695 * \note Because this is done only once (at the init stage), no need to be locked
4696
4697 IRQL = PASSIVE_LEVEL
4698
4699 */
4700NDIS_STATUS MlmeQueueInit(
4701 IN MLME_QUEUE *Queue)
4702{
4703 INT i;
4704
4705 NdisAllocateSpinLock(&Queue->Lock);
4706
4707 Queue->Num = 0;
4708 Queue->Head = 0;
4709 Queue->Tail = 0;
4710
4711 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4712 {
4713 Queue->Entry[i].Occupied = FALSE;
4714 Queue->Entry[i].MsgLen = 0;
4715 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4716 }
4717
4718 return NDIS_STATUS_SUCCESS;
4719}
4720
4721/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4722 * \param *Queue The MLME Queue
4723 * \param Machine The State Machine Id
4724 * \param MsgType The Message Type
4725 * \param MsgLen The Message length
4726 * \param *Msg The message pointer
4727 * \return TRUE if enqueue is successful, FALSE if the queue is full
4728 * \pre
4729 * \post
4730 * \note The message has to be initialized
4731
4732 IRQL = PASSIVE_LEVEL
4733 IRQL = DISPATCH_LEVEL
4734
4735 */
4736BOOLEAN MlmeEnqueue(
4737 IN PRTMP_ADAPTER pAd,
4738 IN ULONG Machine,
4739 IN ULONG MsgType,
4740 IN ULONG MsgLen,
4741 IN VOID *Msg)
4742{
4743 INT Tail;
4744 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4745
4746 // Do nothing if the driver is starting halt state.
4747 // This might happen when timer already been fired before cancel timer with mlmehalt
4748 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4749 return FALSE;
4750
4751 // First check the size, it MUST not exceed the mlme queue size
4752 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4753 {
4754 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4755 return FALSE;
4756 }
4757
4758 if (MlmeQueueFull(Queue))
4759 {
4760 return FALSE;
4761 }
4762
4763 NdisAcquireSpinLock(&(Queue->Lock));
4764 Tail = Queue->Tail;
4765 Queue->Tail++;
4766 Queue->Num++;
4767 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4768 {
4769 Queue->Tail = 0;
4770 }
4771
4772 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4773 Queue->Entry[Tail].Occupied = TRUE;
4774 Queue->Entry[Tail].Machine = Machine;
4775 Queue->Entry[Tail].MsgType = MsgType;
4776 Queue->Entry[Tail].MsgLen = MsgLen;
4777
4778 if (Msg != NULL)
4779 {
4780 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4781 }
4782
4783 NdisReleaseSpinLock(&(Queue->Lock));
4784 return TRUE;
4785}
4786
4787/*! \brief This function is used when Recv gets a MLME message
4788 * \param *Queue The MLME Queue
4789 * \param TimeStampHigh The upper 32 bit of timestamp
4790 * \param TimeStampLow The lower 32 bit of timestamp
4791 * \param Rssi The receiving RSSI strength
4792 * \param MsgLen The length of the message
4793 * \param *Msg The message pointer
4794 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4795 * \pre
4796 * \post
4797
4798 IRQL = DISPATCH_LEVEL
4799
4800 */
4801BOOLEAN MlmeEnqueueForRecv(
4802 IN PRTMP_ADAPTER pAd,
4803 IN ULONG Wcid,
4804 IN ULONG TimeStampHigh,
4805 IN ULONG TimeStampLow,
4806 IN UCHAR Rssi0,
4807 IN UCHAR Rssi1,
4808 IN UCHAR Rssi2,
4809 IN ULONG MsgLen,
4810 IN VOID *Msg,
4811 IN UCHAR Signal)
4812{
4813 INT Tail, Machine;
4814 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4815 INT MsgType;
4816 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4817
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004818 // Do nothing if the driver is starting halt state.
4819 // This might happen when timer already been fired before cancel timer with mlmehalt
4820 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4821 {
4822 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4823 return FALSE;
4824 }
4825
4826 // First check the size, it MUST not exceed the mlme queue size
4827 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4828 {
4829 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4830 return FALSE;
4831 }
4832
4833 if (MlmeQueueFull(Queue))
4834 {
4835 return FALSE;
4836 }
4837
4838#ifdef CONFIG_STA_SUPPORT
4839 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4840 {
4841 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4842 {
4843 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4844 return FALSE;
4845 }
4846 }
4847#endif // CONFIG_STA_SUPPORT //
4848
4849 // OK, we got all the informations, it is time to put things into queue
4850 NdisAcquireSpinLock(&(Queue->Lock));
4851 Tail = Queue->Tail;
4852 Queue->Tail++;
4853 Queue->Num++;
4854 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4855 {
4856 Queue->Tail = 0;
4857 }
4858 Queue->Entry[Tail].Occupied = TRUE;
4859 Queue->Entry[Tail].Machine = Machine;
4860 Queue->Entry[Tail].MsgType = MsgType;
4861 Queue->Entry[Tail].MsgLen = MsgLen;
4862 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4863 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4864 Queue->Entry[Tail].Rssi0 = Rssi0;
4865 Queue->Entry[Tail].Rssi1 = Rssi1;
4866 Queue->Entry[Tail].Rssi2 = Rssi2;
4867 Queue->Entry[Tail].Signal = Signal;
4868 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4869
4870 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4871
4872 if (Msg != NULL)
4873 {
4874 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4875 }
4876
4877 NdisReleaseSpinLock(&(Queue->Lock));
4878
4879 RT28XX_MLME_HANDLER(pAd);
4880
4881 return TRUE;
4882}
4883
4884
4885/*! \brief Dequeue a message from the MLME Queue
4886 * \param *Queue The MLME Queue
4887 * \param *Elem The message dequeued from MLME Queue
4888 * \return TRUE if the Elem contains something, FALSE otherwise
4889 * \pre
4890 * \post
4891
4892 IRQL = DISPATCH_LEVEL
4893
4894 */
4895BOOLEAN MlmeDequeue(
4896 IN MLME_QUEUE *Queue,
4897 OUT MLME_QUEUE_ELEM **Elem)
4898{
4899 NdisAcquireSpinLock(&(Queue->Lock));
4900 *Elem = &(Queue->Entry[Queue->Head]);
4901 Queue->Num--;
4902 Queue->Head++;
4903 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4904 {
4905 Queue->Head = 0;
4906 }
4907 NdisReleaseSpinLock(&(Queue->Lock));
4908 return TRUE;
4909}
4910
4911// IRQL = DISPATCH_LEVEL
4912VOID MlmeRestartStateMachine(
4913 IN PRTMP_ADAPTER pAd)
4914{
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004915 MLME_QUEUE_ELEM *Elem = NULL;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004916#ifdef CONFIG_STA_SUPPORT
4917 BOOLEAN Cancelled;
4918#endif // CONFIG_STA_SUPPORT //
4919
4920 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4921
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004922 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4923 if(pAd->Mlme.bRunning)
4924 {
4925 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4926 return;
4927 }
4928 else
4929 {
4930 pAd->Mlme.bRunning = TRUE;
4931 }
4932 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4933
4934 // Remove all Mlme queues elements
4935 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4936 {
4937 //From message type, determine which state machine I should drive
4938 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4939 {
4940 // free MLME element
4941 Elem->Occupied = FALSE;
4942 Elem->MsgLen = 0;
4943
4944 }
4945 else {
4946 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4947 }
4948 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004949
4950#ifdef CONFIG_STA_SUPPORT
4951 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4952 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004953 // Cancel all timer events
4954 // Be careful to cancel new added timer
4955 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4956 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4957 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4958 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4959 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4960 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004961 }
4962#endif // CONFIG_STA_SUPPORT //
4963
4964 // Change back to original channel in case of doing scan
4965 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4966 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4967
4968 // Resume MSDU which is turned off durning scan
4969 RTMPResumeMsduTransmission(pAd);
4970
4971#ifdef CONFIG_STA_SUPPORT
4972 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4973 {
4974 // Set all state machines back IDLE
4975 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4976 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4977 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4978 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4979 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4980 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004981 }
4982#endif // CONFIG_STA_SUPPORT //
4983
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004984 // Remove running state
4985 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4986 pAd->Mlme.bRunning = FALSE;
4987 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004988}
4989
4990/*! \brief test if the MLME Queue is empty
4991 * \param *Queue The MLME Queue
4992 * \return TRUE if the Queue is empty, FALSE otherwise
4993 * \pre
4994 * \post
4995
4996 IRQL = DISPATCH_LEVEL
4997
4998 */
4999BOOLEAN MlmeQueueEmpty(
5000 IN MLME_QUEUE *Queue)
5001{
5002 BOOLEAN Ans;
5003
5004 NdisAcquireSpinLock(&(Queue->Lock));
5005 Ans = (Queue->Num == 0);
5006 NdisReleaseSpinLock(&(Queue->Lock));
5007
5008 return Ans;
5009}
5010
5011/*! \brief test if the MLME Queue is full
5012 * \param *Queue The MLME Queue
5013 * \return TRUE if the Queue is empty, FALSE otherwise
5014 * \pre
5015 * \post
5016
5017 IRQL = PASSIVE_LEVEL
5018 IRQL = DISPATCH_LEVEL
5019
5020 */
5021BOOLEAN MlmeQueueFull(
5022 IN MLME_QUEUE *Queue)
5023{
5024 BOOLEAN Ans;
5025
5026 NdisAcquireSpinLock(&(Queue->Lock));
5027 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5028 NdisReleaseSpinLock(&(Queue->Lock));
5029
5030 return Ans;
5031}
5032
5033/*! \brief The destructor of MLME Queue
5034 * \param
5035 * \return
5036 * \pre
5037 * \post
5038 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5039
5040 IRQL = PASSIVE_LEVEL
5041
5042 */
5043VOID MlmeQueueDestroy(
5044 IN MLME_QUEUE *pQueue)
5045{
5046 NdisAcquireSpinLock(&(pQueue->Lock));
5047 pQueue->Num = 0;
5048 pQueue->Head = 0;
5049 pQueue->Tail = 0;
5050 NdisReleaseSpinLock(&(pQueue->Lock));
5051 NdisFreeSpinLock(&(pQueue->Lock));
5052}
5053
5054/*! \brief To substitute the message type if the message is coming from external
5055 * \param pFrame The frame received
5056 * \param *Machine The state machine
5057 * \param *MsgType the message type for the state machine
5058 * \return TRUE if the substitution is successful, FALSE otherwise
5059 * \pre
5060 * \post
5061
5062 IRQL = DISPATCH_LEVEL
5063
5064 */
5065#ifdef CONFIG_STA_SUPPORT
5066BOOLEAN MsgTypeSubst(
5067 IN PRTMP_ADAPTER pAd,
5068 IN PFRAME_802_11 pFrame,
5069 OUT INT *Machine,
5070 OUT INT *MsgType)
5071{
5072 USHORT Seq;
5073 UCHAR EAPType;
5074 PUCHAR pData;
5075
5076 // Pointer to start of data frames including SNAP header
5077 pData = (PUCHAR) pFrame + LENGTH_802_11;
5078
5079 // The only data type will pass to this function is EAPOL frame
5080 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5081 {
5082 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5083 {
5084 // Cisco Aironet SNAP header
5085 *Machine = AIRONET_STATE_MACHINE;
5086 *MsgType = MT2_AIRONET_MSG;
5087 return (TRUE);
5088 }
5089#ifdef LEAP_SUPPORT
5090 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5091 {
5092 // LEAP frames
5093 *Machine = LEAP_STATE_MACHINE;
5094 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5095 return (LeapMsgTypeSubst(EAPType, MsgType));
5096 }
5097 else
5098#endif // LEAP_SUPPORT //
5099 {
5100 *Machine = WPA_PSK_STATE_MACHINE;
5101 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5102 return(WpaMsgTypeSubst(EAPType, MsgType));
5103 }
5104 }
5105
5106 switch (pFrame->Hdr.FC.SubType)
5107 {
5108 case SUBTYPE_ASSOC_REQ:
5109 *Machine = ASSOC_STATE_MACHINE;
5110 *MsgType = MT2_PEER_ASSOC_REQ;
5111 break;
5112 case SUBTYPE_ASSOC_RSP:
5113 *Machine = ASSOC_STATE_MACHINE;
5114 *MsgType = MT2_PEER_ASSOC_RSP;
5115 break;
5116 case SUBTYPE_REASSOC_REQ:
5117 *Machine = ASSOC_STATE_MACHINE;
5118 *MsgType = MT2_PEER_REASSOC_REQ;
5119 break;
5120 case SUBTYPE_REASSOC_RSP:
5121 *Machine = ASSOC_STATE_MACHINE;
5122 *MsgType = MT2_PEER_REASSOC_RSP;
5123 break;
5124 case SUBTYPE_PROBE_REQ:
5125 *Machine = SYNC_STATE_MACHINE;
5126 *MsgType = MT2_PEER_PROBE_REQ;
5127 break;
5128 case SUBTYPE_PROBE_RSP:
5129 *Machine = SYNC_STATE_MACHINE;
5130 *MsgType = MT2_PEER_PROBE_RSP;
5131 break;
5132 case SUBTYPE_BEACON:
5133 *Machine = SYNC_STATE_MACHINE;
5134 *MsgType = MT2_PEER_BEACON;
5135 break;
5136 case SUBTYPE_ATIM:
5137 *Machine = SYNC_STATE_MACHINE;
5138 *MsgType = MT2_PEER_ATIM;
5139 break;
5140 case SUBTYPE_DISASSOC:
5141 *Machine = ASSOC_STATE_MACHINE;
5142 *MsgType = MT2_PEER_DISASSOC_REQ;
5143 break;
5144 case SUBTYPE_AUTH:
5145 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5146 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5147 if (Seq == 1 || Seq == 3)
5148 {
5149 *Machine = AUTH_RSP_STATE_MACHINE;
5150 *MsgType = MT2_PEER_AUTH_ODD;
5151 }
5152 else if (Seq == 2 || Seq == 4)
5153 {
5154 *Machine = AUTH_STATE_MACHINE;
5155 *MsgType = MT2_PEER_AUTH_EVEN;
5156 }
5157 else
5158 {
5159 return FALSE;
5160 }
5161 break;
5162 case SUBTYPE_DEAUTH:
5163 *Machine = AUTH_RSP_STATE_MACHINE;
5164 *MsgType = MT2_PEER_DEAUTH;
5165 break;
5166 case SUBTYPE_ACTION:
5167 *Machine = ACTION_STATE_MACHINE;
5168 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5169 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5170 {
5171 *MsgType = MT2_ACT_INVALID;
5172 }
5173 else
5174 {
5175 *MsgType = (pFrame->Octet[0]&0x7F);
5176 }
5177 break;
5178 default:
5179 return FALSE;
5180 break;
5181 }
5182
5183 return TRUE;
5184}
5185#endif // CONFIG_STA_SUPPORT //
5186
5187// ===========================================================================================
5188// state_machine.c
5189// ===========================================================================================
5190
5191/*! \brief Initialize the state machine.
5192 * \param *S pointer to the state machine
5193 * \param Trans State machine transition function
5194 * \param StNr number of states
5195 * \param MsgNr number of messages
5196 * \param DefFunc default function, when there is invalid state/message combination
5197 * \param InitState initial state of the state machine
5198 * \param Base StateMachine base, internal use only
5199 * \pre p_sm should be a legal pointer
5200 * \post
5201
5202 IRQL = PASSIVE_LEVEL
5203
5204 */
5205VOID StateMachineInit(
5206 IN STATE_MACHINE *S,
5207 IN STATE_MACHINE_FUNC Trans[],
5208 IN ULONG StNr,
5209 IN ULONG MsgNr,
5210 IN STATE_MACHINE_FUNC DefFunc,
5211 IN ULONG InitState,
5212 IN ULONG Base)
5213{
5214 ULONG i, j;
5215
5216 // set number of states and messages
5217 S->NrState = StNr;
5218 S->NrMsg = MsgNr;
5219 S->Base = Base;
5220
5221 S->TransFunc = Trans;
5222
5223 // init all state transition to default function
5224 for (i = 0; i < StNr; i++)
5225 {
5226 for (j = 0; j < MsgNr; j++)
5227 {
5228 S->TransFunc[i * MsgNr + j] = DefFunc;
5229 }
5230 }
5231
5232 // set the starting state
5233 S->CurrState = InitState;
5234}
5235
5236/*! \brief This function fills in the function pointer into the cell in the state machine
5237 * \param *S pointer to the state machine
5238 * \param St state
5239 * \param Msg incoming message
5240 * \param f the function to be executed when (state, message) combination occurs at the state machine
5241 * \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
5242 * \post
5243
5244 IRQL = PASSIVE_LEVEL
5245
5246 */
5247VOID StateMachineSetAction(
5248 IN STATE_MACHINE *S,
5249 IN ULONG St,
5250 IN ULONG Msg,
5251 IN STATE_MACHINE_FUNC Func)
5252{
5253 ULONG MsgIdx;
5254
5255 MsgIdx = Msg - S->Base;
5256
5257 if (St < S->NrState && MsgIdx < S->NrMsg)
5258 {
5259 // boundary checking before setting the action
5260 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5261 }
5262}
5263
5264/*! \brief This function does the state transition
5265 * \param *Adapter the NIC adapter pointer
5266 * \param *S the state machine
5267 * \param *Elem the message to be executed
5268 * \return None
5269
5270 IRQL = DISPATCH_LEVEL
5271
5272 */
5273VOID StateMachinePerformAction(
5274 IN PRTMP_ADAPTER pAd,
5275 IN STATE_MACHINE *S,
5276 IN MLME_QUEUE_ELEM *Elem)
5277{
5278 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5279}
5280
5281/*
5282 ==========================================================================
5283 Description:
5284 The drop function, when machine executes this, the message is simply
5285 ignored. This function does nothing, the message is freed in
5286 StateMachinePerformAction()
5287 ==========================================================================
5288 */
5289VOID Drop(
5290 IN PRTMP_ADAPTER pAd,
5291 IN MLME_QUEUE_ELEM *Elem)
5292{
5293}
5294
5295// ===========================================================================================
5296// lfsr.c
5297// ===========================================================================================
5298
5299/*
5300 ==========================================================================
5301 Description:
5302
5303 IRQL = PASSIVE_LEVEL
5304
5305 ==========================================================================
5306 */
5307VOID LfsrInit(
5308 IN PRTMP_ADAPTER pAd,
5309 IN ULONG Seed)
5310{
5311 if (Seed == 0)
5312 pAd->Mlme.ShiftReg = 1;
5313 else
5314 pAd->Mlme.ShiftReg = Seed;
5315}
5316
5317/*
5318 ==========================================================================
5319 Description:
5320 ==========================================================================
5321 */
5322UCHAR RandomByte(
5323 IN PRTMP_ADAPTER pAd)
5324{
5325 ULONG i;
5326 UCHAR R, Result;
5327
5328 R = 0;
5329
5330 if (pAd->Mlme.ShiftReg == 0)
5331 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5332
5333 for (i = 0; i < 8; i++)
5334 {
5335 if (pAd->Mlme.ShiftReg & 0x00000001)
5336 {
5337 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5338 Result = 1;
5339 }
5340 else
5341 {
5342 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5343 Result = 0;
5344 }
5345 R = (R << 1) | Result;
5346 }
5347
5348 return R;
5349}
5350
5351VOID AsicUpdateAutoFallBackTable(
5352 IN PRTMP_ADAPTER pAd,
5353 IN PUCHAR pRateTable)
5354{
5355 UCHAR i;
5356 HT_FBK_CFG0_STRUC HtCfg0;
5357 HT_FBK_CFG1_STRUC HtCfg1;
5358 LG_FBK_CFG0_STRUC LgCfg0;
5359 LG_FBK_CFG1_STRUC LgCfg1;
5360 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5361
5362 // set to initial value
5363 HtCfg0.word = 0x65432100;
5364 HtCfg1.word = 0xedcba988;
5365 LgCfg0.word = 0xedcba988;
5366 LgCfg1.word = 0x00002100;
5367
5368 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5369 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5370 {
5371 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5372 switch (pCurrTxRate->Mode)
5373 {
5374 case 0: //CCK
5375 break;
5376 case 1: //OFDM
5377 {
5378 switch(pCurrTxRate->CurrMCS)
5379 {
5380 case 0:
5381 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5382 break;
5383 case 1:
5384 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5385 break;
5386 case 2:
5387 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5388 break;
5389 case 3:
5390 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5391 break;
5392 case 4:
5393 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5394 break;
5395 case 5:
5396 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5397 break;
5398 case 6:
5399 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5400 break;
5401 case 7:
5402 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5403 break;
5404 }
5405 }
5406 break;
5407#ifdef DOT11_N_SUPPORT
5408 case 2: //HT-MIX
5409 case 3: //HT-GF
5410 {
5411 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5412 {
5413 switch(pCurrTxRate->CurrMCS)
5414 {
5415 case 0:
5416 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5417 break;
5418 case 1:
5419 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5420 break;
5421 case 2:
5422 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5423 break;
5424 case 3:
5425 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5426 break;
5427 case 4:
5428 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5429 break;
5430 case 5:
5431 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5432 break;
5433 case 6:
5434 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5435 break;
5436 case 7:
5437 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5438 break;
5439 case 8:
5440 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5441 break;
5442 case 9:
5443 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5444 break;
5445 case 10:
5446 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5447 break;
5448 case 11:
5449 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5450 break;
5451 case 12:
5452 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5453 break;
5454 case 13:
5455 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5456 break;
5457 case 14:
5458 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5459 break;
5460 case 15:
5461 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5462 break;
5463 default:
5464 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5465 }
5466 }
5467 }
5468 break;
5469#endif // DOT11_N_SUPPORT //
5470 }
5471
5472 pNextTxRate = pCurrTxRate;
5473 }
5474
5475 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5476 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5477 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5478 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5479}
5480
5481/*
5482 ========================================================================
5483
5484 Routine Description:
5485 Set MAC register value according operation mode.
5486 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5487 If MM or GF mask is not set, those passing argument doesn't not take effect.
5488
5489 Operation mode meaning:
5490 = 0 : Pure HT, no preotection.
5491 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5492 = 0x10: No Transmission in 40M is protected.
5493 = 0x11: Transmission in both 40M and 20M shall be protected
5494 if (bNonGFExist)
5495 we should choose not to use GF. But still set correct ASIC registers.
5496 ========================================================================
5497*/
5498VOID AsicUpdateProtect(
5499 IN PRTMP_ADAPTER pAd,
5500 IN USHORT OperationMode,
5501 IN UCHAR SetMask,
5502 IN BOOLEAN bDisableBGProtect,
5503 IN BOOLEAN bNonGFExist)
5504{
5505 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5506 UINT32 Protect[6];
5507 USHORT offset;
5508 UCHAR i;
5509 UINT32 MacReg = 0;
5510
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005511#ifdef DOT11_N_SUPPORT
5512 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5513 {
5514 return;
5515 }
5516
5517 if (pAd->BATable.numAsOriginator)
5518 {
5519 //
5520 // enable the RTS/CTS to avoid channel collision
5521 //
5522 SetMask = ALLN_SETPROTECT;
5523 OperationMode = 8;
5524 }
5525#endif // DOT11_N_SUPPORT //
5526
5527 // Config ASIC RTS threshold register
5528 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5529 MacReg &= 0xFF0000FF;
5530#if 0
5531 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5532#else
Thadeu Lima de Souza Cascardo4b512d22009-04-14 23:14:10 -03005533 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005534 if ((
5535#ifdef DOT11_N_SUPPORT
5536 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5537#endif // DOT11_N_SUPPORT //
5538 (pAd->CommonCfg.bAggregationCapable == TRUE))
5539 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5540 {
5541 MacReg |= (0x1000 << 8);
5542 }
5543 else
5544 {
5545 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5546 }
5547#endif
5548
5549 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5550
5551 // Initial common protection settings
5552 RTMPZeroMemory(Protect, sizeof(Protect));
5553 ProtCfg4.word = 0;
5554 ProtCfg.word = 0;
5555 ProtCfg.field.TxopAllowGF40 = 1;
5556 ProtCfg.field.TxopAllowGF20 = 1;
5557 ProtCfg.field.TxopAllowMM40 = 1;
5558 ProtCfg.field.TxopAllowMM20 = 1;
5559 ProtCfg.field.TxopAllowOfdm = 1;
5560 ProtCfg.field.TxopAllowCck = 1;
5561 ProtCfg.field.RTSThEn = 1;
5562 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5563
5564 // update PHY mode and rate
5565 if (pAd->CommonCfg.Channel > 14)
5566 ProtCfg.field.ProtectRate = 0x4000;
5567 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5568
5569 // Handle legacy(B/G) protection
5570 if (bDisableBGProtect)
5571 {
5572 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5573 ProtCfg.field.ProtectCtrl = 0;
5574 Protect[0] = ProtCfg.word;
5575 Protect[1] = ProtCfg.word;
5576 }
5577 else
5578 {
5579 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5580 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5581 Protect[0] = ProtCfg.word;
5582 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5583 Protect[1] = ProtCfg.word;
5584 }
5585
5586#ifdef DOT11_N_SUPPORT
5587 // Decide HT frame protection.
5588 if ((SetMask & ALLN_SETPROTECT) != 0)
5589 {
5590 switch(OperationMode)
5591 {
5592 case 0x0:
5593 // NO PROTECT
5594 // 1.All STAs in the BSS are 20/40 MHz HT
5595 // 2. in ai 20/40MHz BSS
5596 // 3. all STAs are 20MHz in a 20MHz BSS
5597 // Pure HT. no protection.
5598
5599 // MM20_PROT_CFG
5600 // Reserved (31:27)
5601 // PROT_TXOP(25:20) -- 010111
5602 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5603 // PROT_CTRL(17:16) -- 00 (None)
5604 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5605 Protect[2] = 0x01744004;
5606
5607 // MM40_PROT_CFG
5608 // Reserved (31:27)
5609 // PROT_TXOP(25:20) -- 111111
5610 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5611 // PROT_CTRL(17:16) -- 00 (None)
5612 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5613 Protect[3] = 0x03f44084;
5614
5615 // CF20_PROT_CFG
5616 // Reserved (31:27)
5617 // PROT_TXOP(25:20) -- 010111
5618 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5619 // PROT_CTRL(17:16) -- 00 (None)
5620 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5621 Protect[4] = 0x01744004;
5622
5623 // CF40_PROT_CFG
5624 // Reserved (31:27)
5625 // PROT_TXOP(25:20) -- 111111
5626 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5627 // PROT_CTRL(17:16) -- 00 (None)
5628 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5629 Protect[5] = 0x03f44084;
5630
5631 if (bNonGFExist)
5632 {
5633 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5634 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5635 Protect[4] = 0x01754004;
5636 Protect[5] = 0x03f54084;
5637 }
5638 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5639 break;
5640
5641 case 1:
5642 // This is "HT non-member protection mode."
5643 // If there may be non-HT STAs my BSS
5644 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5645 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5646 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5647 {
5648 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5649 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5650 }
5651 //Assign Protection method for 20&40 MHz packets
5652 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5653 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5654 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5655 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5656 Protect[2] = ProtCfg.word;
5657 Protect[3] = ProtCfg4.word;
5658 Protect[4] = ProtCfg.word;
5659 Protect[5] = ProtCfg4.word;
5660 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5661 break;
5662
5663 case 2:
5664 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5665 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5666 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5667
5668 //Assign Protection method for 40MHz packets
5669 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5670 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5671 Protect[2] = ProtCfg.word;
5672 Protect[3] = ProtCfg4.word;
5673 if (bNonGFExist)
5674 {
5675 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5676 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5677 }
5678 Protect[4] = ProtCfg.word;
5679 Protect[5] = ProtCfg4.word;
5680
5681 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5682 break;
5683
5684 case 3:
5685 // HT mixed mode. PROTECT ALL!
5686 // Assign Rate
5687 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5688 ProtCfg4.word = 0x03f44084;
5689 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5690 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5691 {
5692 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5693 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5694 }
5695 //Assign Protection method for 20&40 MHz packets
5696 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5697 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5698 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5699 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5700 Protect[2] = ProtCfg.word;
5701 Protect[3] = ProtCfg4.word;
5702 Protect[4] = ProtCfg.word;
5703 Protect[5] = ProtCfg4.word;
5704 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5705 break;
5706
5707 case 8:
5708 // Special on for Atheros problem n chip.
5709 Protect[2] = 0x01754004;
5710 Protect[3] = 0x03f54084;
5711 Protect[4] = 0x01754004;
5712 Protect[5] = 0x03f54084;
5713 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5714 break;
5715 }
5716 }
5717#endif // DOT11_N_SUPPORT //
5718
5719 offset = CCK_PROT_CFG;
5720 for (i = 0;i < 6;i++)
5721 {
5722 if ((SetMask & (1<< i)))
5723 {
5724 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5725 }
5726 }
5727}
5728
5729/*
5730 ==========================================================================
5731 Description:
5732
5733 IRQL = PASSIVE_LEVEL
5734 IRQL = DISPATCH_LEVEL
5735
5736 ==========================================================================
5737 */
5738VOID AsicSwitchChannel(
5739 IN PRTMP_ADAPTER pAd,
5740 IN UCHAR Channel,
5741 IN BOOLEAN bScan)
5742{
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;
5748
5749 // Search Tx power value
5750 for (index = 0; index < pAd->ChannelListNum; index++)
5751 {
5752 if (Channel == pAd->ChannelList[index].Channel)
5753 {
5754 TxPwer = pAd->ChannelList[index].Power;
5755 TxPwer2 = pAd->ChannelList[index].Power2;
5756 break;
5757 }
5758 }
5759
5760 if (index == MAX_NUM_OF_CHANNELS)
5761 {
5762 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5763 }
5764
5765 {
5766 RFRegTable = RF2850RegTable;
5767
5768 switch (pAd->RfIcType)
5769 {
5770 case RFIC_2820:
5771 case RFIC_2850:
5772 case RFIC_2720:
5773 case RFIC_2750:
5774
5775 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5776 {
5777 if (Channel == RFRegTable[index].Channel)
5778 {
5779 R2 = RFRegTable[index].R2;
5780 if (pAd->Antenna.field.TxPath == 1)
5781 {
5782 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5783 }
5784
5785 if (pAd->Antenna.field.RxPath == 2)
5786 {
5787 R2 |= 0x40; // write 1 to off Rxpath.
5788 }
5789 else if (pAd->Antenna.field.RxPath == 1)
5790 {
5791 R2 |= 0x20040; // write 1 to off RxPath
5792 }
5793
5794 if (Channel > 14)
5795 {
5796 // initialize R3, R4
5797 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5798 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5799
5800 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5801 // R3
5802 if ((TxPwer >= -7) && (TxPwer < 0))
5803 {
5804 TxPwer = (7+TxPwer);
5805 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5806 R3 |= (TxPwer << 10);
5807 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5808 }
5809 else
5810 {
5811 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5812 R3 |= (TxPwer << 10) | (1 << 9);
5813 }
5814
5815 // R4
5816 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5817 {
5818 TxPwer2 = (7+TxPwer2);
5819 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5820 R4 |= (TxPwer2 << 7);
5821 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5822 }
5823 else
5824 {
5825 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5826 R4 |= (TxPwer2 << 7) | (1 << 6);
5827 }
5828 }
5829 else
5830 {
5831 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5832 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5833 }
5834
5835 // Based on BBP current mode before changing RF channel.
5836 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5837 {
5838 R4 |=0x200000;
5839 }
5840
5841 // Update variables
5842 pAd->LatchRfRegs.Channel = Channel;
5843 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5844 pAd->LatchRfRegs.R2 = R2;
5845 pAd->LatchRfRegs.R3 = R3;
5846 pAd->LatchRfRegs.R4 = R4;
5847
5848 // Set RF value 1's set R3[bit2] = [0]
5849 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5850 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5851 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5852 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5853
5854 RTMPusecDelay(200);
5855
5856 // Set RF value 2's set R3[bit2] = [1]
5857 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5858 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5859 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5860 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5861
5862 RTMPusecDelay(200);
5863
5864 // Set RF value 3's set R3[bit2] = [0]
5865 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5866 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5867 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5868 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5869
5870 break;
5871 }
5872 }
5873 break;
5874
5875 default:
5876 break;
5877 }
5878 }
5879
5880 // Change BBP setting during siwtch from a->g, g->a
5881 if (Channel <= 14)
5882 {
5883 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5884
5885 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5886 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5887 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5888 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.
5889 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5890
5891 // Rx High power VGA offset for LNA select
5892 if (pAd->NicConfig2.field.ExternalLNAForG)
5893 {
5894 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5895 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5896 }
5897 else
5898 {
5899 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5900 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5901 }
5902
5903 // 5G band selection PIN, bit1 and bit2 are complement
5904 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5905 Value &= (~0x6);
5906 Value |= (0x04);
5907 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5908
5909 // Turn off unused PA or LNA when only 1T or 1R
5910 if (pAd->Antenna.field.TxPath == 1)
5911 {
5912 TxPinCfg &= 0xFFFFFFF3;
5913 }
5914 if (pAd->Antenna.field.RxPath == 1)
5915 {
5916 TxPinCfg &= 0xFFFFF3FF;
5917 }
5918
5919 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5920 }
5921 else
5922 {
5923 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5924
5925 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5926 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5927 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5928 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.
5929 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5930
5931 // Rx High power VGA offset for LNA select
5932 if (pAd->NicConfig2.field.ExternalLNAForA)
5933 {
5934 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5935 }
5936 else
5937 {
5938 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5939 }
5940
5941 // 5G band selection PIN, bit1 and bit2 are complement
5942 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5943 Value &= (~0x6);
5944 Value |= (0x02);
5945 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5946
5947 // Turn off unused PA or LNA when only 1T or 1R
5948 if (pAd->Antenna.field.TxPath == 1)
5949 {
5950 TxPinCfg &= 0xFFFFFFF3;
5951 }
5952 if (pAd->Antenna.field.RxPath == 1)
5953 {
5954 TxPinCfg &= 0xFFFFF3FF;
5955 }
5956
5957 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5958 }
5959
5960 // R66 should be set according to Channel and use 20MHz when scanning
5961 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5962 if (bScan)
5963 RTMPSetAGCInitValue(pAd, BW_20);
5964 else
5965 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5966
5967 //
5968 // On 11A, We should delay and wait RF/BBP to be stable
5969 // and the appropriate time should be 1000 micro seconds
5970 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5971 //
5972 RTMPusecDelay(1000);
5973
5974 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",
5975 Channel,
5976 pAd->RfIcType,
5977 (R3 & 0x00003e00) >> 9,
5978 (R4 & 0x000007c0) >> 6,
5979 pAd->Antenna.field.TxPath,
5980 pAd->LatchRfRegs.R1,
5981 pAd->LatchRfRegs.R2,
5982 pAd->LatchRfRegs.R3,
5983 pAd->LatchRfRegs.R4));
5984}
5985
5986/*
5987 ==========================================================================
5988 Description:
5989 This function is required for 2421 only, and should not be used during
5990 site survey. It's only required after NIC decided to stay at a channel
5991 for a longer period.
5992 When this function is called, it's always after AsicSwitchChannel().
5993
5994 IRQL = PASSIVE_LEVEL
5995 IRQL = DISPATCH_LEVEL
5996
5997 ==========================================================================
5998 */
5999VOID AsicLockChannel(
6000 IN PRTMP_ADAPTER pAd,
6001 IN UCHAR Channel)
6002{
6003}
6004
6005/*
6006 ==========================================================================
6007 Description:
6008
6009 IRQL = PASSIVE_LEVEL
6010 IRQL = DISPATCH_LEVEL
6011
6012 ==========================================================================
6013 */
6014VOID AsicAntennaSelect(
6015 IN PRTMP_ADAPTER pAd,
6016 IN UCHAR Channel)
6017{
6018}
6019
6020/*
6021 ========================================================================
6022
6023 Routine Description:
6024 Antenna miscellaneous setting.
6025
6026 Arguments:
6027 pAd Pointer to our adapter
6028 BandState Indicate current Band State.
6029
6030 Return Value:
6031 None
6032
6033 IRQL <= DISPATCH_LEVEL
6034
6035 Note:
6036 1.) Frame End type control
6037 only valid for G only (RF_2527 & RF_2529)
6038 0: means DPDT, set BBP R4 bit 5 to 1
6039 1: means SPDT, set BBP R4 bit 5 to 0
6040
6041
6042 ========================================================================
6043*/
6044VOID AsicAntennaSetting(
6045 IN PRTMP_ADAPTER pAd,
6046 IN ABGBAND_STATE BandState)
6047{
6048}
6049
6050VOID AsicRfTuningExec(
6051 IN PVOID SystemSpecific1,
6052 IN PVOID FunctionContext,
6053 IN PVOID SystemSpecific2,
6054 IN PVOID SystemSpecific3)
6055{
6056}
6057
6058/*
6059 ==========================================================================
6060 Description:
6061 Gives CCK TX rate 2 more dB TX power.
6062 This routine works only in LINK UP in INFRASTRUCTURE mode.
6063
6064 calculate desired Tx power in RF R3.Tx0~5, should consider -
6065 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6066 1. TxPowerPercentage
6067 2. auto calibration based on TSSI feedback
6068 3. extra 2 db for CCK
6069 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6070
6071 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6072 it should be called AFTER MlmeDynamicTxRatSwitching()
6073 ==========================================================================
6074 */
6075VOID AsicAdjustTxPower(
6076 IN PRTMP_ADAPTER pAd)
6077{
6078 INT i, j;
6079 CHAR DeltaPwr = 0;
6080 BOOLEAN bAutoTxAgc = FALSE;
6081 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6082 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6083 PCHAR pTxAgcCompensate;
6084 ULONG TxPwr[5];
6085 CHAR Value;
6086
Adam McDanieled291e82009-02-23 08:01:07 -07006087 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6088 || (pAd->bPCIclkOff == TRUE)
6089 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6090 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6091 return;
6092
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006093 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6094 {
6095 if (pAd->CommonCfg.CentralChannel > 14)
6096 {
6097 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6098 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6099 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6100 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6101 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6102 }
6103 else
6104 {
6105 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6106 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6107 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6108 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6109 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6110 }
6111 }
6112 else
6113 {
6114 if (pAd->CommonCfg.Channel > 14)
6115 {
6116 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6117 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6118 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6119 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6120 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6121 }
6122 else
6123 {
6124 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6125 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6126 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6127 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6128 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6129 }
6130 }
6131
6132 // TX power compensation for temperature variation based on TSSI. try every 4 second
6133 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6134 {
6135 if (pAd->CommonCfg.Channel <= 14)
6136 {
6137 /* bg channel */
6138 bAutoTxAgc = pAd->bAutoTxAgcG;
6139 TssiRef = pAd->TssiRefG;
6140 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6141 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6142 TxAgcStep = pAd->TxAgcStepG;
6143 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6144 }
6145 else
6146 {
6147 /* a channel */
6148 bAutoTxAgc = pAd->bAutoTxAgcA;
6149 TssiRef = pAd->TssiRefA;
6150 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6151 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6152 TxAgcStep = pAd->TxAgcStepA;
6153 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6154 }
6155
6156 if (bAutoTxAgc)
6157 {
6158 /* BbpR1 is unsigned char */
6159 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6160
6161 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6162 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6163 /* step value is defined in pAd->TxAgcStepG for tx power value */
6164
6165 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6166 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6167 above value are examined in mass factory production */
6168 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6169
6170 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6171 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6172 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6173
6174 if (BbpR49 > pTssiMinusBoundary[1])
6175 {
6176 // Reading is larger than the reference value
6177 // check for how large we need to decrease the Tx power
6178 for (idx = 1; idx < 5; idx++)
6179 {
6180 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6181 break;
6182 }
6183 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6184 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6185
6186 DeltaPwr += (*pTxAgcCompensate);
6187 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6188 BbpR49, TssiRef, TxAgcStep, idx-1));
6189 }
6190 else if (BbpR49 < pTssiPlusBoundary[1])
6191 {
6192 // Reading is smaller than the reference value
6193 // check for how large we need to increase the Tx power
6194 for (idx = 1; idx < 5; idx++)
6195 {
6196 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6197 break;
6198 }
6199 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6200 *pTxAgcCompensate = TxAgcStep * (idx-1);
6201 DeltaPwr += (*pTxAgcCompensate);
6202 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6203 BbpR49, TssiRef, TxAgcStep, idx-1));
6204 }
6205 else
6206 {
6207 *pTxAgcCompensate = 0;
6208 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6209 BbpR49, TssiRef, TxAgcStep, 0));
6210 }
6211 }
6212 }
6213 else
6214 {
6215 if (pAd->CommonCfg.Channel <= 14)
6216 {
6217 bAutoTxAgc = pAd->bAutoTxAgcG;
6218 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6219 }
6220 else
6221 {
6222 bAutoTxAgc = pAd->bAutoTxAgcA;
6223 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6224 }
6225
6226 if (bAutoTxAgc)
6227 DeltaPwr += (*pTxAgcCompensate);
6228 }
6229
6230 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6231 BbpR1 &= 0xFC;
6232
6233#ifdef SINGLE_SKU
6234 // Handle regulatory max tx power constrain
6235 do
6236 {
6237 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6238 UCHAR AdjustMaxTxPwr[40];
6239
6240 if (pAd->CommonCfg.Channel > 14) // 5G band
6241 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6242 else // 2.4G band
6243 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6244 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6245
6246 // error handling, range check
6247 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6248 {
6249 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6250 break;
6251 }
6252
6253 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6254
6255 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6256
6257 // Adjust max tx power according to the relationship of tx power in E2PROM
6258 for (i=0; i<5; i++)
6259 {
6260 // CCK will have 4dBm larger than OFDM
6261 // Therefore, we should separate to parse the tx power field
6262 if (i == 0)
6263 {
6264 for (j=0; j<8; j++)
6265 {
6266 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6267
6268 if (j < 4)
6269 {
6270 // CCK will have 4dBm larger than OFDM
6271 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6272 }
6273 else
6274 {
6275 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6276 }
6277 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6278 }
6279 }
6280 else
6281 {
6282 for (j=0; j<8; j++)
6283 {
6284 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6285
6286 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6287 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6288 }
6289 }
6290 }
6291
6292 // Adjust tx power according to the relationship
6293 for (i=0; i<5; i++)
6294 {
6295 if (TxPwr[i] != 0xffffffff)
6296 {
6297 for (j=0; j<8; j++)
6298 {
6299 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6300
6301 // The system tx power is larger than the regulatory, the power should be restrain
6302 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6303 {
6304 // decrease to zero and don't need to take care BBPR1
6305 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6306 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6307 else
6308 Value = 0;
6309
6310 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6311 }
6312 else
6313 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6314
6315 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6316 }
6317 }
6318 }
6319 } while (FALSE);
6320#endif // SINGLE_SKU //
6321
6322 /* calculate delta power based on the percentage specified from UI */
6323 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6324 // We lower TX power here according to the percentage specified from UI
6325 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6326 ;
6327 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6328 ;
6329 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6330 {
6331 DeltaPwr -= 1;
6332 }
6333 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6334 {
6335 DeltaPwr -= 3;
6336 }
6337 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6338 {
6339 BbpR1 |= 0x01;
6340 }
6341 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6342 {
6343 BbpR1 |= 0x01;
6344 DeltaPwr -= 3;
6345 }
6346 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6347 {
6348 BbpR1 |= 0x02;
6349 }
6350
6351 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6352
6353 /* reset different new tx power for different TX rate */
6354 for(i=0; i<5; i++)
6355 {
6356 if (TxPwr[i] != 0xffffffff)
6357 {
6358 for (j=0; j<8; j++)
6359 {
6360 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6361
6362 if ((Value + DeltaPwr) < 0)
6363 {
6364 Value = 0; /* min */
6365 }
6366 else if ((Value + DeltaPwr) > 0xF)
6367 {
6368 Value = 0xF; /* max */
6369 }
6370 else
6371 {
6372 Value += DeltaPwr; /* temperature compensation */
6373 }
6374
6375 /* fill new value to CSR offset */
6376 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6377 }
6378
6379 /* write tx power value to CSR */
6380 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6381 TX power for OFDM 6M/9M
6382 TX power for CCK5.5M/11M
6383 TX power for CCK1M/2M */
6384 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6385 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6386 }
6387 }
6388
6389}
6390
6391#ifdef CONFIG_STA_SUPPORT
6392/*
6393 ==========================================================================
6394 Description:
6395 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6396 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6397 the wakeup timer timeout. Driver has to issue a separate command to wake
6398 PHY up.
6399
6400 IRQL = DISPATCH_LEVEL
6401
6402 ==========================================================================
6403 */
6404VOID AsicSleepThenAutoWakeup(
6405 IN PRTMP_ADAPTER pAd,
6406 IN USHORT TbttNumToNextWakeUp)
6407{
6408 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6409}
6410
6411/*
6412 ==========================================================================
6413 Description:
6414 AsicForceWakeup() is used whenever manual wakeup is required
6415 AsicForceSleep() should only be used when not in INFRA BSS. When
6416 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6417 ==========================================================================
6418 */
6419VOID AsicForceSleep(
6420 IN PRTMP_ADAPTER pAd)
6421{
6422
6423}
6424
6425/*
6426 ==========================================================================
6427 Description:
6428 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6429 expired.
6430
6431 IRQL = PASSIVE_LEVEL
6432 IRQL = DISPATCH_LEVEL
6433 ==========================================================================
6434 */
6435VOID AsicForceWakeup(
6436 IN PRTMP_ADAPTER pAd,
Adam McDanieled291e82009-02-23 08:01:07 -07006437 IN UCHAR Level)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006438{
6439 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
Adam McDanieled291e82009-02-23 08:01:07 -07006440 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006441}
6442#endif // CONFIG_STA_SUPPORT //
6443/*
6444 ==========================================================================
6445 Description:
6446 Set My BSSID
6447
6448 IRQL = DISPATCH_LEVEL
6449
6450 ==========================================================================
6451 */
6452VOID AsicSetBssid(
6453 IN PRTMP_ADAPTER pAd,
6454 IN PUCHAR pBssid)
6455{
6456 ULONG Addr4;
6457 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6458 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6459
6460 Addr4 = (ULONG)(pBssid[0]) |
6461 (ULONG)(pBssid[1] << 8) |
6462 (ULONG)(pBssid[2] << 16) |
6463 (ULONG)(pBssid[3] << 24);
6464 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6465
6466 Addr4 = 0;
6467 // always one BSSID in STA mode
6468 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6469
6470 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6471}
6472
6473VOID AsicSetMcastWC(
6474 IN PRTMP_ADAPTER pAd)
6475{
6476 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6477 USHORT offset;
6478
6479 pEntry->Sst = SST_ASSOC;
6480 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6481 pEntry->PsMode = PWR_ACTIVE;
6482 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6483 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6484}
6485
6486/*
6487 ==========================================================================
6488 Description:
6489
6490 IRQL = DISPATCH_LEVEL
6491
6492 ==========================================================================
6493 */
6494VOID AsicDelWcidTab(
6495 IN PRTMP_ADAPTER pAd,
6496 IN UCHAR Wcid)
6497{
6498 ULONG Addr0 = 0x0, Addr1 = 0x0;
6499 ULONG offset;
6500
6501 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6502 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6503 RTMP_IO_WRITE32(pAd, offset, Addr0);
6504 offset += 4;
6505 RTMP_IO_WRITE32(pAd, offset, Addr1);
6506}
6507
6508/*
6509 ==========================================================================
6510 Description:
6511
6512 IRQL = DISPATCH_LEVEL
6513
6514 ==========================================================================
6515 */
6516VOID AsicEnableRDG(
6517 IN PRTMP_ADAPTER pAd)
6518{
6519 TX_LINK_CFG_STRUC TxLinkCfg;
6520 UINT32 Data = 0;
6521
6522 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6523 TxLinkCfg.field.TxRDGEn = 1;
6524 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6525
6526 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6527 Data &= 0xFFFFFF00;
6528 Data |= 0x80;
6529 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6530
6531 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6532}
6533
6534/*
6535 ==========================================================================
6536 Description:
6537
6538 IRQL = DISPATCH_LEVEL
6539
6540 ==========================================================================
6541 */
6542VOID AsicDisableRDG(
6543 IN PRTMP_ADAPTER pAd)
6544{
6545 TX_LINK_CFG_STRUC TxLinkCfg;
6546 UINT32 Data = 0;
6547
6548
6549 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6550 TxLinkCfg.field.TxRDGEn = 0;
6551 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6552
6553 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6554
6555 Data &= 0xFFFFFF00;
6556 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6557#ifdef DOT11_N_SUPPORT
6558 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6559#endif // DOT11_N_SUPPORT //
6560 )
6561 {
6562 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6563 if (pAd->CommonCfg.bEnableTxBurst)
6564 Data |= 0x20;
6565 }
6566 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6567}
6568
6569/*
6570 ==========================================================================
6571 Description:
6572
6573 IRQL = PASSIVE_LEVEL
6574 IRQL = DISPATCH_LEVEL
6575
6576 ==========================================================================
6577 */
6578VOID AsicDisableSync(
6579 IN PRTMP_ADAPTER pAd)
6580{
6581 BCN_TIME_CFG_STRUC csr;
6582
6583 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6584
6585 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6586 // that NIC will never wakes up because TSF stops and no more
6587 // TBTT interrupts
6588 pAd->TbttTickCount = 0;
6589 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6590 csr.field.bBeaconGen = 0;
6591 csr.field.bTBTTEnable = 0;
6592 csr.field.TsfSyncMode = 0;
6593 csr.field.bTsfTicking = 0;
6594 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6595
6596}
6597
6598/*
6599 ==========================================================================
6600 Description:
6601
6602 IRQL = DISPATCH_LEVEL
6603
6604 ==========================================================================
6605 */
6606VOID AsicEnableBssSync(
6607 IN PRTMP_ADAPTER pAd)
6608{
6609 BCN_TIME_CFG_STRUC csr;
6610
6611 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6612
6613 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6614#ifdef CONFIG_STA_SUPPORT
6615 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6616 {
6617 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6618 csr.field.bTsfTicking = 1;
6619 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6620 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6621 csr.field.bTBTTEnable = 1;
6622 }
6623#endif // CONFIG_STA_SUPPORT //
6624 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6625}
6626
6627/*
6628 ==========================================================================
6629 Description:
6630 Note:
6631 BEACON frame in shared memory should be built ok before this routine
6632 can be called. Otherwise, a garbage frame maybe transmitted out every
6633 Beacon period.
6634
6635 IRQL = DISPATCH_LEVEL
6636
6637 ==========================================================================
6638 */
6639VOID AsicEnableIbssSync(
6640 IN PRTMP_ADAPTER pAd)
6641{
6642 BCN_TIME_CFG_STRUC csr9;
6643 PUCHAR ptr;
6644 UINT i;
6645
6646 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6647
6648 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6649 csr9.field.bBeaconGen = 0;
6650 csr9.field.bTBTTEnable = 0;
6651 csr9.field.bTsfTicking = 0;
6652 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6653
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006654 // move BEACON TXD and frame content to on-chip memory
6655 ptr = (PUCHAR)&pAd->BeaconTxWI;
6656 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6657 {
6658 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6659 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6660 ptr += 4;
6661 }
6662
6663 // start right after the 16-byte TXWI field
6664 ptr = pAd->BeaconBuf;
6665 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6666 {
6667 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6668 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6669 ptr +=4;
6670 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006671
6672 // start sending BEACON
6673 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6674 csr9.field.bTsfTicking = 1;
6675 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6676 csr9.field.bTBTTEnable = 1;
6677 csr9.field.bBeaconGen = 1;
6678 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6679}
6680
6681/*
6682 ==========================================================================
6683 Description:
6684
6685 IRQL = PASSIVE_LEVEL
6686 IRQL = DISPATCH_LEVEL
6687
6688 ==========================================================================
6689 */
6690VOID AsicSetEdcaParm(
6691 IN PRTMP_ADAPTER pAd,
6692 IN PEDCA_PARM pEdcaParm)
6693{
6694 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6695 AC_TXOP_CSR0_STRUC csr0;
6696 AC_TXOP_CSR1_STRUC csr1;
6697 AIFSN_CSR_STRUC AifsnCsr;
6698 CWMIN_CSR_STRUC CwminCsr;
6699 CWMAX_CSR_STRUC CwmaxCsr;
6700 int i;
6701
6702 Ac0Cfg.word = 0;
6703 Ac1Cfg.word = 0;
6704 Ac2Cfg.word = 0;
6705 Ac3Cfg.word = 0;
6706 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6707 {
6708 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6709 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6710 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6711 {
6712 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6713 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6714 }
6715
6716 //========================================================
6717 // MAC Register has a copy .
6718 //========================================================
6719 if( pAd->CommonCfg.bEnableTxBurst )
6720 {
6721 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6722 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6723 }
6724 else
6725 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6726 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6727 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6728 Ac0Cfg.field.Aifsn = 2;
6729 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6730
6731 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6732 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6733 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6734 Ac1Cfg.field.Aifsn = 2;
6735 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6736
6737 if (pAd->CommonCfg.PhyMode == PHY_11B)
6738 {
6739 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6740 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6741 }
6742 else
6743 {
6744 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6745 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6746 }
6747 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6748 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6749 Ac2Cfg.field.Aifsn = 2;
6750 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6751 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6752 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6753 Ac3Cfg.field.Aifsn = 2;
6754 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6755
6756 //========================================================
6757 // DMA Register has a copy too.
6758 //========================================================
6759 csr0.field.Ac0Txop = 0; // QID_AC_BE
6760 csr0.field.Ac1Txop = 0; // QID_AC_BK
6761 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6762 if (pAd->CommonCfg.PhyMode == PHY_11B)
6763 {
6764 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6765 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6766 }
6767 else
6768 {
6769 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6770 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6771 }
6772 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6773
6774 CwminCsr.word = 0;
6775 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6776 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6777 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6778 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6779 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6780
6781 CwmaxCsr.word = 0;
6782 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6783 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6784 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6785 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6786 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6787
6788 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6789
6790 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6791 }
6792 else
6793 {
6794 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6795 //========================================================
6796 // MAC Register has a copy.
6797 //========================================================
6798 //
6799 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6800 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6801 //
6802 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6803
6804 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6805 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6806 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6807 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6808
6809 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6810 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6811 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6812 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6813
6814 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6815 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6816 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6817 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6818#ifdef CONFIG_STA_SUPPORT
6819 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6820 {
6821 // Tuning for Wi-Fi WMM S06
6822 if (pAd->CommonCfg.bWiFiTest &&
6823 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6824 Ac2Cfg.field.Aifsn -= 1;
6825
6826 // Tuning for TGn Wi-Fi 5.2.32
6827 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6828 if (STA_TGN_WIFI_ON(pAd) &&
6829 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6830 {
6831 Ac0Cfg.field.Aifsn = 3;
6832 Ac2Cfg.field.AcTxop = 5;
6833 }
6834 }
6835#endif // CONFIG_STA_SUPPORT //
6836
6837 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6838 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6839 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6840 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6841
6842//#ifdef WIFI_TEST
6843 if (pAd->CommonCfg.bWiFiTest)
6844 {
6845 if (Ac3Cfg.field.AcTxop == 102)
6846 {
6847 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6848 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6849 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6850 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6851 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6852 } /* End of if */
6853 }
6854//#endif // WIFI_TEST //
6855
6856 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6857 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6858 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6859 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6860
6861
6862 //========================================================
6863 // DMA Register has a copy too.
6864 //========================================================
6865 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6866 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6867 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6868
6869 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6870 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6871 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6872
6873 CwminCsr.word = 0;
6874 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6875 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6876 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6877#ifdef CONFIG_STA_SUPPORT
6878 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6879 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6880#endif // CONFIG_STA_SUPPORT //
6881 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6882
6883 CwmaxCsr.word = 0;
6884 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6885 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6886 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6887 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6888 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6889
6890 AifsnCsr.word = 0;
6891 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6892 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6893 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6894#ifdef CONFIG_STA_SUPPORT
6895 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6896 {
6897 // Tuning for Wi-Fi WMM S06
6898 if (pAd->CommonCfg.bWiFiTest &&
6899 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6900 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6901
6902 // Tuning for TGn Wi-Fi 5.2.32
6903 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6904 if (STA_TGN_WIFI_ON(pAd) &&
6905 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6906 {
6907 AifsnCsr.field.Aifsn0 = 3;
6908 AifsnCsr.field.Aifsn2 = 7;
6909 }
6910 }
6911#endif // CONFIG_STA_SUPPORT //
6912
6913#ifdef CONFIG_STA_SUPPORT
6914 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6915 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6916#endif // CONFIG_STA_SUPPORT //
6917 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6918
6919 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6920 if (!ADHOC_ON(pAd))
6921 {
6922 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6923 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6924 pEdcaParm->Aifsn[0],
6925 pEdcaParm->Cwmin[0],
6926 pEdcaParm->Cwmax[0],
6927 pEdcaParm->Txop[0]<<5,
6928 pEdcaParm->bACM[0]));
6929 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6930 pEdcaParm->Aifsn[1],
6931 pEdcaParm->Cwmin[1],
6932 pEdcaParm->Cwmax[1],
6933 pEdcaParm->Txop[1]<<5,
6934 pEdcaParm->bACM[1]));
6935 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6936 pEdcaParm->Aifsn[2],
6937 pEdcaParm->Cwmin[2],
6938 pEdcaParm->Cwmax[2],
6939 pEdcaParm->Txop[2]<<5,
6940 pEdcaParm->bACM[2]));
6941 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6942 pEdcaParm->Aifsn[3],
6943 pEdcaParm->Cwmin[3],
6944 pEdcaParm->Cwmax[3],
6945 pEdcaParm->Txop[3]<<5,
6946 pEdcaParm->bACM[3]));
6947 }
6948 }
6949}
6950
6951/*
6952 ==========================================================================
6953 Description:
6954
6955 IRQL = PASSIVE_LEVEL
6956 IRQL = DISPATCH_LEVEL
6957
6958 ==========================================================================
6959 */
6960VOID AsicSetSlotTime(
6961 IN PRTMP_ADAPTER pAd,
6962 IN BOOLEAN bUseShortSlotTime)
6963{
6964 ULONG SlotTime;
6965 UINT32 RegValue = 0;
6966
6967#ifdef CONFIG_STA_SUPPORT
6968 if (pAd->CommonCfg.Channel > 14)
6969 bUseShortSlotTime = TRUE;
6970#endif // CONFIG_STA_SUPPORT //
6971
6972 if (bUseShortSlotTime)
6973 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6974 else
6975 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6976
6977 SlotTime = (bUseShortSlotTime)? 9 : 20;
6978
6979#ifdef CONFIG_STA_SUPPORT
6980 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6981 {
6982 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6983 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6984#ifdef DOT11_N_SUPPORT
6985 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6986#endif // DOT11_N_SUPPORT //
6987 )
6988 {
6989 // In this case, we will think it is doing Wi-Fi test
6990 // And we will not set to short slot when bEnableTxBurst is TRUE.
6991 }
6992 else if (pAd->CommonCfg.bEnableTxBurst)
6993 SlotTime = 9;
6994 }
6995#endif // CONFIG_STA_SUPPORT //
6996
6997 //
6998 // For some reasons, always set it to short slot time.
6999 //
7000 // ToDo: Should consider capability with 11B
7001 //
7002#ifdef CONFIG_STA_SUPPORT
7003 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7004 {
7005 if (pAd->StaCfg.BssType == BSS_ADHOC)
7006 SlotTime = 20;
7007 }
7008#endif // CONFIG_STA_SUPPORT //
7009
7010 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7011 RegValue = RegValue & 0xFFFFFF00;
7012
7013 RegValue |= SlotTime;
7014
7015 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7016}
7017
7018/*
7019 ========================================================================
7020 Description:
7021 Add Shared key information into ASIC.
7022 Update shared key, TxMic and RxMic to Asic Shared key table
7023 Update its cipherAlg to Asic Shared key Mode.
7024
7025 Return:
7026 ========================================================================
7027*/
7028VOID AsicAddSharedKeyEntry(
7029 IN PRTMP_ADAPTER pAd,
7030 IN UCHAR BssIndex,
7031 IN UCHAR KeyIdx,
7032 IN UCHAR CipherAlg,
7033 IN PUCHAR pKey,
7034 IN PUCHAR pTxMic,
7035 IN PUCHAR pRxMic)
7036{
7037 ULONG offset; //, csr0;
7038 SHAREDKEY_MODE_STRUC csr1;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007039 INT i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007040
7041 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7042//============================================================================================
7043
7044 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7045 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7046 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]));
7047 if (pRxMic)
7048 {
7049 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7050 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7051 }
7052 if (pTxMic)
7053 {
7054 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7055 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7056 }
7057//============================================================================================
7058 //
7059 // fill key material - key + TX MIC + RX MIC
7060 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007061 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7062 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7063 {
7064 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7065 }
7066
7067 offset += MAX_LEN_OF_SHARE_KEY;
7068 if (pTxMic)
7069 {
7070 for (i=0; i<8; i++)
7071 {
7072 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7073 }
7074 }
7075
7076 offset += 8;
7077 if (pRxMic)
7078 {
7079 for (i=0; i<8; i++)
7080 {
7081 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7082 }
7083 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007084
7085
7086 //
7087 // Update cipher algorithm. WSTA always use BSS0
7088 //
7089 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7090 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7091 if ((BssIndex%2) == 0)
7092 {
7093 if (KeyIdx == 0)
7094 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7095 else if (KeyIdx == 1)
7096 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7097 else if (KeyIdx == 2)
7098 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7099 else
7100 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7101 }
7102 else
7103 {
7104 if (KeyIdx == 0)
7105 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7106 else if (KeyIdx == 1)
7107 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7108 else if (KeyIdx == 2)
7109 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7110 else
7111 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7112 }
7113 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7114 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7115
7116}
7117
7118// IRQL = DISPATCH_LEVEL
7119VOID AsicRemoveSharedKeyEntry(
7120 IN PRTMP_ADAPTER pAd,
7121 IN UCHAR BssIndex,
7122 IN UCHAR KeyIdx)
7123{
7124 //ULONG SecCsr0;
7125 SHAREDKEY_MODE_STRUC csr1;
7126
7127 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7128
7129 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7130 if ((BssIndex%2) == 0)
7131 {
7132 if (KeyIdx == 0)
7133 csr1.field.Bss0Key0CipherAlg = 0;
7134 else if (KeyIdx == 1)
7135 csr1.field.Bss0Key1CipherAlg = 0;
7136 else if (KeyIdx == 2)
7137 csr1.field.Bss0Key2CipherAlg = 0;
7138 else
7139 csr1.field.Bss0Key3CipherAlg = 0;
7140 }
7141 else
7142 {
7143 if (KeyIdx == 0)
7144 csr1.field.Bss1Key0CipherAlg = 0;
7145 else if (KeyIdx == 1)
7146 csr1.field.Bss1Key1CipherAlg = 0;
7147 else if (KeyIdx == 2)
7148 csr1.field.Bss1Key2CipherAlg = 0;
7149 else
7150 csr1.field.Bss1Key3CipherAlg = 0;
7151 }
7152 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7153 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7154 ASSERT(BssIndex < 4);
7155 ASSERT(KeyIdx < 4);
7156
7157}
7158
7159
7160VOID AsicUpdateWCIDAttribute(
7161 IN PRTMP_ADAPTER pAd,
7162 IN USHORT WCID,
7163 IN UCHAR BssIndex,
7164 IN UCHAR CipherAlg,
7165 IN BOOLEAN bUsePairewiseKeyTable)
7166{
7167 ULONG WCIDAttri = 0, offset;
7168
7169 //
7170 // Update WCID attribute.
7171 // Only TxKey could update WCID attribute.
7172 //
7173 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7174 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7175 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7176}
7177
7178VOID AsicUpdateWCIDIVEIV(
7179 IN PRTMP_ADAPTER pAd,
7180 IN USHORT WCID,
7181 IN ULONG uIV,
7182 IN ULONG uEIV)
7183{
7184 ULONG offset;
7185
7186 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7187
7188 RTMP_IO_WRITE32(pAd, offset, uIV);
7189 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7190}
7191
7192VOID AsicUpdateRxWCIDTable(
7193 IN PRTMP_ADAPTER pAd,
7194 IN USHORT WCID,
7195 IN PUCHAR pAddr)
7196{
7197 ULONG offset;
7198 ULONG Addr;
7199
7200 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7201 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7202 RTMP_IO_WRITE32(pAd, offset, Addr);
7203 Addr = pAddr[4] + (pAddr[5] << 8);
7204 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7205}
7206
7207
7208/*
7209 ========================================================================
7210
7211 Routine Description:
7212 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7213
7214 Arguments:
7215 pAd Pointer to our adapter
7216 WCID WCID Entry number.
7217 BssIndex BSSID index, station or none multiple BSSID support
7218 this value should be 0.
7219 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7220 pCipherKey Pointer to Cipher Key.
7221 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7222 otherwise PairewiseKey table
7223 bTxKey This is the transmit key if enabled.
7224
7225 Return Value:
7226 None
7227
7228 Note:
7229 This routine will set the relative key stuff to Asic including WCID attribute,
7230 Cipher Key, Cipher algorithm and IV/EIV.
7231
7232 IV/EIV will be update if this CipherKey is the transmission key because
7233 ASIC will base on IV's KeyID value to select Cipher Key.
7234
7235 If bTxKey sets to FALSE, this is not the TX key, but it could be
7236 RX key
7237
7238 For AP mode bTxKey must be always set to TRUE.
7239 ========================================================================
7240*/
7241VOID AsicAddKeyEntry(
7242 IN PRTMP_ADAPTER pAd,
7243 IN USHORT WCID,
7244 IN UCHAR BssIndex,
7245 IN UCHAR KeyIdx,
7246 IN PCIPHER_KEY pCipherKey,
7247 IN BOOLEAN bUsePairewiseKeyTable,
7248 IN BOOLEAN bTxKey)
7249{
7250 ULONG offset;
7251 UCHAR IV4 = 0;
7252 PUCHAR pKey = pCipherKey->Key;
7253 PUCHAR pTxMic = pCipherKey->TxMic;
7254 PUCHAR pRxMic = pCipherKey->RxMic;
7255 PUCHAR pTxtsc = pCipherKey->TxTsc;
7256 UCHAR CipherAlg = pCipherKey->CipherAlg;
7257 SHAREDKEY_MODE_STRUC csr1;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007258 UCHAR i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007259
7260 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7261 //
7262 // 1.) decide key table offset
7263 //
7264 if (bUsePairewiseKeyTable)
7265 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7266 else
7267 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7268
7269 //
7270 // 2.) Set Key to Asic
7271 //
7272 //for (i = 0; i < KeyLen; i++)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007273 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7274 {
7275 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7276 }
7277 offset += MAX_LEN_OF_PEER_KEY;
7278
7279 //
7280 // 3.) Set MIC key if available
7281 //
7282 if (pTxMic)
7283 {
7284 for (i = 0; i < 8; i++)
7285 {
7286 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7287 }
7288 }
7289 offset += LEN_TKIP_TXMICK;
7290
7291 if (pRxMic)
7292 {
7293 for (i = 0; i < 8; i++)
7294 {
7295 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7296 }
7297 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007298
7299
7300 //
7301 // 4.) Modify IV/EIV if needs
7302 // This will force Asic to use this key ID by setting IV.
7303 //
7304 if (bTxKey)
7305 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007306 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7307 //
7308 // Write IV
7309 //
7310 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7311 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7312 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7313
7314 IV4 = (KeyIdx << 6);
7315 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7316 IV4 |= 0x20; // turn on extension bit means EIV existence
7317
7318 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7319
7320 //
7321 // Write EIV
7322 //
7323 offset += 4;
7324 for (i = 0; i < 4; i++)
7325 {
7326 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7327 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007328
7329 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7330 }
7331
7332 if (!bUsePairewiseKeyTable)
7333 {
7334 //
7335 // Only update the shared key security mode
7336 //
7337 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7338 if ((BssIndex % 2) == 0)
7339 {
7340 if (KeyIdx == 0)
7341 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7342 else if (KeyIdx == 1)
7343 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7344 else if (KeyIdx == 2)
7345 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7346 else
7347 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7348 }
7349 else
7350 {
7351 if (KeyIdx == 0)
7352 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7353 else if (KeyIdx == 1)
7354 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7355 else if (KeyIdx == 2)
7356 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7357 else
7358 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7359 }
7360 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7361 }
7362
7363 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7364}
7365
7366
7367/*
7368 ========================================================================
7369 Description:
7370 Add Pair-wise key material into ASIC.
7371 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7372
7373 Return:
7374 ========================================================================
7375*/
7376VOID AsicAddPairwiseKeyEntry(
7377 IN PRTMP_ADAPTER pAd,
7378 IN PUCHAR pAddr,
7379 IN UCHAR WCID,
7380 IN CIPHER_KEY *pCipherKey)
7381{
7382 INT i;
7383 ULONG offset;
7384 PUCHAR pKey = pCipherKey->Key;
7385 PUCHAR pTxMic = pCipherKey->TxMic;
7386 PUCHAR pRxMic = pCipherKey->RxMic;
7387#ifdef DBG
7388 UCHAR CipherAlg = pCipherKey->CipherAlg;
7389#endif // DBG //
7390
7391 // EKEY
7392 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007393 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7394 {
7395 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7396 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007397 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7398 {
7399 UINT32 Value;
7400 RTMP_IO_READ32(pAd, offset + i, &Value);
7401 }
7402
7403 offset += MAX_LEN_OF_PEER_KEY;
7404
7405 // MIC KEY
7406 if (pTxMic)
7407 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007408 for (i=0; i<8; i++)
7409 {
7410 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7411 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007412 }
7413 offset += 8;
7414 if (pRxMic)
7415 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007416 for (i=0; i<8; i++)
7417 {
7418 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7419 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007420 }
7421
7422 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7423 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7424 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]));
7425 if (pRxMic)
7426 {
7427 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7428 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7429 }
7430 if (pTxMic)
7431 {
7432 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7433 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7434 }
7435}
7436/*
7437 ========================================================================
7438 Description:
7439 Remove Pair-wise key material from ASIC.
7440
7441 Return:
7442 ========================================================================
7443*/
7444VOID AsicRemovePairwiseKeyEntry(
7445 IN PRTMP_ADAPTER pAd,
7446 IN UCHAR BssIdx,
7447 IN UCHAR Wcid)
7448{
7449 ULONG WCIDAttri;
7450 USHORT offset;
7451
7452 // re-set the entry's WCID attribute as OPEN-NONE.
7453 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7454 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7455 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7456}
7457
7458BOOLEAN AsicSendCommandToMcu(
7459 IN PRTMP_ADAPTER pAd,
7460 IN UCHAR Command,
7461 IN UCHAR Token,
7462 IN UCHAR Arg0,
7463 IN UCHAR Arg1)
7464{
7465 HOST_CMD_CSR_STRUC H2MCmd;
7466 H2M_MAILBOX_STRUC H2MMailbox;
7467 ULONG i = 0;
Bartlomiej Zolnierkiewicz063f22a2009-04-26 16:04:50 +02007468
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007469 do
7470 {
7471 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7472 if (H2MMailbox.field.Owner == 0)
7473 break;
7474
7475 RTMPusecDelay(2);
7476 } while(i++ < 100);
7477
7478 if (i >= 100)
7479 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007480 {
Adam McDanieled291e82009-02-23 08:01:07 -07007481 UINT32 Data;
7482
7483 // Reset DMA
7484 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7485 Data |= 0x2;
7486 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7487
7488 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7489 // Reset DMA/CPU ring index
7490 RTMPRingCleanUp(pAd, QID_AC_BK);
7491 RTMPRingCleanUp(pAd, QID_AC_BE);
7492 RTMPRingCleanUp(pAd, QID_AC_VI);
7493 RTMPRingCleanUp(pAd, QID_AC_VO);
7494 RTMPRingCleanUp(pAd, QID_HCCA);
7495 RTMPRingCleanUp(pAd, QID_MGMT);
7496 RTMPRingCleanUp(pAd, QID_RX);
7497
7498 // Clear Reset
7499 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7500 Data &= 0xfffffffd;
7501 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007502 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7503 }
Adam McDanieled291e82009-02-23 08:01:07 -07007504 //return FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007505 }
7506
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007507 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7508 H2MMailbox.field.CmdToken = Token;
7509 H2MMailbox.field.HighByte = Arg1;
7510 H2MMailbox.field.LowByte = Arg0;
7511 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7512
7513 H2MCmd.word = 0;
7514 H2MCmd.field.HostCommand = Command;
7515 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7516
7517 if (Command != 0x80)
7518 {
7519 }
7520
7521 return TRUE;
7522}
7523
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007524BOOLEAN AsicCheckCommanOk(
7525 IN PRTMP_ADAPTER pAd,
7526 IN UCHAR Command)
7527{
7528 UINT32 CmdStatus = 0, CID = 0, i;
7529 UINT32 ThisCIDMask = 0;
7530
7531 i = 0;
7532 do
7533 {
7534 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7535 // Find where the command is. Because this is randomly specified by firmware.
7536 if ((CID & CID0MASK) == Command)
7537 {
7538 ThisCIDMask = CID0MASK;
7539 break;
7540 }
7541 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7542 {
7543 ThisCIDMask = CID1MASK;
7544 break;
7545 }
7546 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7547 {
7548 ThisCIDMask = CID2MASK;
7549 break;
7550 }
7551 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7552 {
7553 ThisCIDMask = CID3MASK;
7554 break;
7555 }
7556
7557 RTMPusecDelay(100);
7558 i++;
7559 }while (i < 200);
7560
7561 // Get CommandStatus Value
7562 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7563
7564 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7565 if (i < 200)
7566 {
7567 // If Status is 1, the comamnd is success.
7568 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7569 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7570 {
7571 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7572 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7573 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7574 return TRUE;
7575 }
7576 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7577 }
7578 else
7579 {
7580 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7581 }
7582 // Clear Command and Status.
7583 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7584 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7585
7586 return FALSE;
7587}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007588
7589/*
7590 ========================================================================
7591
7592 Routine Description:
7593 Verify the support rate for different PHY type
7594
7595 Arguments:
7596 pAd Pointer to our adapter
7597
7598 Return Value:
7599 None
7600
7601 IRQL = PASSIVE_LEVEL
7602
7603 ========================================================================
7604*/
7605VOID RTMPCheckRates(
7606 IN PRTMP_ADAPTER pAd,
7607 IN OUT UCHAR SupRate[],
7608 IN OUT UCHAR *SupRateLen)
7609{
7610 UCHAR RateIdx, i, j;
7611 UCHAR NewRate[12], NewRateLen;
7612
7613 NewRateLen = 0;
7614
7615 if (pAd->CommonCfg.PhyMode == PHY_11B)
7616 RateIdx = 4;
7617 else
7618 RateIdx = 12;
7619
7620 // Check for support rates exclude basic rate bit
7621 for (i = 0; i < *SupRateLen; i++)
7622 for (j = 0; j < RateIdx; j++)
7623 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7624 NewRate[NewRateLen++] = SupRate[i];
7625
7626 *SupRateLen = NewRateLen;
7627 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7628}
7629
7630#ifdef CONFIG_STA_SUPPORT
7631#ifdef DOT11_N_SUPPORT
7632BOOLEAN RTMPCheckChannel(
7633 IN PRTMP_ADAPTER pAd,
7634 IN UCHAR CentralChannel,
7635 IN UCHAR Channel)
7636{
7637 UCHAR k;
7638 UCHAR UpperChannel = 0, LowerChannel = 0;
7639 UCHAR NoEffectChannelinList = 0;
7640
7641 // Find upper and lower channel according to 40MHz current operation.
7642 if (CentralChannel < Channel)
7643 {
7644 UpperChannel = Channel;
7645 if (CentralChannel > 2)
7646 LowerChannel = CentralChannel - 2;
7647 else
7648 return FALSE;
7649 }
7650 else if (CentralChannel > Channel)
7651 {
7652 UpperChannel = CentralChannel + 2;
7653 LowerChannel = Channel;
7654 }
7655
7656 for (k = 0;k < pAd->ChannelListNum;k++)
7657 {
7658 if (pAd->ChannelList[k].Channel == UpperChannel)
7659 {
7660 NoEffectChannelinList ++;
7661 }
7662 if (pAd->ChannelList[k].Channel == LowerChannel)
7663 {
7664 NoEffectChannelinList ++;
7665 }
7666 }
7667
7668 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7669 if (NoEffectChannelinList == 2)
7670 return TRUE;
7671 else
7672 return FALSE;
7673}
7674
7675/*
7676 ========================================================================
7677
7678 Routine Description:
7679 Verify the support rate for HT phy type
7680
7681 Arguments:
7682 pAd Pointer to our adapter
7683
7684 Return Value:
7685 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7686
7687 IRQL = PASSIVE_LEVEL
7688
7689 ========================================================================
7690*/
7691BOOLEAN RTMPCheckHt(
7692 IN PRTMP_ADAPTER pAd,
7693 IN UCHAR Wcid,
7694 IN HT_CAPABILITY_IE *pHtCapability,
7695 IN ADD_HT_INFO_IE *pAddHtInfo)
7696{
7697 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7698 return FALSE;
7699
7700 // If use AMSDU, set flag.
7701 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7702 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7703 // Save Peer Capability
7704 if (pHtCapability->HtCapInfo.ShortGIfor20)
7705 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7706 if (pHtCapability->HtCapInfo.ShortGIfor40)
7707 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7708 if (pHtCapability->HtCapInfo.TxSTBC)
7709 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7710 if (pHtCapability->HtCapInfo.RxSTBC)
7711 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7712 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7713 {
7714 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7715 }
7716
7717 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7718 {
7719 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7720 }
7721
7722 // Will check ChannelWidth for MCSSet[4] below
7723 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7724 switch (pAd->CommonCfg.RxStream)
7725 {
7726 case 1:
7727 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7728 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7729 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7730 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7731 break;
7732 case 2:
7733 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7734 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7735 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7736 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7737 break;
7738 case 3:
7739 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7740 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7741 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7742 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7743 break;
7744 }
7745
7746 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7747
7748 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7749 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7750 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7751
7752 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7753
7754 // Send Assoc Req with my HT capability.
7755 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7756 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7757 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7758 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7759 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7760 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7761 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7762 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7763 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7764 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7765 if (pAd->CommonCfg.bRdg)
7766 {
7767 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7768 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7769 }
7770
7771 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7772 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7773
7774 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7775 return TRUE;
7776}
7777#endif // DOT11_N_SUPPORT //
7778#endif // CONFIG_STA_SUPPORT //
7779
7780/*
7781 ========================================================================
7782
7783 Routine Description:
7784 Verify the support rate for different PHY type
7785
7786 Arguments:
7787 pAd Pointer to our adapter
7788
7789 Return Value:
7790 None
7791
7792 IRQL = PASSIVE_LEVEL
7793
7794 ========================================================================
7795*/
7796VOID RTMPUpdateMlmeRate(
7797 IN PRTMP_ADAPTER pAd)
7798{
7799 UCHAR MinimumRate;
7800 UCHAR ProperMlmeRate; //= RATE_54;
7801 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7802 BOOLEAN bMatch = FALSE;
7803
7804 switch (pAd->CommonCfg.PhyMode)
7805 {
7806 case PHY_11B:
7807 ProperMlmeRate = RATE_11;
7808 MinimumRate = RATE_1;
7809 break;
7810 case PHY_11BG_MIXED:
7811#ifdef DOT11_N_SUPPORT
7812 case PHY_11ABGN_MIXED:
7813 case PHY_11BGN_MIXED:
7814#endif // DOT11_N_SUPPORT //
7815 if ((pAd->MlmeAux.SupRateLen == 4) &&
7816 (pAd->MlmeAux.ExtRateLen == 0))
7817 // B only AP
7818 ProperMlmeRate = RATE_11;
7819 else
7820 ProperMlmeRate = RATE_24;
7821
7822 if (pAd->MlmeAux.Channel <= 14)
7823 MinimumRate = RATE_1;
7824 else
7825 MinimumRate = RATE_6;
7826 break;
7827 case PHY_11A:
7828#ifdef DOT11_N_SUPPORT
7829 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7830 case PHY_11GN_MIXED:
7831 case PHY_11AGN_MIXED:
7832 case PHY_11AN_MIXED:
7833 case PHY_11N_5G:
7834#endif // DOT11_N_SUPPORT //
7835 ProperMlmeRate = RATE_24;
7836 MinimumRate = RATE_6;
7837 break;
7838 case PHY_11ABG_MIXED:
7839 ProperMlmeRate = RATE_24;
7840 if (pAd->MlmeAux.Channel <= 14)
7841 MinimumRate = RATE_1;
7842 else
7843 MinimumRate = RATE_6;
7844 break;
7845 default: // error
7846 ProperMlmeRate = RATE_1;
7847 MinimumRate = RATE_1;
7848 break;
7849 }
7850
7851 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7852 {
7853 for (j = 0; j < RateIdx; j++)
7854 {
7855 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7856 {
7857 if (j == ProperMlmeRate)
7858 {
7859 bMatch = TRUE;
7860 break;
7861 }
7862 }
7863 }
7864
7865 if (bMatch)
7866 break;
7867 }
7868
7869 if (bMatch == FALSE)
7870 {
7871 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7872 {
7873 for (j = 0; j < RateIdx; j++)
7874 {
7875 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7876 {
7877 if (j == ProperMlmeRate)
7878 {
7879 bMatch = TRUE;
7880 break;
7881 }
7882 }
7883 }
7884
7885 if (bMatch)
7886 break;
7887 }
7888 }
7889
7890 if (bMatch == FALSE)
7891 {
7892 ProperMlmeRate = MinimumRate;
7893 }
7894
7895 pAd->CommonCfg.MlmeRate = MinimumRate;
7896 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7897 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7898 {
7899 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7900 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7901 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7902 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7903 }
7904 else
7905 {
7906 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7907 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7908 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7909 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7910 }
7911
7912 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7913}
7914
7915CHAR RTMPMaxRssi(
7916 IN PRTMP_ADAPTER pAd,
7917 IN CHAR Rssi0,
7918 IN CHAR Rssi1,
7919 IN CHAR Rssi2)
7920{
7921 CHAR larger = -127;
7922
7923 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7924 {
7925 larger = Rssi0;
7926 }
7927
7928 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7929 {
7930 larger = max(Rssi0, Rssi1);
7931 }
7932
7933 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7934 {
7935 larger = max(larger, Rssi2);
7936 }
7937
7938 if (larger == -127)
7939 larger = 0;
7940
7941 return larger;
7942}
7943
7944/*
7945 ========================================================================
7946 Routine Description:
7947 Periodic evaluate antenna link status
7948
7949 Arguments:
7950 pAd - Adapter pointer
7951
7952 Return Value:
7953 None
7954
7955 ========================================================================
7956*/
7957VOID AsicEvaluateRxAnt(
7958 IN PRTMP_ADAPTER pAd)
7959{
7960 UCHAR BBPR3 = 0;
7961
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007962#ifdef CONFIG_STA_SUPPORT
7963 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7964 {
7965 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7966 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7967 fRTMP_ADAPTER_RADIO_OFF |
7968 fRTMP_ADAPTER_NIC_NOT_EXIST |
7969 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7970 return;
7971
7972 if (pAd->StaCfg.Psm == PWR_SAVE)
7973 return;
7974 }
7975#endif // CONFIG_STA_SUPPORT //
7976
7977 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7978 BBPR3 &= (~0x18);
7979 if(pAd->Antenna.field.RxPath == 3)
7980 {
7981 BBPR3 |= (0x10);
7982 }
7983 else if(pAd->Antenna.field.RxPath == 2)
7984 {
7985 BBPR3 |= (0x8);
7986 }
7987 else if(pAd->Antenna.field.RxPath == 1)
7988 {
7989 BBPR3 |= (0x0);
7990 }
7991 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7992#ifdef CONFIG_STA_SUPPORT
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007993 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7994 pAd->StaCfg.BBPR3 = BBPR3;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007995#endif // CONFIG_STA_SUPPORT //
7996 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7997 )
7998 {
7999 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8000 pAd->RalinkCounters.OneSecTxRetryOkCount +
8001 pAd->RalinkCounters.OneSecTxFailCount;
8002
8003 if (TxTotalCnt > 50)
8004 {
8005 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8006 pAd->Mlme.bLowThroughput = FALSE;
8007 }
8008 else
8009 {
8010 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8011 pAd->Mlme.bLowThroughput = TRUE;
8012 }
8013 }
8014}
8015
8016/*
8017 ========================================================================
8018 Routine Description:
8019 After evaluation, check antenna link status
8020
8021 Arguments:
8022 pAd - Adapter pointer
8023
8024 Return Value:
8025 None
8026
8027 ========================================================================
8028*/
8029VOID AsicRxAntEvalTimeout(
8030 IN PVOID SystemSpecific1,
8031 IN PVOID FunctionContext,
8032 IN PVOID SystemSpecific2,
8033 IN PVOID SystemSpecific3)
8034{
8035 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8036#ifdef CONFIG_STA_SUPPORT
8037 UCHAR BBPR3 = 0;
8038 CHAR larger = -127, rssi0, rssi1, rssi2;
8039#endif // CONFIG_STA_SUPPORT //
8040
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008041#ifdef CONFIG_STA_SUPPORT
8042 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8043 {
8044 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8045 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8046 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8047 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8048 return;
8049
8050 if (pAd->StaCfg.Psm == PWR_SAVE)
8051 return;
8052
8053
8054 // if the traffic is low, use average rssi as the criteria
8055 if (pAd->Mlme.bLowThroughput == TRUE)
8056 {
8057 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8058 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8059 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8060 }
8061 else
8062 {
8063 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8064 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8065 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8066 }
8067
8068 if(pAd->Antenna.field.RxPath == 3)
8069 {
8070 larger = max(rssi0, rssi1);
8071
8072 if (larger > (rssi2 + 20))
8073 pAd->Mlme.RealRxPath = 2;
8074 else
8075 pAd->Mlme.RealRxPath = 3;
8076 }
8077 else if(pAd->Antenna.field.RxPath == 2)
8078 {
8079 if (rssi0 > (rssi1 + 20))
8080 pAd->Mlme.RealRxPath = 1;
8081 else
8082 pAd->Mlme.RealRxPath = 2;
8083 }
8084
8085 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8086 BBPR3 &= (~0x18);
8087 if(pAd->Mlme.RealRxPath == 3)
8088 {
8089 BBPR3 |= (0x10);
8090 }
8091 else if(pAd->Mlme.RealRxPath == 2)
8092 {
8093 BBPR3 |= (0x8);
8094 }
8095 else if(pAd->Mlme.RealRxPath == 1)
8096 {
8097 BBPR3 |= (0x0);
8098 }
8099 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
Mark Einonbdc0a172009-03-13 23:28:15 +00008100 pAd->StaCfg.BBPR3 = BBPR3;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008101 }
8102
8103#endif // CONFIG_STA_SUPPORT //
8104
8105}
8106
8107
8108
8109VOID APSDPeriodicExec(
8110 IN PVOID SystemSpecific1,
8111 IN PVOID FunctionContext,
8112 IN PVOID SystemSpecific2,
8113 IN PVOID SystemSpecific3)
8114{
8115 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8116
8117 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8118 return;
8119
8120 pAd->CommonCfg.TriggerTimerCount++;
8121
8122}
8123
8124/*
8125 ========================================================================
8126 Routine Description:
8127 Set/reset MAC registers according to bPiggyBack parameter
8128
8129 Arguments:
8130 pAd - Adapter pointer
8131 bPiggyBack - Enable / Disable Piggy-Back
8132
8133 Return Value:
8134 None
8135
8136 ========================================================================
8137*/
8138VOID RTMPSetPiggyBack(
8139 IN PRTMP_ADAPTER pAd,
8140 IN BOOLEAN bPiggyBack)
8141{
8142 TX_LINK_CFG_STRUC TxLinkCfg;
8143
8144 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8145
8146 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8147 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8148}
8149
8150/*
8151 ========================================================================
8152 Routine Description:
8153 check if this entry need to switch rate automatically
8154
8155 Arguments:
8156 pAd
8157 pEntry
8158
8159 Return Value:
8160 TURE
8161 FALSE
8162
8163 ========================================================================
8164*/
8165BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8166 IN PRTMP_ADAPTER pAd,
8167 IN PMAC_TABLE_ENTRY pEntry)
8168{
8169 BOOLEAN result = TRUE;
8170
8171
8172#ifdef CONFIG_STA_SUPPORT
8173 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8174 {
8175 // only associated STA counts
8176 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8177 {
8178 result = pAd->StaCfg.bAutoTxRateSwitch;
8179 }
8180 else
8181 result = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008182 }
8183#endif // CONFIG_STA_SUPPORT //
8184
8185
8186
8187 return result;
8188}
8189
8190
8191BOOLEAN RTMPAutoRateSwitchCheck(
8192 IN PRTMP_ADAPTER pAd)
8193{
8194
8195#ifdef CONFIG_STA_SUPPORT
8196 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8197 {
8198 if (pAd->StaCfg.bAutoTxRateSwitch)
8199 return TRUE;
8200 }
8201#endif // CONFIG_STA_SUPPORT //
8202 return FALSE;
8203}
8204
8205
8206/*
8207 ========================================================================
8208 Routine Description:
8209 check if this entry need to fix tx legacy rate
8210
8211 Arguments:
8212 pAd
8213 pEntry
8214
8215 Return Value:
8216 TURE
8217 FALSE
8218
8219 ========================================================================
8220*/
8221UCHAR RTMPStaFixedTxMode(
8222 IN PRTMP_ADAPTER pAd,
8223 IN PMAC_TABLE_ENTRY pEntry)
8224{
8225 UCHAR tx_mode = FIXED_TXMODE_HT;
8226
8227
8228#ifdef CONFIG_STA_SUPPORT
8229 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8230 {
8231 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8232 }
8233#endif // CONFIG_STA_SUPPORT //
8234
8235 return tx_mode;
8236}
8237
8238/*
8239 ========================================================================
8240 Routine Description:
8241 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8242
8243 Arguments:
8244 pAd
8245 pEntry
8246
8247 Return Value:
8248 TURE
8249 FALSE
8250
8251 ========================================================================
8252*/
8253VOID RTMPUpdateLegacyTxSetting(
8254 UCHAR fixed_tx_mode,
8255 PMAC_TABLE_ENTRY pEntry)
8256{
8257 HTTRANSMIT_SETTING TransmitSetting;
8258
8259 if (fixed_tx_mode == FIXED_TXMODE_HT)
8260 return;
8261
8262 TransmitSetting.word = 0;
8263
8264 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8265 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8266
8267 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8268 {
8269 TransmitSetting.field.MODE = MODE_CCK;
8270 // CCK mode allow MCS 0~3
8271 if (TransmitSetting.field.MCS > MCS_3)
8272 TransmitSetting.field.MCS = MCS_3;
8273 }
8274 else
8275 {
8276 TransmitSetting.field.MODE = MODE_OFDM;
8277 // OFDM mode allow MCS 0~7
8278 if (TransmitSetting.field.MCS > MCS_7)
8279 TransmitSetting.field.MCS = MCS_7;
8280 }
8281
8282 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8283 {
8284 pEntry->HTPhyMode.word = TransmitSetting.word;
8285 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8286 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8287 }
8288}
8289
8290#ifdef CONFIG_STA_SUPPORT
8291/*
8292 ==========================================================================
8293 Description:
8294 dynamic tune BBP R66 to find a balance between sensibility and
8295 noise isolation
8296
8297 IRQL = DISPATCH_LEVEL
8298
8299 ==========================================================================
8300 */
8301VOID AsicStaBbpTuning(
8302 IN PRTMP_ADAPTER pAd)
8303{
8304 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8305 CHAR Rssi;
8306
8307 // 2860C did not support Fase CCA, therefore can't tune
8308 if (pAd->MACVersion == 0x28600100)
8309 return;
8310
8311 //
8312 // work as a STA
8313 //
8314 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8315 return;
8316
8317 if ((pAd->OpMode == OPMODE_STA)
8318 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8319 )
8320 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
Mark Einonbdc0a172009-03-13 23:28:15 +00008321 && (pAd->bPCIclkOff == FALSE))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008322 {
8323 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8324 R66 = OrigR66Value;
8325
8326 if (pAd->Antenna.field.RxPath > 1)
8327 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8328 else
8329 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8330
8331 if (pAd->LatchRfRegs.Channel <= 14)
8332 { //BG band
8333 {
8334 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8335 {
8336 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8337 if (OrigR66Value != R66)
8338 {
8339 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8340 }
8341 }
8342 else
8343 {
8344 R66 = 0x2E + GET_LNA_GAIN(pAd);
8345 if (OrigR66Value != R66)
8346 {
8347 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8348 }
8349 }
8350 }
8351 }
8352 else
8353 { //A band
8354 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8355 {
8356 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8357 {
8358 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8359 if (OrigR66Value != R66)
8360 {
8361 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8362 }
8363 }
8364 else
8365 {
8366 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8367 if (OrigR66Value != R66)
8368 {
8369 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8370 }
8371 }
8372 }
8373 else
8374 {
8375 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8376 {
8377 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8378 if (OrigR66Value != R66)
8379 {
8380 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8381 }
8382 }
8383 else
8384 {
8385 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8386 if (OrigR66Value != R66)
8387 {
8388 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8389 }
8390 }
8391 }
8392 }
8393
8394
8395 }
8396}
Adam McDanieled291e82009-02-23 08:01:07 -07008397
8398VOID AsicResetFromDMABusy(
8399 IN PRTMP_ADAPTER pAd)
8400{
8401 UINT32 Data;
8402 BOOLEAN bCtrl = FALSE;
8403
8404 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8405
8406 // Be sure restore link control value so we can write register.
8407 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8408 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8409 {
8410 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8411 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8412 RTMPusecDelay(6000);
8413 pAd->bPCIclkOff = FALSE;
8414 bCtrl = TRUE;
8415 }
8416 // Reset DMA
8417 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8418 Data |= 0x2;
8419 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8420
8421 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8422 // Reset DMA/CPU ring index
8423 RTMPRingCleanUp(pAd, QID_AC_BK);
8424 RTMPRingCleanUp(pAd, QID_AC_BE);
8425 RTMPRingCleanUp(pAd, QID_AC_VI);
8426 RTMPRingCleanUp(pAd, QID_AC_VO);
8427 RTMPRingCleanUp(pAd, QID_HCCA);
8428 RTMPRingCleanUp(pAd, QID_MGMT);
8429 RTMPRingCleanUp(pAd, QID_RX);
8430
8431 // Clear Reset
8432 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8433 Data &= 0xfffffffd;
8434 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8435
8436 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8437 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8438 RTMPPCIeLinkCtrlSetting(pAd, 3);
8439
8440 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8441 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8442 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8443}
8444
8445VOID AsicResetBBP(
8446 IN PRTMP_ADAPTER pAd)
8447{
8448 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8449
8450 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8451 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8452 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8453
8454 // After hard-reset BBP, initialize all BBP values.
8455 NICRestoreBBPValue(pAd);
8456 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8457}
8458
8459VOID AsicResetMAC(
8460 IN PRTMP_ADAPTER pAd)
8461{
8462 ULONG Data;
8463
8464 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8465 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8466 Data |= 0x4;
8467 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8468 Data &= 0xfffffffb;
8469 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8470
8471 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8472}
8473
8474VOID AsicResetPBF(
8475 IN PRTMP_ADAPTER pAd)
8476{
8477 ULONG Value1, Value2;
8478 ULONG Data;
8479
8480 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8481 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8482
8483 Value2 &= 0xff;
8484 // sum should be equals to 0xff, which is the total buffer size.
8485 if ((Value1 + Value2) < 0xff)
8486 {
8487 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8488 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8489 Data |= 0x8;
8490 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8491 Data &= 0xfffffff7;
8492 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8493
8494 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8495 }
8496}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008497#endif // CONFIG_STA_SUPPORT //
8498
8499VOID RTMPSetAGCInitValue(
8500 IN PRTMP_ADAPTER pAd,
8501 IN UCHAR BandWidth)
8502{
8503 UCHAR R66 = 0x30;
8504
8505 if (pAd->LatchRfRegs.Channel <= 14)
8506 { // BG band
8507 R66 = 0x2E + GET_LNA_GAIN(pAd);
8508 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8509 }
8510 else
8511 { //A band
8512 if (BandWidth == BW_20)
8513 {
8514 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8515 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8516 }
8517#ifdef DOT11_N_SUPPORT
8518 else
8519 {
8520 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8521 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8522 }
8523#endif // DOT11_N_SUPPORT //
8524 }
8525
8526}
8527
8528VOID AsicTurnOffRFClk(
8529 IN PRTMP_ADAPTER pAd,
8530 IN UCHAR Channel)
8531{
8532
8533 // RF R2 bit 18 = 0
8534 UINT32 R1 = 0, R2 = 0, R3 = 0;
8535 UCHAR index;
8536 RTMP_RF_REGS *RFRegTable;
8537
8538 RFRegTable = RF2850RegTable;
8539
8540 switch (pAd->RfIcType)
8541 {
8542 case RFIC_2820:
8543 case RFIC_2850:
8544 case RFIC_2720:
8545 case RFIC_2750:
8546
8547 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8548 {
8549 if (Channel == RFRegTable[index].Channel)
8550 {
8551 R1 = RFRegTable[index].R1 & 0xffffdfff;
8552 R2 = RFRegTable[index].R2 & 0xfffbffff;
8553 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8554
8555 RTMP_RF_IO_WRITE32(pAd, R1);
8556 RTMP_RF_IO_WRITE32(pAd, R2);
8557
8558 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8559 // Set RF R2 bit18=0, R3 bit[18:19]=0
8560 //if (pAd->StaCfg.bRadio == FALSE)
8561 if (1)
8562 {
8563 RTMP_RF_IO_WRITE32(pAd, R3);
8564
8565 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8566 Channel, pAd->RfIcType, R2, R3));
8567 }
8568 else
8569 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8570 Channel, pAd->RfIcType, R2));
8571 break;
8572 }
8573 }
8574 break;
8575
8576 default:
8577 break;
8578 }
8579}
8580
8581
8582VOID AsicTurnOnRFClk(
8583 IN PRTMP_ADAPTER pAd,
8584 IN UCHAR Channel)
8585{
8586
8587 // RF R2 bit 18 = 0
8588 UINT32 R1 = 0, R2 = 0, R3 = 0;
8589 UCHAR index;
8590 RTMP_RF_REGS *RFRegTable;
8591
8592 RFRegTable = RF2850RegTable;
8593
8594 switch (pAd->RfIcType)
8595 {
8596 case RFIC_2820:
8597 case RFIC_2850:
8598 case RFIC_2720:
8599 case RFIC_2750:
8600
8601 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8602 {
8603 if (Channel == RFRegTable[index].Channel)
8604 {
8605 R3 = pAd->LatchRfRegs.R3;
8606 R3 &= 0xfff3ffff;
8607 R3 |= 0x00080000;
8608 RTMP_RF_IO_WRITE32(pAd, R3);
8609
8610 R1 = RFRegTable[index].R1;
8611 RTMP_RF_IO_WRITE32(pAd, R1);
8612
8613 R2 = RFRegTable[index].R2;
8614 if (pAd->Antenna.field.TxPath == 1)
8615 {
8616 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8617 }
8618
8619 if (pAd->Antenna.field.RxPath == 2)
8620 {
8621 R2 |= 0x40; // write 1 to off Rxpath.
8622 }
8623 else if (pAd->Antenna.field.RxPath == 1)
8624 {
8625 R2 |= 0x20040; // write 1 to off RxPath
8626 }
8627 RTMP_RF_IO_WRITE32(pAd, R2);
8628
8629 break;
8630 }
8631 }
8632 break;
8633
8634 default:
8635 break;
8636 }
8637
8638 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8639 Channel,
8640 pAd->RfIcType,
8641 R2));
8642}
8643