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