blob: d2f0a8be59ce43e2b6f6c9c6581fcd2c908037d5 [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 Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002774#endif
2775#if !defined(RT2860) && !defined(RT30xx)
2776 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2777#endif
2778#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002779 {
2780 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2781 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2782 MlmeSetPsmBit(pAd, PWR_SAVE);
2783 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2784 {
2785 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2786 }
2787 else
2788 {
2789 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2790 }
2791 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002792#endif
2793#ifdef RT30xx
2794// (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2795 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2796 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2797 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2798 {
2799 // add by johnli, use Rx OK data count per second to calculate throughput
2800 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2801 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2802 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2803/* Iverson mark
2804 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2805*/
2806 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2807 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2808/* Iverson mark
2809 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2810*/
2811 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2812 {
2813 // Get this time
2814 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2815 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2816 MlmeSetPsmBit(pAd, PWR_SAVE);
2817 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2818 {
2819 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2820 }
2821 else
2822 {
2823 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2824 }
2825 }
2826 }
2827#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002828}
2829
2830// IRQL = PASSIVE_LEVEL
2831// IRQL = DISPATCH_LEVEL
2832VOID MlmeSetPsmBit(
2833 IN PRTMP_ADAPTER pAd,
2834 IN USHORT psm)
2835{
2836 AUTO_RSP_CFG_STRUC csr4;
2837
2838 pAd->StaCfg.Psm = psm;
2839 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2840 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2841 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002842#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002843 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002844#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002845}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002846
2847// IRQL = DISPATCH_LEVEL
2848VOID MlmeSetTxPreamble(
2849 IN PRTMP_ADAPTER pAd,
2850 IN USHORT TxPreamble)
2851{
2852 AUTO_RSP_CFG_STRUC csr4;
2853
2854 //
2855 // Always use Long preamble before verifiation short preamble functionality works well.
2856 // Todo: remove the following line if short preamble functionality works
2857 //
2858 //TxPreamble = Rt802_11PreambleLong;
2859
2860 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2861 if (TxPreamble == Rt802_11PreambleLong)
2862 {
2863 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2864 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2865 csr4.field.AutoResponderPreamble = 0;
2866 }
2867 else
2868 {
2869 // NOTE: 1Mbps should always use long preamble
2870 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2871 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2872 csr4.field.AutoResponderPreamble = 1;
2873 }
2874
2875 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2876}
2877
2878/*
2879 ==========================================================================
2880 Description:
2881 Update basic rate bitmap
2882 ==========================================================================
2883 */
2884
2885VOID UpdateBasicRateBitmap(
2886 IN PRTMP_ADAPTER pAdapter)
2887{
2888 INT i, j;
2889 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2890 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2891 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2892 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2893 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2894
2895
2896 /* if A mode, always use fix BasicRateBitMap */
2897 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2898 if (pAdapter->CommonCfg.Channel > 14)
2899 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2900 /* End of if */
2901
2902 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2903 {
2904 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2905 return;
2906 } /* End of if */
2907
2908 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2909 {
2910 sup_p[i] &= 0x7f;
2911 ext_p[i] &= 0x7f;
2912 } /* End of for */
2913
2914 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2915 {
2916 if (bitmap & (1 << i))
2917 {
2918 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2919 {
2920 if (sup_p[j] == rate[i])
2921 sup_p[j] |= 0x80;
2922 /* End of if */
2923 } /* End of for */
2924
2925 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2926 {
2927 if (ext_p[j] == rate[i])
2928 ext_p[j] |= 0x80;
2929 /* End of if */
2930 } /* End of for */
2931 } /* End of if */
2932 } /* End of for */
2933} /* End of UpdateBasicRateBitmap */
2934
2935// IRQL = PASSIVE_LEVEL
2936// IRQL = DISPATCH_LEVEL
2937// bLinkUp is to identify the inital link speed.
2938// TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2939VOID MlmeUpdateTxRates(
2940 IN PRTMP_ADAPTER pAd,
2941 IN BOOLEAN bLinkUp,
2942 IN UCHAR apidx)
2943{
2944 int i, num;
2945 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2946 UCHAR MinSupport = RATE_54;
2947 ULONG BasicRateBitmap = 0;
2948 UCHAR CurrBasicRate = RATE_1;
2949 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2950 PHTTRANSMIT_SETTING pHtPhy = NULL;
2951 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2952 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2953 BOOLEAN *auto_rate_cur_p;
2954 UCHAR HtMcs = MCS_AUTO;
2955
2956 // find max desired rate
2957 UpdateBasicRateBitmap(pAd);
2958
2959 num = 0;
2960 auto_rate_cur_p = NULL;
2961 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2962 {
2963 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2964 {
2965 case 2: Rate = RATE_1; num++; break;
2966 case 4: Rate = RATE_2; num++; break;
2967 case 11: Rate = RATE_5_5; num++; break;
2968 case 22: Rate = RATE_11; num++; break;
2969 case 12: Rate = RATE_6; num++; break;
2970 case 18: Rate = RATE_9; num++; break;
2971 case 24: Rate = RATE_12; num++; break;
2972 case 36: Rate = RATE_18; num++; break;
2973 case 48: Rate = RATE_24; num++; break;
2974 case 72: Rate = RATE_36; num++; break;
2975 case 96: Rate = RATE_48; num++; break;
2976 case 108: Rate = RATE_54; num++; break;
2977 //default: Rate = RATE_1; break;
2978 }
2979 if (MaxDesire < Rate) MaxDesire = Rate;
2980 }
2981
2982//===========================================================================
2983//===========================================================================
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002984 {
2985 pHtPhy = &pAd->StaCfg.HTPhyMode;
2986 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2987 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2988
2989 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2990 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2991
2992 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2993 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2994 (MaxDesire > RATE_11))
2995 {
2996 MaxDesire = RATE_11;
2997 }
2998 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002999
3000 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
3001 pMinHtPhy->word = 0;
3002 pMaxHtPhy->word = 0;
3003 pHtPhy->word = 0;
3004
3005 // Auto rate switching is enabled only if more than one DESIRED RATES are
3006 // specified; otherwise disabled
3007 if (num <= 1)
3008 {
3009 *auto_rate_cur_p = FALSE;
3010 }
3011 else
3012 {
3013 *auto_rate_cur_p = TRUE;
3014 }
3015
3016#if 1
3017 if (HtMcs != MCS_AUTO)
3018 {
3019 *auto_rate_cur_p = FALSE;
3020 }
3021 else
3022 {
3023 *auto_rate_cur_p = TRUE;
3024 }
3025#endif
3026
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003027 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3028 {
3029 pSupRate = &pAd->StaActive.SupRate[0];
3030 pExtRate = &pAd->StaActive.ExtRate[0];
3031 SupRateLen = pAd->StaActive.SupRateLen;
3032 ExtRateLen = pAd->StaActive.ExtRateLen;
3033 }
3034 else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003035 {
3036 pSupRate = &pAd->CommonCfg.SupRate[0];
3037 pExtRate = &pAd->CommonCfg.ExtRate[0];
3038 SupRateLen = pAd->CommonCfg.SupRateLen;
3039 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3040 }
3041
3042 // find max supported rate
3043 for (i=0; i<SupRateLen; i++)
3044 {
3045 switch (pSupRate[i] & 0x7f)
3046 {
3047 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3048 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3049 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3050 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3051 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3052 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3053 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3054 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3055 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3056 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3057 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3058 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3059 default: Rate = RATE_1; break;
3060 }
3061 if (MaxSupport < Rate) MaxSupport = Rate;
3062
3063 if (MinSupport > Rate) MinSupport = Rate;
3064 }
3065
3066 for (i=0; i<ExtRateLen; i++)
3067 {
3068 switch (pExtRate[i] & 0x7f)
3069 {
3070 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3071 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3072 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3073 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3074 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3075 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3076 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3077 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3078 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3079 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3080 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3081 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3082 default: Rate = RATE_1; break;
3083 }
3084 if (MaxSupport < Rate) MaxSupport = Rate;
3085
3086 if (MinSupport > Rate) MinSupport = Rate;
3087 }
3088
3089 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3090
3091 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3092 // the DURATION field of outgoing uniicast DATA/MGMT frame
3093 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3094 {
3095 if (BasicRateBitmap & (0x01 << i))
3096 CurrBasicRate = (UCHAR)i;
3097 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3098 }
3099
3100 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3101 // max tx rate = min {max desire rate, max supported rate}
3102 if (MaxSupport < MaxDesire)
3103 pAd->CommonCfg.MaxTxRate = MaxSupport;
3104 else
3105 pAd->CommonCfg.MaxTxRate = MaxDesire;
3106
3107 pAd->CommonCfg.MinTxRate = MinSupport;
3108 if (*auto_rate_cur_p)
3109 {
3110 short dbm = 0;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02003111
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02003112 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02003113
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003114 if (bLinkUp == TRUE)
3115 pAd->CommonCfg.TxRate = RATE_24;
3116 else
3117 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3118
3119 if (dbm < -75)
3120 pAd->CommonCfg.TxRate = RATE_11;
3121 else if (dbm < -70)
3122 pAd->CommonCfg.TxRate = RATE_24;
3123
3124 // should never exceed MaxTxRate (consider 11B-only mode)
3125 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3126 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3127
3128 pAd->CommonCfg.TxRateIndex = 0;
3129 }
3130 else
3131 {
3132 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3133 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3134 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3135
3136 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3137 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3138 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3139 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3140 }
3141
3142 if (pAd->CommonCfg.TxRate <= RATE_11)
3143 {
3144 pMaxHtPhy->field.MODE = MODE_CCK;
3145 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3146 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3147 }
3148 else
3149 {
3150 pMaxHtPhy->field.MODE = MODE_OFDM;
3151 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3152 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3153 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3154 else
3155 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3156 }
3157
3158 pHtPhy->word = (pMaxHtPhy->word);
3159 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3160 {
3161 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3162 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3163 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3164 }
3165 else
3166 {
3167 switch (pAd->CommonCfg.PhyMode)
3168 {
3169 case PHY_11BG_MIXED:
3170 case PHY_11B:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003171 case PHY_11BGN_MIXED:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003172 pAd->CommonCfg.MlmeRate = RATE_1;
3173 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3174 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3175 pAd->CommonCfg.RtsRate = RATE_11;
3176 break;
3177 case PHY_11G:
3178 case PHY_11A:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003179 case PHY_11AGN_MIXED:
3180 case PHY_11GN_MIXED:
3181 case PHY_11N_2_4G:
3182 case PHY_11AN_MIXED:
3183 case PHY_11N_5G:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003184 pAd->CommonCfg.MlmeRate = RATE_6;
3185 pAd->CommonCfg.RtsRate = RATE_6;
3186 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3187 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3188 break;
3189 case PHY_11ABG_MIXED:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003190 case PHY_11ABGN_MIXED:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003191 if (pAd->CommonCfg.Channel <= 14)
3192 {
3193 pAd->CommonCfg.MlmeRate = RATE_1;
3194 pAd->CommonCfg.RtsRate = RATE_1;
3195 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3196 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3197 }
3198 else
3199 {
3200 pAd->CommonCfg.MlmeRate = RATE_6;
3201 pAd->CommonCfg.RtsRate = RATE_6;
3202 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3203 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3204 }
3205 break;
3206 default: // error
3207 pAd->CommonCfg.MlmeRate = RATE_6;
3208 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3209 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3210 pAd->CommonCfg.RtsRate = RATE_1;
3211 break;
3212 }
3213 //
3214 // Keep Basic Mlme Rate.
3215 //
3216 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3217 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3218 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3219 else
3220 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3221 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3222 }
3223
3224 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3225 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3226 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3227 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3228 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3229 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3230 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 ));
3231}
3232
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003233/*
3234 ==========================================================================
3235 Description:
3236 This function update HT Rate setting.
3237 Input Wcid value is valid for 2 case :
3238 1. it's used for Station in infra mode that copy AP rate to Mactable.
3239 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3240
3241 IRQL = DISPATCH_LEVEL
3242
3243 ==========================================================================
3244 */
3245VOID MlmeUpdateHtTxRates(
3246 IN PRTMP_ADAPTER pAd,
3247 IN UCHAR apidx)
3248{
3249 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3250 CHAR i; // 3*3
3251 RT_HT_CAPABILITY *pRtHtCap = NULL;
3252 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3253 ULONG BasicMCS;
3254 UCHAR j, bitmask;
3255 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3256 PHTTRANSMIT_SETTING pHtPhy = NULL;
3257 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3258 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3259 BOOLEAN *auto_rate_cur_p;
3260
3261 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3262
3263 auto_rate_cur_p = NULL;
3264
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003265 {
3266 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3267 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3268 pHtPhy = &pAd->StaCfg.HTPhyMode;
3269 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3270 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3271
3272 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3273 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003274
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003275 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3276 {
3277 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3278 return;
3279
3280 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3281 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3282 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3283 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3284 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3285 pMaxHtPhy->field.STBC = STBC_USE;
3286 else
3287 pMaxHtPhy->field.STBC = STBC_NONE;
3288 }
3289 else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003290 {
3291 if (pDesireHtPhy->bHtEnable == FALSE)
3292 return;
3293
3294 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3295 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3296 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3297 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3298 pMaxHtPhy->field.STBC = STBC_USE;
3299 else
3300 pMaxHtPhy->field.STBC = STBC_NONE;
3301 }
3302
3303 // Decide MAX ht rate.
3304 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3305 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3306 else
3307 pMaxHtPhy->field.MODE = MODE_HTMIX;
3308
3309 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3310 pMaxHtPhy->field.BW = BW_40;
3311 else
3312 pMaxHtPhy->field.BW = BW_20;
3313
3314 if (pMaxHtPhy->field.BW == BW_20)
3315 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3316 else
3317 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3318
3319 for (i=23; i>=0; i--) // 3*3
3320 {
3321 j = i/8;
3322 bitmask = (1<<(i-(j*8)));
3323
3324 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3325 {
3326 pMaxHtPhy->field.MCS = i;
3327 break;
3328 }
3329
3330 if (i==0)
3331 break;
3332 }
3333
3334 // Copy MIN ht rate. rt2860???
3335 pMinHtPhy->field.BW = BW_20;
3336 pMinHtPhy->field.MCS = 0;
3337 pMinHtPhy->field.STBC = 0;
3338 pMinHtPhy->field.ShortGI = 0;
3339 //If STA assigns fixed rate. update to fixed here.
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003340 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3341 {
3342 if (pDesireHtPhy->MCSSet[4] != 0)
3343 {
3344 pMaxHtPhy->field.MCS = 32;
3345 pMinHtPhy->field.MCS = 32;
3346 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3347 }
3348
3349 for (i=23; (CHAR)i >= 0; i--) // 3*3
3350 {
3351 j = i/8;
3352 bitmask = (1<<(i-(j*8)));
3353 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3354 {
3355 pMaxHtPhy->field.MCS = i;
3356 pMinHtPhy->field.MCS = i;
3357 break;
3358 }
3359 if (i==0)
3360 break;
3361 }
3362 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003363
3364 // Decide ht rate
3365 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3366 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3367 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3368 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3369 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3370
3371 // use default now. rt2860
3372 if (pDesireHtPhy->MCSSet[0] != 0xff)
3373 *auto_rate_cur_p = FALSE;
3374 else
3375 *auto_rate_cur_p = TRUE;
3376
3377 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3378 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3379 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3380 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3381}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003382
3383// IRQL = DISPATCH_LEVEL
3384VOID MlmeRadioOff(
3385 IN PRTMP_ADAPTER pAd)
3386{
3387 RT28XX_MLME_RADIO_OFF(pAd);
3388}
3389
3390// IRQL = DISPATCH_LEVEL
3391VOID MlmeRadioOn(
3392 IN PRTMP_ADAPTER pAd)
3393{
3394 RT28XX_MLME_RADIO_ON(pAd);
3395}
3396
3397// ===========================================================================================
3398// bss_table.c
3399// ===========================================================================================
3400
3401
3402/*! \brief initialize BSS table
3403 * \param p_tab pointer to the table
3404 * \return none
3405 * \pre
3406 * \post
3407
3408 IRQL = PASSIVE_LEVEL
3409 IRQL = DISPATCH_LEVEL
3410
3411 */
3412VOID BssTableInit(
3413 IN BSS_TABLE *Tab)
3414{
3415 int i;
3416
3417 Tab->BssNr = 0;
3418 Tab->BssOverlapNr = 0;
3419 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3420 {
3421 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3422 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3423 }
3424}
3425
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003426VOID BATableInit(
3427 IN PRTMP_ADAPTER pAd,
3428 IN BA_TABLE *Tab)
3429{
3430 int i;
3431
3432 Tab->numAsOriginator = 0;
3433 Tab->numAsRecipient = 0;
3434 NdisAllocateSpinLock(&pAd->BATabLock);
3435 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3436 {
3437 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3438 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3439 }
3440 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3441 {
3442 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3443 }
3444}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003445
3446/*! \brief search the BSS table by SSID
3447 * \param p_tab pointer to the bss table
3448 * \param ssid SSID string
3449 * \return index of the table, BSS_NOT_FOUND if not in the table
3450 * \pre
3451 * \post
3452 * \note search by sequential search
3453
3454 IRQL = DISPATCH_LEVEL
3455
3456 */
3457ULONG BssTableSearch(
3458 IN BSS_TABLE *Tab,
3459 IN PUCHAR pBssid,
3460 IN UCHAR Channel)
3461{
3462 UCHAR i;
3463
3464 for (i = 0; i < Tab->BssNr; i++)
3465 {
3466 //
3467 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3468 // We should distinguish this case.
3469 //
3470 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3471 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3472 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3473 {
3474 return i;
3475 }
3476 }
3477 return (ULONG)BSS_NOT_FOUND;
3478}
3479
3480ULONG BssSsidTableSearch(
3481 IN BSS_TABLE *Tab,
3482 IN PUCHAR pBssid,
3483 IN PUCHAR pSsid,
3484 IN UCHAR SsidLen,
3485 IN UCHAR Channel)
3486{
3487 UCHAR i;
3488
3489 for (i = 0; i < Tab->BssNr; i++)
3490 {
3491 //
3492 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3493 // We should distinguish this case.
3494 //
3495 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3496 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3497 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3498 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3499 {
3500 return i;
3501 }
3502 }
3503 return (ULONG)BSS_NOT_FOUND;
3504}
3505
3506ULONG BssTableSearchWithSSID(
3507 IN BSS_TABLE *Tab,
3508 IN PUCHAR Bssid,
3509 IN PUCHAR pSsid,
3510 IN UCHAR SsidLen,
3511 IN UCHAR Channel)
3512{
3513 UCHAR i;
3514
3515 for (i = 0; i < Tab->BssNr; i++)
3516 {
3517 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3518 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3519 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3520 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3521 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3522 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3523 {
3524 return i;
3525 }
3526 }
3527 return (ULONG)BSS_NOT_FOUND;
3528}
3529
3530// IRQL = DISPATCH_LEVEL
3531VOID BssTableDeleteEntry(
3532 IN OUT BSS_TABLE *Tab,
3533 IN PUCHAR pBssid,
3534 IN UCHAR Channel)
3535{
3536 UCHAR i, j;
3537
3538 for (i = 0; i < Tab->BssNr; i++)
3539 {
3540 if ((Tab->BssEntry[i].Channel == Channel) &&
3541 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3542 {
3543 for (j = i; j < Tab->BssNr - 1; j++)
3544 {
3545 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3546 }
3547 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3548 Tab->BssNr -= 1;
3549 return;
3550 }
3551 }
3552}
3553
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003554/*
3555 ========================================================================
3556 Routine Description:
3557 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3558
3559 Arguments:
3560 // IRQL = DISPATCH_LEVEL
3561 ========================================================================
3562*/
3563VOID BATableDeleteORIEntry(
3564 IN OUT PRTMP_ADAPTER pAd,
3565 IN BA_ORI_ENTRY *pBAORIEntry)
3566{
3567
3568 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3569 {
3570 NdisAcquireSpinLock(&pAd->BATabLock);
3571 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3572 {
3573 pAd->BATable.numAsOriginator -= 1;
3574 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3575 // Erase Bitmap flag.
3576 }
3577 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3578 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3579 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3580 pBAORIEntry->Token = 1;
3581 // Not clear Sequence here.
3582 NdisReleaseSpinLock(&pAd->BATabLock);
3583 }
3584}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003585
3586/*! \brief
3587 * \param
3588 * \return
3589 * \pre
3590 * \post
3591
3592 IRQL = DISPATCH_LEVEL
3593
3594 */
3595VOID BssEntrySet(
3596 IN PRTMP_ADAPTER pAd,
3597 OUT BSS_ENTRY *pBss,
3598 IN PUCHAR pBssid,
3599 IN CHAR Ssid[],
3600 IN UCHAR SsidLen,
3601 IN UCHAR BssType,
3602 IN USHORT BeaconPeriod,
3603 IN PCF_PARM pCfParm,
3604 IN USHORT AtimWin,
3605 IN USHORT CapabilityInfo,
3606 IN UCHAR SupRate[],
3607 IN UCHAR SupRateLen,
3608 IN UCHAR ExtRate[],
3609 IN UCHAR ExtRateLen,
3610 IN HT_CAPABILITY_IE *pHtCapability,
3611 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3612 IN UCHAR HtCapabilityLen,
3613 IN UCHAR AddHtInfoLen,
3614 IN UCHAR NewExtChanOffset,
3615 IN UCHAR Channel,
3616 IN CHAR Rssi,
3617 IN LARGE_INTEGER TimeStamp,
3618 IN UCHAR CkipFlag,
3619 IN PEDCA_PARM pEdcaParm,
3620 IN PQOS_CAPABILITY_PARM pQosCapability,
3621 IN PQBSS_LOAD_PARM pQbssLoad,
3622 IN USHORT LengthVIE,
3623 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3624{
3625 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3626 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3627 pBss->Hidden = 1;
3628 if (SsidLen > 0)
3629 {
3630 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3631 // Or send beacon /probe response with SSID len matching real SSID length,
3632 // but SSID is all zero. such as "00-00-00-00" with length 4.
3633 // We have to prevent this case overwrite correct table
3634 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3635 {
3636 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3637 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3638 pBss->SsidLen = SsidLen;
3639 pBss->Hidden = 0;
3640 }
3641 }
3642 else
3643 pBss->SsidLen = 0;
3644 pBss->BssType = BssType;
3645 pBss->BeaconPeriod = BeaconPeriod;
3646 if (BssType == BSS_INFRA)
3647 {
3648 if (pCfParm->bValid)
3649 {
3650 pBss->CfpCount = pCfParm->CfpCount;
3651 pBss->CfpPeriod = pCfParm->CfpPeriod;
3652 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3653 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3654 }
3655 }
3656 else
3657 {
3658 pBss->AtimWin = AtimWin;
3659 }
3660
3661 pBss->CapabilityInfo = CapabilityInfo;
3662 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3663 // Combine with AuthMode, they will decide the connection methods.
3664 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3665 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3666 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3667 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3668 else
3669 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3670 pBss->SupRateLen = SupRateLen;
3671 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3672 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3673 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3674 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3675 pBss->NewExtChanOffset = NewExtChanOffset;
3676 pBss->ExtRateLen = ExtRateLen;
3677 pBss->Channel = Channel;
3678 pBss->CentralChannel = Channel;
3679 pBss->Rssi = Rssi;
3680 // Update CkipFlag. if not exists, the value is 0x0
3681 pBss->CkipFlag = CkipFlag;
3682
3683 // New for microsoft Fixed IEs
3684 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3685 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3686 pBss->FixIEs.Capabilities = CapabilityInfo;
3687
3688 // New for microsoft Variable IEs
3689 if (LengthVIE != 0)
3690 {
3691 pBss->VarIELen = LengthVIE;
3692 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3693 }
3694 else
3695 {
3696 pBss->VarIELen = 0;
3697 }
3698
3699 pBss->AddHtInfoLen = 0;
3700 pBss->HtCapabilityLen = 0;
Bartlomiej Zolnierkiewicz16232672009-04-26 16:06:00 +02003701
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003702 if (HtCapabilityLen> 0)
3703 {
3704 pBss->HtCapabilityLen = HtCapabilityLen;
3705 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3706 if (AddHtInfoLen > 0)
3707 {
3708 pBss->AddHtInfoLen = AddHtInfoLen;
3709 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3710
3711 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3712 {
3713 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3714 }
3715 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3716 {
3717 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3718 }
3719 }
3720 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003721
3722 BssCipherParse(pBss);
3723
3724 // new for QOS
3725 if (pEdcaParm)
3726 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3727 else
3728 pBss->EdcaParm.bValid = FALSE;
3729 if (pQosCapability)
3730 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3731 else
3732 pBss->QosCapability.bValid = FALSE;
3733 if (pQbssLoad)
3734 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3735 else
3736 pBss->QbssLoad.bValid = FALSE;
3737
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003738 {
3739 PEID_STRUCT pEid;
3740 USHORT Length = 0;
3741
3742
3743 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3744 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
Bartlomiej Zolnierkiewiczd439c372009-04-26 16:05:13 +02003745
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003746 pEid = (PEID_STRUCT) pVIE;
Bartlomiej Zolnierkiewiczd439c372009-04-26 16:05:13 +02003747
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003748 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3749 {
3750 switch(pEid->Eid)
3751 {
3752 case IE_WPA:
3753 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3754 {
3755 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3756 {
3757 pBss->WpaIE.IELen = 0;
3758 break;
3759 }
3760 pBss->WpaIE.IELen = pEid->Len + 2;
3761 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3762 }
3763 break;
3764 case IE_RSN:
3765 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3766 {
3767 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3768 {
3769 pBss->RsnIE.IELen = 0;
3770 break;
3771 }
3772 pBss->RsnIE.IELen = pEid->Len + 2;
3773 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3774 }
3775 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003776 }
3777 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3778 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3779 }
3780 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003781}
3782
3783/*!
3784 * \brief insert an entry into the bss table
3785 * \param p_tab The BSS table
3786 * \param Bssid BSSID
3787 * \param ssid SSID
3788 * \param ssid_len Length of SSID
3789 * \param bss_type
3790 * \param beacon_period
3791 * \param timestamp
3792 * \param p_cf
3793 * \param atim_win
3794 * \param cap
3795 * \param rates
3796 * \param rates_len
3797 * \param channel_idx
3798 * \return none
3799 * \pre
3800 * \post
3801 * \note If SSID is identical, the old entry will be replaced by the new one
3802
3803 IRQL = DISPATCH_LEVEL
3804
3805 */
3806ULONG BssTableSetEntry(
3807 IN PRTMP_ADAPTER pAd,
3808 OUT BSS_TABLE *Tab,
3809 IN PUCHAR pBssid,
3810 IN CHAR Ssid[],
3811 IN UCHAR SsidLen,
3812 IN UCHAR BssType,
3813 IN USHORT BeaconPeriod,
3814 IN CF_PARM *CfParm,
3815 IN USHORT AtimWin,
3816 IN USHORT CapabilityInfo,
3817 IN UCHAR SupRate[],
3818 IN UCHAR SupRateLen,
3819 IN UCHAR ExtRate[],
3820 IN UCHAR ExtRateLen,
3821 IN HT_CAPABILITY_IE *pHtCapability,
3822 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3823 IN UCHAR HtCapabilityLen,
3824 IN UCHAR AddHtInfoLen,
3825 IN UCHAR NewExtChanOffset,
3826 IN UCHAR ChannelNo,
3827 IN CHAR Rssi,
3828 IN LARGE_INTEGER TimeStamp,
3829 IN UCHAR CkipFlag,
3830 IN PEDCA_PARM pEdcaParm,
3831 IN PQOS_CAPABILITY_PARM pQosCapability,
3832 IN PQBSS_LOAD_PARM pQbssLoad,
3833 IN USHORT LengthVIE,
3834 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3835{
3836 ULONG Idx;
3837
3838 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3839 if (Idx == BSS_NOT_FOUND)
3840 {
3841 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3842 {
3843 //
3844 // It may happen when BSS Table was full.
3845 // The desired AP will not be added into BSS Table
3846 // In this case, if we found the desired AP then overwrite BSS Table.
3847 //
3848 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3849 {
3850 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3851 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3852 {
3853 Idx = Tab->BssOverlapNr;
3854 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3855 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3856 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3857 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3858 }
3859 return Idx;
3860 }
3861 else
3862 {
3863 return BSS_NOT_FOUND;
3864 }
3865 }
3866 Idx = Tab->BssNr;
3867 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3868 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3869 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3870 Tab->BssNr++;
3871 }
3872 else
3873 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003874#ifdef RT30xx
3875 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3876 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3877 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3878 {
3879#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003880 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3881 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3882 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003883#ifdef RT30xx
3884 }
3885#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003886 }
3887
3888 return Idx;
3889}
3890
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003891// IRQL = DISPATCH_LEVEL
3892VOID BssTableSsidSort(
3893 IN PRTMP_ADAPTER pAd,
3894 OUT BSS_TABLE *OutTab,
3895 IN CHAR Ssid[],
3896 IN UCHAR SsidLen)
3897{
3898 INT i;
3899 BssTableInit(OutTab);
3900
3901 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3902 {
3903 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3904 BOOLEAN bIsHiddenApIncluded = FALSE;
3905
3906 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3907 (pAd->MlmeAux.Channel > 14) &&
3908 RadarChannelCheck(pAd, pInBss->Channel))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003909 )
3910 {
3911 if (pInBss->Hidden)
3912 bIsHiddenApIncluded = TRUE;
3913 }
3914
3915 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3916 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3917 {
3918 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
Bartlomiej Zolnierkiewicz16232672009-04-26 16:06:00 +02003919
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003920 // 2.4G/5G N only mode
3921 if ((pInBss->HtCapabilityLen == 0) &&
3922 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3923 {
3924 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3925 continue;
3926 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003927
3928 // New for WPA2
3929 // Check the Authmode first
3930 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3931 {
3932 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3933 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3934 // None matched
3935 continue;
3936
3937 // Check cipher suite, AP must have more secured cipher than station setting
3938 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3939 {
3940 // If it's not mixed mode, we should only let BSS pass with the same encryption
3941 if (pInBss->WPA.bMixMode == FALSE)
3942 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3943 continue;
3944
3945 // check group cipher
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02003946 if (
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003947#ifndef RT30xx
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02003948 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3949 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003950#endif
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02003951 pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003952 continue;
3953
3954 // check pairwise cipher, skip if none matched
3955 // If profile set to AES, let it pass without question.
3956 // If profile set to TKIP, we must find one mateched
3957 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3958 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3959 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3960 continue;
3961 }
3962 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3963 {
3964 // If it's not mixed mode, we should only let BSS pass with the same encryption
3965 if (pInBss->WPA2.bMixMode == FALSE)
3966 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3967 continue;
3968
3969 // check group cipher
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02003970 if (
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003971#ifndef RT30xx
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02003972 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3973 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003974#endif
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02003975 pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003976 continue;
3977
3978 // check pairwise cipher, skip if none matched
3979 // If profile set to AES, let it pass without question.
3980 // If profile set to TKIP, we must find one mateched
3981 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3982 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3983 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3984 continue;
3985 }
3986 }
3987 // Bss Type matched, SSID matched.
3988 // We will check wepstatus for qualification Bss
3989 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3990 {
3991 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3992 //
3993 // For the SESv2 case, we will not qualify WepStatus.
3994 //
3995 if (!pInBss->bSES)
3996 continue;
3997 }
3998
3999 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4000 // It definitely will fail. So, skip it.
4001 // CCX also require not even try to connect it!!
4002 if (SsidLen == 0)
4003 continue;
4004
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004005 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4006 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4007 if ((pInBss->CentralChannel != pInBss->Channel) &&
4008 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4009 {
4010 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4011 {
4012 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4013 SetCommonHT(pAd);
4014 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4015 }
4016 else
4017 {
4018 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4019 {
4020 SetCommonHT(pAd);
4021 }
4022 }
4023 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004024
4025 // copy matching BSS from InTab to OutTab
4026 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4027
4028 OutTab->BssNr++;
4029 }
4030 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4031 {
4032 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4033
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004034 // 2.4G/5G N only mode
4035 if ((pInBss->HtCapabilityLen == 0) &&
4036 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4037 {
4038 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4039 continue;
4040 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004041
4042 // New for WPA2
4043 // Check the Authmode first
4044 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4045 {
4046 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4047 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4048 // None matched
4049 continue;
4050
4051 // Check cipher suite, AP must have more secured cipher than station setting
4052 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4053 {
4054 // If it's not mixed mode, we should only let BSS pass with the same encryption
4055 if (pInBss->WPA.bMixMode == FALSE)
4056 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4057 continue;
4058
4059 // check group cipher
4060 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4061 continue;
4062
4063 // check pairwise cipher, skip if none matched
4064 // If profile set to AES, let it pass without question.
4065 // If profile set to TKIP, we must find one mateched
4066 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4067 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4068 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4069 continue;
4070 }
4071 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4072 {
4073 // If it's not mixed mode, we should only let BSS pass with the same encryption
4074 if (pInBss->WPA2.bMixMode == FALSE)
4075 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4076 continue;
4077
4078 // check group cipher
4079 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4080 continue;
4081
4082 // check pairwise cipher, skip if none matched
4083 // If profile set to AES, let it pass without question.
4084 // If profile set to TKIP, we must find one mateched
4085 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4086 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4087 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4088 continue;
4089 }
4090 }
4091 // Bss Type matched, SSID matched.
4092 // We will check wepstatus for qualification Bss
4093 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4094 continue;
4095
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004096 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4097 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4098 if ((pInBss->CentralChannel != pInBss->Channel) &&
4099 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4100 {
4101 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4102 {
4103 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4104 SetCommonHT(pAd);
4105 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4106 }
4107 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004108
4109 // copy matching BSS from InTab to OutTab
4110 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4111
4112 OutTab->BssNr++;
4113 }
4114
4115 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4116 break;
4117 }
4118
4119 BssTableSortByRssi(OutTab);
4120}
4121
4122
4123// IRQL = DISPATCH_LEVEL
4124VOID BssTableSortByRssi(
4125 IN OUT BSS_TABLE *OutTab)
4126{
4127 INT i, j;
4128 BSS_ENTRY TmpBss;
4129
4130 for (i = 0; i < OutTab->BssNr - 1; i++)
4131 {
4132 for (j = i+1; j < OutTab->BssNr; j++)
4133 {
4134 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4135 {
4136 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4137 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4138 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4139 }
4140 }
4141 }
4142}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004143
4144VOID BssCipherParse(
4145 IN OUT PBSS_ENTRY pBss)
4146{
4147 PEID_STRUCT pEid;
4148 PUCHAR pTmp;
4149 PRSN_IE_HEADER_STRUCT pRsnHeader;
4150 PCIPHER_SUITE_STRUCT pCipher;
4151 PAKM_SUITE_STRUCT pAKM;
4152 USHORT Count;
4153 INT Length;
4154 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4155
4156 //
4157 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4158 //
4159 if (pBss->Privacy)
4160 {
4161 pBss->WepStatus = Ndis802_11WEPEnabled;
4162 }
4163 else
4164 {
4165 pBss->WepStatus = Ndis802_11WEPDisabled;
4166 }
4167 // Set default to disable & open authentication before parsing variable IE
4168 pBss->AuthMode = Ndis802_11AuthModeOpen;
4169 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4170
4171 // Init WPA setting
4172 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4173 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4174 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4175 pBss->WPA.RsnCapability = 0;
4176 pBss->WPA.bMixMode = FALSE;
4177
4178 // Init WPA2 setting
4179 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4180 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4181 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4182 pBss->WPA2.RsnCapability = 0;
4183 pBss->WPA2.bMixMode = FALSE;
4184
4185
4186 Length = (INT) pBss->VarIELen;
4187
4188 while (Length > 0)
4189 {
4190 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4191 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4192 pEid = (PEID_STRUCT) pTmp;
4193 switch (pEid->Eid)
4194 {
4195 case IE_WPA:
4196 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4197 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4198 {
4199 pTmp += 11;
4200 switch (*pTmp)
4201 {
4202 case 1:
4203 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4204 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4205 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4206 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4207 break;
4208 case 2:
4209 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4210 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4211 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4212 break;
4213 case 4:
4214 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4215 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4216 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4217 break;
4218 default:
4219 break;
4220 }
4221
4222 // if Cisco IE_WPA, break
4223 break;
4224 }
4225 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4226 {
4227 pBss->bSES = TRUE;
4228 break;
4229 }
4230 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4231 {
4232 // if unsupported vendor specific IE
4233 break;
4234 }
4235 // Skip OUI, version, and multicast suite
4236 // This part should be improved in the future when AP supported multiple cipher suite.
4237 // For now, it's OK since almost all APs have fixed cipher suite supported.
4238 // pTmp = (PUCHAR) pEid->Octet;
4239 pTmp += 11;
4240
4241 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4242 // Value Meaning
4243 // 0 None
4244 // 1 WEP-40
4245 // 2 Tkip
4246 // 3 WRAP
4247 // 4 AES
4248 // 5 WEP-104
4249 // Parse group cipher
4250 switch (*pTmp)
4251 {
4252 case 1:
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004253#ifndef RT30xx
Adam McDanieled291e82009-02-23 08:01:07 -07004254 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4255 break;
4256 case 5:
4257 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004258#endif
4259#ifdef RT30xx
4260 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4261 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4262#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004263 break;
4264 case 2:
4265 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4266 break;
4267 case 4:
4268 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4269 break;
4270 default:
4271 break;
4272 }
4273 // number of unicast suite
4274 pTmp += 1;
4275
4276 // skip all unicast cipher suites
4277 //Count = *(PUSHORT) pTmp;
4278 Count = (pTmp[1]<<8) + pTmp[0];
4279 pTmp += sizeof(USHORT);
4280
4281 // Parsing all unicast cipher suite
4282 while (Count > 0)
4283 {
4284 // Skip OUI
4285 pTmp += 3;
4286 TmpCipher = Ndis802_11WEPDisabled;
4287 switch (*pTmp)
4288 {
4289 case 1:
4290 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4291 TmpCipher = Ndis802_11Encryption1Enabled;
4292 break;
4293 case 2:
4294 TmpCipher = Ndis802_11Encryption2Enabled;
4295 break;
4296 case 4:
4297 TmpCipher = Ndis802_11Encryption3Enabled;
4298 break;
4299 default:
4300 break;
4301 }
4302 if (TmpCipher > pBss->WPA.PairCipher)
4303 {
4304 // Move the lower cipher suite to PairCipherAux
4305 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4306 pBss->WPA.PairCipher = TmpCipher;
4307 }
4308 else
4309 {
4310 pBss->WPA.PairCipherAux = TmpCipher;
4311 }
4312 pTmp++;
4313 Count--;
4314 }
4315
4316 // 4. get AKM suite counts
4317 //Count = *(PUSHORT) pTmp;
4318 Count = (pTmp[1]<<8) + pTmp[0];
4319 pTmp += sizeof(USHORT);
4320 pTmp += 3;
4321
4322 switch (*pTmp)
4323 {
4324 case 1:
4325 // Set AP support WPA mode
4326 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4327 pBss->AuthMode = Ndis802_11AuthModeWPA;
4328 else
4329 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4330 break;
4331 case 2:
4332 // Set AP support WPA mode
4333 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4334 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4335 else
4336 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4337 break;
4338 default:
4339 break;
4340 }
4341 pTmp += 1;
4342
4343 // Fixed for WPA-None
4344 if (pBss->BssType == BSS_ADHOC)
4345 {
4346 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4347 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4348 pBss->WepStatus = pBss->WPA.GroupCipher;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004349 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4350 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4351 }
4352 else
4353 pBss->WepStatus = pBss->WPA.PairCipher;
4354
4355 // Check the Pair & Group, if different, turn on mixed mode flag
4356 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4357 pBss->WPA.bMixMode = TRUE;
4358
4359 break;
4360
4361 case IE_RSN:
4362 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4363
4364 // 0. Version must be 1
4365 if (le2cpu16(pRsnHeader->Version) != 1)
4366 break;
4367 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4368
4369 // 1. Check group cipher
4370 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4371 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4372 break;
4373
4374 // Parse group cipher
4375 switch (pCipher->Type)
4376 {
4377 case 1:
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004378#ifndef RT30xx
Adam McDanieled291e82009-02-23 08:01:07 -07004379 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4380 break;
4381 case 5:
4382 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004383#endif
4384#ifdef RT30xx
4385 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4386 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4387#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004388 break;
4389 case 2:
4390 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4391 break;
4392 case 4:
4393 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4394 break;
4395 default:
4396 break;
4397 }
4398 // set to correct offset for next parsing
4399 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4400
4401 // 2. Get pairwise cipher counts
4402 //Count = *(PUSHORT) pTmp;
4403 Count = (pTmp[1]<<8) + pTmp[0];
4404 pTmp += sizeof(USHORT);
4405
4406 // 3. Get pairwise cipher
4407 // Parsing all unicast cipher suite
4408 while (Count > 0)
4409 {
4410 // Skip OUI
4411 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4412 TmpCipher = Ndis802_11WEPDisabled;
4413 switch (pCipher->Type)
4414 {
4415 case 1:
4416 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4417 TmpCipher = Ndis802_11Encryption1Enabled;
4418 break;
4419 case 2:
4420 TmpCipher = Ndis802_11Encryption2Enabled;
4421 break;
4422 case 4:
4423 TmpCipher = Ndis802_11Encryption3Enabled;
4424 break;
4425 default:
4426 break;
4427 }
4428 if (TmpCipher > pBss->WPA2.PairCipher)
4429 {
4430 // Move the lower cipher suite to PairCipherAux
4431 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4432 pBss->WPA2.PairCipher = TmpCipher;
4433 }
4434 else
4435 {
4436 pBss->WPA2.PairCipherAux = TmpCipher;
4437 }
4438 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4439 Count--;
4440 }
4441
4442 // 4. get AKM suite counts
4443 //Count = *(PUSHORT) pTmp;
4444 Count = (pTmp[1]<<8) + pTmp[0];
4445 pTmp += sizeof(USHORT);
4446
4447 // 5. Get AKM ciphers
4448 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4449 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4450 break;
4451
4452 switch (pAKM->Type)
4453 {
4454 case 1:
4455 // Set AP support WPA mode
4456 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4457 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4458 else
4459 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4460 break;
4461 case 2:
4462 // Set AP support WPA mode
4463 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4464 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4465 else
4466 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4467 break;
4468 default:
4469 break;
4470 }
4471 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4472
4473 // Fixed for WPA-None
4474 if (pBss->BssType == BSS_ADHOC)
4475 {
4476 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4477 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4478 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4479 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4480 pBss->WepStatus = pBss->WPA.GroupCipher;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004481 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4482 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4483 }
4484 pBss->WepStatus = pBss->WPA2.PairCipher;
4485
4486 // 6. Get RSN capability
4487 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4488 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4489 pTmp += sizeof(USHORT);
4490
4491 // Check the Pair & Group, if different, turn on mixed mode flag
4492 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4493 pBss->WPA2.bMixMode = TRUE;
4494
4495 break;
4496 default:
4497 break;
4498 }
4499 Length -= (pEid->Len + 2);
4500 }
4501}
4502
4503// ===========================================================================================
4504// mac_table.c
4505// ===========================================================================================
4506
4507/*! \brief generates a random mac address value for IBSS BSSID
4508 * \param Addr the bssid location
4509 * \return none
4510 * \pre
4511 * \post
4512 */
4513VOID MacAddrRandomBssid(
4514 IN PRTMP_ADAPTER pAd,
4515 OUT PUCHAR pAddr)
4516{
4517 INT i;
4518
4519 for (i = 0; i < MAC_ADDR_LEN; i++)
4520 {
4521 pAddr[i] = RandomByte(pAd);
4522 }
4523
4524 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4525}
4526
4527/*! \brief init the management mac frame header
4528 * \param p_hdr mac header
4529 * \param subtype subtype of the frame
4530 * \param p_ds destination address, don't care if it is a broadcast address
4531 * \return none
4532 * \pre the station has the following information in the pAd->StaCfg
4533 * - bssid
4534 * - station address
4535 * \post
4536 * \note this function initializes the following field
4537
4538 IRQL = PASSIVE_LEVEL
4539 IRQL = DISPATCH_LEVEL
4540
4541 */
4542VOID MgtMacHeaderInit(
4543 IN PRTMP_ADAPTER pAd,
4544 IN OUT PHEADER_802_11 pHdr80211,
4545 IN UCHAR SubType,
4546 IN UCHAR ToDs,
4547 IN PUCHAR pDA,
4548 IN PUCHAR pBssid)
4549{
4550 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4551
4552 pHdr80211->FC.Type = BTYPE_MGMT;
4553 pHdr80211->FC.SubType = SubType;
4554 pHdr80211->FC.ToDs = ToDs;
4555 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02004556
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02004557 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02004558
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004559 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4560}
4561
4562// ===========================================================================================
4563// mem_mgmt.c
4564// ===========================================================================================
4565
4566/*!***************************************************************************
4567 * This routine build an outgoing frame, and fill all information specified
4568 * in argument list to the frame body. The actual frame size is the summation
4569 * of all arguments.
4570 * input params:
4571 * Buffer - pointer to a pre-allocated memory segment
4572 * args - a list of <int arg_size, arg> pairs.
4573 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4574 * function will FAIL!!!
4575 * return:
4576 * Size of the buffer
4577 * usage:
4578 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4579
4580 IRQL = PASSIVE_LEVEL
4581 IRQL = DISPATCH_LEVEL
4582
4583 ****************************************************************************/
4584ULONG MakeOutgoingFrame(
4585 OUT CHAR *Buffer,
4586 OUT ULONG *FrameLen, ...)
4587{
4588 CHAR *p;
4589 int leng;
4590 ULONG TotLeng;
4591 va_list Args;
4592
4593 // calculates the total length
4594 TotLeng = 0;
4595 va_start(Args, FrameLen);
4596 do
4597 {
4598 leng = va_arg(Args, int);
4599 if (leng == END_OF_ARGS)
4600 {
4601 break;
4602 }
4603 p = va_arg(Args, PVOID);
4604 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4605 TotLeng = TotLeng + leng;
4606 } while(TRUE);
4607
4608 va_end(Args); /* clean up */
4609 *FrameLen = TotLeng;
4610 return TotLeng;
4611}
4612
4613// ===========================================================================================
4614// mlme_queue.c
4615// ===========================================================================================
4616
4617/*! \brief Initialize The MLME Queue, used by MLME Functions
4618 * \param *Queue The MLME Queue
4619 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4620 * \pre
4621 * \post
4622 * \note Because this is done only once (at the init stage), no need to be locked
4623
4624 IRQL = PASSIVE_LEVEL
4625
4626 */
4627NDIS_STATUS MlmeQueueInit(
4628 IN MLME_QUEUE *Queue)
4629{
4630 INT i;
4631
4632 NdisAllocateSpinLock(&Queue->Lock);
4633
4634 Queue->Num = 0;
4635 Queue->Head = 0;
4636 Queue->Tail = 0;
4637
4638 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4639 {
4640 Queue->Entry[i].Occupied = FALSE;
4641 Queue->Entry[i].MsgLen = 0;
4642 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4643 }
4644
4645 return NDIS_STATUS_SUCCESS;
4646}
4647
4648/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4649 * \param *Queue The MLME Queue
4650 * \param Machine The State Machine Id
4651 * \param MsgType The Message Type
4652 * \param MsgLen The Message length
4653 * \param *Msg The message pointer
4654 * \return TRUE if enqueue is successful, FALSE if the queue is full
4655 * \pre
4656 * \post
4657 * \note The message has to be initialized
4658
4659 IRQL = PASSIVE_LEVEL
4660 IRQL = DISPATCH_LEVEL
4661
4662 */
4663BOOLEAN MlmeEnqueue(
4664 IN PRTMP_ADAPTER pAd,
4665 IN ULONG Machine,
4666 IN ULONG MsgType,
4667 IN ULONG MsgLen,
4668 IN VOID *Msg)
4669{
4670 INT Tail;
4671 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4672
4673 // Do nothing if the driver is starting halt state.
4674 // This might happen when timer already been fired before cancel timer with mlmehalt
4675 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4676 return FALSE;
4677
4678 // First check the size, it MUST not exceed the mlme queue size
4679 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4680 {
4681 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4682 return FALSE;
4683 }
4684
4685 if (MlmeQueueFull(Queue))
4686 {
4687 return FALSE;
4688 }
4689
4690 NdisAcquireSpinLock(&(Queue->Lock));
4691 Tail = Queue->Tail;
4692 Queue->Tail++;
4693 Queue->Num++;
4694 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4695 {
4696 Queue->Tail = 0;
4697 }
4698
4699 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4700 Queue->Entry[Tail].Occupied = TRUE;
4701 Queue->Entry[Tail].Machine = Machine;
4702 Queue->Entry[Tail].MsgType = MsgType;
4703 Queue->Entry[Tail].MsgLen = MsgLen;
4704
4705 if (Msg != NULL)
4706 {
4707 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4708 }
4709
4710 NdisReleaseSpinLock(&(Queue->Lock));
4711 return TRUE;
4712}
4713
4714/*! \brief This function is used when Recv gets a MLME message
4715 * \param *Queue The MLME Queue
4716 * \param TimeStampHigh The upper 32 bit of timestamp
4717 * \param TimeStampLow The lower 32 bit of timestamp
4718 * \param Rssi The receiving RSSI strength
4719 * \param MsgLen The length of the message
4720 * \param *Msg The message pointer
4721 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4722 * \pre
4723 * \post
4724
4725 IRQL = DISPATCH_LEVEL
4726
4727 */
4728BOOLEAN MlmeEnqueueForRecv(
4729 IN PRTMP_ADAPTER pAd,
4730 IN ULONG Wcid,
4731 IN ULONG TimeStampHigh,
4732 IN ULONG TimeStampLow,
4733 IN UCHAR Rssi0,
4734 IN UCHAR Rssi1,
4735 IN UCHAR Rssi2,
4736 IN ULONG MsgLen,
4737 IN VOID *Msg,
4738 IN UCHAR Signal)
4739{
4740 INT Tail, Machine;
4741 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4742 INT MsgType;
4743 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4744
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004745 // Do nothing if the driver is starting halt state.
4746 // This might happen when timer already been fired before cancel timer with mlmehalt
4747 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4748 {
4749 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4750 return FALSE;
4751 }
4752
4753 // First check the size, it MUST not exceed the mlme queue size
4754 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4755 {
4756 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4757 return FALSE;
4758 }
4759
4760 if (MlmeQueueFull(Queue))
4761 {
4762 return FALSE;
4763 }
4764
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004765 {
4766 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4767 {
4768 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4769 return FALSE;
4770 }
4771 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004772
4773 // OK, we got all the informations, it is time to put things into queue
4774 NdisAcquireSpinLock(&(Queue->Lock));
4775 Tail = Queue->Tail;
4776 Queue->Tail++;
4777 Queue->Num++;
4778 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4779 {
4780 Queue->Tail = 0;
4781 }
4782 Queue->Entry[Tail].Occupied = TRUE;
4783 Queue->Entry[Tail].Machine = Machine;
4784 Queue->Entry[Tail].MsgType = MsgType;
4785 Queue->Entry[Tail].MsgLen = MsgLen;
4786 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4787 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4788 Queue->Entry[Tail].Rssi0 = Rssi0;
4789 Queue->Entry[Tail].Rssi1 = Rssi1;
4790 Queue->Entry[Tail].Rssi2 = Rssi2;
4791 Queue->Entry[Tail].Signal = Signal;
4792 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4793
4794 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4795
4796 if (Msg != NULL)
4797 {
4798 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4799 }
4800
4801 NdisReleaseSpinLock(&(Queue->Lock));
4802
4803 RT28XX_MLME_HANDLER(pAd);
4804
4805 return TRUE;
4806}
4807
4808
4809/*! \brief Dequeue a message from the MLME Queue
4810 * \param *Queue The MLME Queue
4811 * \param *Elem The message dequeued from MLME Queue
4812 * \return TRUE if the Elem contains something, FALSE otherwise
4813 * \pre
4814 * \post
4815
4816 IRQL = DISPATCH_LEVEL
4817
4818 */
4819BOOLEAN MlmeDequeue(
4820 IN MLME_QUEUE *Queue,
4821 OUT MLME_QUEUE_ELEM **Elem)
4822{
4823 NdisAcquireSpinLock(&(Queue->Lock));
4824 *Elem = &(Queue->Entry[Queue->Head]);
4825 Queue->Num--;
4826 Queue->Head++;
4827 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4828 {
4829 Queue->Head = 0;
4830 }
4831 NdisReleaseSpinLock(&(Queue->Lock));
4832 return TRUE;
4833}
4834
4835// IRQL = DISPATCH_LEVEL
4836VOID MlmeRestartStateMachine(
4837 IN PRTMP_ADAPTER pAd)
4838{
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004839#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004840 MLME_QUEUE_ELEM *Elem = NULL;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004841#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004842 BOOLEAN Cancelled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004843
4844 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4845
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004846#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004847 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4848 if(pAd->Mlme.bRunning)
4849 {
4850 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4851 return;
4852 }
4853 else
4854 {
4855 pAd->Mlme.bRunning = TRUE;
4856 }
4857 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4858
4859 // Remove all Mlme queues elements
4860 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4861 {
4862 //From message type, determine which state machine I should drive
4863 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4864 {
4865 // free MLME element
4866 Elem->Occupied = FALSE;
4867 Elem->MsgLen = 0;
4868
4869 }
4870 else {
4871 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4872 }
4873 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004874#endif /* RT2860 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004875
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004876 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004877 // Cancel all timer events
4878 // Be careful to cancel new added timer
4879 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4880 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4881 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4882 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4883 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4884 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004885 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004886
4887 // Change back to original channel in case of doing scan
4888 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4889 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4890
4891 // Resume MSDU which is turned off durning scan
4892 RTMPResumeMsduTransmission(pAd);
4893
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004894 {
4895 // Set all state machines back IDLE
4896 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4897 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4898 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4899 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4900 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4901 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004902 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004903
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004904#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004905 // Remove running state
4906 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4907 pAd->Mlme.bRunning = FALSE;
4908 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02004909#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004910}
4911
4912/*! \brief test if the MLME Queue is empty
4913 * \param *Queue The MLME Queue
4914 * \return TRUE if the Queue is empty, FALSE otherwise
4915 * \pre
4916 * \post
4917
4918 IRQL = DISPATCH_LEVEL
4919
4920 */
4921BOOLEAN MlmeQueueEmpty(
4922 IN MLME_QUEUE *Queue)
4923{
4924 BOOLEAN Ans;
4925
4926 NdisAcquireSpinLock(&(Queue->Lock));
4927 Ans = (Queue->Num == 0);
4928 NdisReleaseSpinLock(&(Queue->Lock));
4929
4930 return Ans;
4931}
4932
4933/*! \brief test if the MLME Queue is full
4934 * \param *Queue The MLME Queue
4935 * \return TRUE if the Queue is empty, FALSE otherwise
4936 * \pre
4937 * \post
4938
4939 IRQL = PASSIVE_LEVEL
4940 IRQL = DISPATCH_LEVEL
4941
4942 */
4943BOOLEAN MlmeQueueFull(
4944 IN MLME_QUEUE *Queue)
4945{
4946 BOOLEAN Ans;
4947
4948 NdisAcquireSpinLock(&(Queue->Lock));
4949 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4950 NdisReleaseSpinLock(&(Queue->Lock));
4951
4952 return Ans;
4953}
4954
4955/*! \brief The destructor of MLME Queue
4956 * \param
4957 * \return
4958 * \pre
4959 * \post
4960 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4961
4962 IRQL = PASSIVE_LEVEL
4963
4964 */
4965VOID MlmeQueueDestroy(
4966 IN MLME_QUEUE *pQueue)
4967{
4968 NdisAcquireSpinLock(&(pQueue->Lock));
4969 pQueue->Num = 0;
4970 pQueue->Head = 0;
4971 pQueue->Tail = 0;
4972 NdisReleaseSpinLock(&(pQueue->Lock));
4973 NdisFreeSpinLock(&(pQueue->Lock));
4974}
4975
4976/*! \brief To substitute the message type if the message is coming from external
4977 * \param pFrame The frame received
4978 * \param *Machine The state machine
4979 * \param *MsgType the message type for the state machine
4980 * \return TRUE if the substitution is successful, FALSE otherwise
4981 * \pre
4982 * \post
4983
4984 IRQL = DISPATCH_LEVEL
4985
4986 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004987BOOLEAN MsgTypeSubst(
4988 IN PRTMP_ADAPTER pAd,
4989 IN PFRAME_802_11 pFrame,
4990 OUT INT *Machine,
4991 OUT INT *MsgType)
4992{
4993 USHORT Seq;
4994 UCHAR EAPType;
4995 PUCHAR pData;
4996
4997 // Pointer to start of data frames including SNAP header
4998 pData = (PUCHAR) pFrame + LENGTH_802_11;
4999
5000 // The only data type will pass to this function is EAPOL frame
5001 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5002 {
5003 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5004 {
5005 // Cisco Aironet SNAP header
5006 *Machine = AIRONET_STATE_MACHINE;
5007 *MsgType = MT2_AIRONET_MSG;
5008 return (TRUE);
5009 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005010 {
5011 *Machine = WPA_PSK_STATE_MACHINE;
5012 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5013 return(WpaMsgTypeSubst(EAPType, MsgType));
5014 }
5015 }
5016
5017 switch (pFrame->Hdr.FC.SubType)
5018 {
5019 case SUBTYPE_ASSOC_REQ:
5020 *Machine = ASSOC_STATE_MACHINE;
5021 *MsgType = MT2_PEER_ASSOC_REQ;
5022 break;
5023 case SUBTYPE_ASSOC_RSP:
5024 *Machine = ASSOC_STATE_MACHINE;
5025 *MsgType = MT2_PEER_ASSOC_RSP;
5026 break;
5027 case SUBTYPE_REASSOC_REQ:
5028 *Machine = ASSOC_STATE_MACHINE;
5029 *MsgType = MT2_PEER_REASSOC_REQ;
5030 break;
5031 case SUBTYPE_REASSOC_RSP:
5032 *Machine = ASSOC_STATE_MACHINE;
5033 *MsgType = MT2_PEER_REASSOC_RSP;
5034 break;
5035 case SUBTYPE_PROBE_REQ:
5036 *Machine = SYNC_STATE_MACHINE;
5037 *MsgType = MT2_PEER_PROBE_REQ;
5038 break;
5039 case SUBTYPE_PROBE_RSP:
5040 *Machine = SYNC_STATE_MACHINE;
5041 *MsgType = MT2_PEER_PROBE_RSP;
5042 break;
5043 case SUBTYPE_BEACON:
5044 *Machine = SYNC_STATE_MACHINE;
5045 *MsgType = MT2_PEER_BEACON;
5046 break;
5047 case SUBTYPE_ATIM:
5048 *Machine = SYNC_STATE_MACHINE;
5049 *MsgType = MT2_PEER_ATIM;
5050 break;
5051 case SUBTYPE_DISASSOC:
5052 *Machine = ASSOC_STATE_MACHINE;
5053 *MsgType = MT2_PEER_DISASSOC_REQ;
5054 break;
5055 case SUBTYPE_AUTH:
5056 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5057 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5058 if (Seq == 1 || Seq == 3)
5059 {
5060 *Machine = AUTH_RSP_STATE_MACHINE;
5061 *MsgType = MT2_PEER_AUTH_ODD;
5062 }
5063 else if (Seq == 2 || Seq == 4)
5064 {
5065 *Machine = AUTH_STATE_MACHINE;
5066 *MsgType = MT2_PEER_AUTH_EVEN;
5067 }
5068 else
5069 {
5070 return FALSE;
5071 }
5072 break;
5073 case SUBTYPE_DEAUTH:
5074 *Machine = AUTH_RSP_STATE_MACHINE;
5075 *MsgType = MT2_PEER_DEAUTH;
5076 break;
5077 case SUBTYPE_ACTION:
5078 *Machine = ACTION_STATE_MACHINE;
5079 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5080 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5081 {
5082 *MsgType = MT2_ACT_INVALID;
5083 }
5084 else
5085 {
5086 *MsgType = (pFrame->Octet[0]&0x7F);
5087 }
5088 break;
5089 default:
5090 return FALSE;
5091 break;
5092 }
5093
5094 return TRUE;
5095}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005096
5097// ===========================================================================================
5098// state_machine.c
5099// ===========================================================================================
5100
5101/*! \brief Initialize the state machine.
5102 * \param *S pointer to the state machine
5103 * \param Trans State machine transition function
5104 * \param StNr number of states
5105 * \param MsgNr number of messages
5106 * \param DefFunc default function, when there is invalid state/message combination
5107 * \param InitState initial state of the state machine
5108 * \param Base StateMachine base, internal use only
5109 * \pre p_sm should be a legal pointer
5110 * \post
5111
5112 IRQL = PASSIVE_LEVEL
5113
5114 */
5115VOID StateMachineInit(
5116 IN STATE_MACHINE *S,
5117 IN STATE_MACHINE_FUNC Trans[],
5118 IN ULONG StNr,
5119 IN ULONG MsgNr,
5120 IN STATE_MACHINE_FUNC DefFunc,
5121 IN ULONG InitState,
5122 IN ULONG Base)
5123{
5124 ULONG i, j;
5125
5126 // set number of states and messages
5127 S->NrState = StNr;
5128 S->NrMsg = MsgNr;
5129 S->Base = Base;
5130
5131 S->TransFunc = Trans;
5132
5133 // init all state transition to default function
5134 for (i = 0; i < StNr; i++)
5135 {
5136 for (j = 0; j < MsgNr; j++)
5137 {
5138 S->TransFunc[i * MsgNr + j] = DefFunc;
5139 }
5140 }
5141
5142 // set the starting state
5143 S->CurrState = InitState;
5144}
5145
5146/*! \brief This function fills in the function pointer into the cell in the state machine
5147 * \param *S pointer to the state machine
5148 * \param St state
5149 * \param Msg incoming message
5150 * \param f the function to be executed when (state, message) combination occurs at the state machine
5151 * \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
5152 * \post
5153
5154 IRQL = PASSIVE_LEVEL
5155
5156 */
5157VOID StateMachineSetAction(
5158 IN STATE_MACHINE *S,
5159 IN ULONG St,
5160 IN ULONG Msg,
5161 IN STATE_MACHINE_FUNC Func)
5162{
5163 ULONG MsgIdx;
5164
5165 MsgIdx = Msg - S->Base;
5166
5167 if (St < S->NrState && MsgIdx < S->NrMsg)
5168 {
5169 // boundary checking before setting the action
5170 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5171 }
5172}
5173
5174/*! \brief This function does the state transition
5175 * \param *Adapter the NIC adapter pointer
5176 * \param *S the state machine
5177 * \param *Elem the message to be executed
5178 * \return None
5179
5180 IRQL = DISPATCH_LEVEL
5181
5182 */
5183VOID StateMachinePerformAction(
5184 IN PRTMP_ADAPTER pAd,
5185 IN STATE_MACHINE *S,
5186 IN MLME_QUEUE_ELEM *Elem)
5187{
5188 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5189}
5190
5191/*
5192 ==========================================================================
5193 Description:
5194 The drop function, when machine executes this, the message is simply
5195 ignored. This function does nothing, the message is freed in
5196 StateMachinePerformAction()
5197 ==========================================================================
5198 */
5199VOID Drop(
5200 IN PRTMP_ADAPTER pAd,
5201 IN MLME_QUEUE_ELEM *Elem)
5202{
5203}
5204
5205// ===========================================================================================
5206// lfsr.c
5207// ===========================================================================================
5208
5209/*
5210 ==========================================================================
5211 Description:
5212
5213 IRQL = PASSIVE_LEVEL
5214
5215 ==========================================================================
5216 */
5217VOID LfsrInit(
5218 IN PRTMP_ADAPTER pAd,
5219 IN ULONG Seed)
5220{
5221 if (Seed == 0)
5222 pAd->Mlme.ShiftReg = 1;
5223 else
5224 pAd->Mlme.ShiftReg = Seed;
5225}
5226
5227/*
5228 ==========================================================================
5229 Description:
5230 ==========================================================================
5231 */
5232UCHAR RandomByte(
5233 IN PRTMP_ADAPTER pAd)
5234{
5235 ULONG i;
5236 UCHAR R, Result;
5237
5238 R = 0;
5239
5240 if (pAd->Mlme.ShiftReg == 0)
5241 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5242
5243 for (i = 0; i < 8; i++)
5244 {
5245 if (pAd->Mlme.ShiftReg & 0x00000001)
5246 {
5247 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5248 Result = 1;
5249 }
5250 else
5251 {
5252 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5253 Result = 0;
5254 }
5255 R = (R << 1) | Result;
5256 }
5257
5258 return R;
5259}
5260
5261VOID AsicUpdateAutoFallBackTable(
5262 IN PRTMP_ADAPTER pAd,
5263 IN PUCHAR pRateTable)
5264{
5265 UCHAR i;
5266 HT_FBK_CFG0_STRUC HtCfg0;
5267 HT_FBK_CFG1_STRUC HtCfg1;
5268 LG_FBK_CFG0_STRUC LgCfg0;
5269 LG_FBK_CFG1_STRUC LgCfg1;
5270 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5271
5272 // set to initial value
5273 HtCfg0.word = 0x65432100;
5274 HtCfg1.word = 0xedcba988;
5275 LgCfg0.word = 0xedcba988;
5276 LgCfg1.word = 0x00002100;
5277
5278 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5279 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5280 {
5281 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5282 switch (pCurrTxRate->Mode)
5283 {
5284 case 0: //CCK
5285 break;
5286 case 1: //OFDM
5287 {
5288 switch(pCurrTxRate->CurrMCS)
5289 {
5290 case 0:
5291 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5292 break;
5293 case 1:
5294 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5295 break;
5296 case 2:
5297 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5298 break;
5299 case 3:
5300 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5301 break;
5302 case 4:
5303 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5304 break;
5305 case 5:
5306 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5307 break;
5308 case 6:
5309 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5310 break;
5311 case 7:
5312 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5313 break;
5314 }
5315 }
5316 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005317 case 2: //HT-MIX
5318 case 3: //HT-GF
5319 {
5320 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5321 {
5322 switch(pCurrTxRate->CurrMCS)
5323 {
5324 case 0:
5325 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5326 break;
5327 case 1:
5328 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5329 break;
5330 case 2:
5331 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5332 break;
5333 case 3:
5334 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5335 break;
5336 case 4:
5337 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5338 break;
5339 case 5:
5340 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5341 break;
5342 case 6:
5343 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5344 break;
5345 case 7:
5346 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5347 break;
5348 case 8:
5349 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5350 break;
5351 case 9:
5352 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5353 break;
5354 case 10:
5355 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5356 break;
5357 case 11:
5358 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5359 break;
5360 case 12:
5361 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5362 break;
5363 case 13:
5364 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5365 break;
5366 case 14:
5367 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5368 break;
5369 case 15:
5370 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5371 break;
5372 default:
5373 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5374 }
5375 }
5376 }
5377 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005378 }
5379
5380 pNextTxRate = pCurrTxRate;
5381 }
5382
5383 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5384 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5385 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5386 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5387}
5388
5389/*
5390 ========================================================================
5391
5392 Routine Description:
5393 Set MAC register value according operation mode.
5394 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5395 If MM or GF mask is not set, those passing argument doesn't not take effect.
5396
5397 Operation mode meaning:
5398 = 0 : Pure HT, no preotection.
5399 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5400 = 0x10: No Transmission in 40M is protected.
5401 = 0x11: Transmission in both 40M and 20M shall be protected
5402 if (bNonGFExist)
5403 we should choose not to use GF. But still set correct ASIC registers.
5404 ========================================================================
5405*/
5406VOID AsicUpdateProtect(
5407 IN PRTMP_ADAPTER pAd,
5408 IN USHORT OperationMode,
5409 IN UCHAR SetMask,
5410 IN BOOLEAN bDisableBGProtect,
5411 IN BOOLEAN bNonGFExist)
5412{
5413 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5414 UINT32 Protect[6];
5415 USHORT offset;
5416 UCHAR i;
5417 UINT32 MacReg = 0;
5418
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005419 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5420 {
5421 return;
5422 }
5423
5424 if (pAd->BATable.numAsOriginator)
5425 {
5426 //
5427 // enable the RTS/CTS to avoid channel collision
5428 //
5429 SetMask = ALLN_SETPROTECT;
5430 OperationMode = 8;
5431 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005432
5433 // Config ASIC RTS threshold register
5434 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5435 MacReg &= 0xFF0000FF;
Bartlomiej Zolnierkiewicz96f139e2009-04-26 16:06:12 +02005436
Thadeu Lima de Souza Cascardo4b512d22009-04-14 23:14:10 -03005437 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005438 if ((
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005439 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005440 (pAd->CommonCfg.bAggregationCapable == TRUE))
5441 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5442 {
5443 MacReg |= (0x1000 << 8);
5444 }
5445 else
5446 {
5447 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5448 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005449
5450 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5451
5452 // Initial common protection settings
5453 RTMPZeroMemory(Protect, sizeof(Protect));
5454 ProtCfg4.word = 0;
5455 ProtCfg.word = 0;
5456 ProtCfg.field.TxopAllowGF40 = 1;
5457 ProtCfg.field.TxopAllowGF20 = 1;
5458 ProtCfg.field.TxopAllowMM40 = 1;
5459 ProtCfg.field.TxopAllowMM20 = 1;
5460 ProtCfg.field.TxopAllowOfdm = 1;
5461 ProtCfg.field.TxopAllowCck = 1;
5462 ProtCfg.field.RTSThEn = 1;
5463 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5464
5465 // update PHY mode and rate
5466 if (pAd->CommonCfg.Channel > 14)
5467 ProtCfg.field.ProtectRate = 0x4000;
5468 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5469
5470 // Handle legacy(B/G) protection
5471 if (bDisableBGProtect)
5472 {
5473 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5474 ProtCfg.field.ProtectCtrl = 0;
5475 Protect[0] = ProtCfg.word;
5476 Protect[1] = ProtCfg.word;
5477 }
5478 else
5479 {
5480 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5481 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5482 Protect[0] = ProtCfg.word;
5483 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5484 Protect[1] = ProtCfg.word;
5485 }
5486
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005487 // Decide HT frame protection.
5488 if ((SetMask & ALLN_SETPROTECT) != 0)
5489 {
5490 switch(OperationMode)
5491 {
5492 case 0x0:
5493 // NO PROTECT
5494 // 1.All STAs in the BSS are 20/40 MHz HT
5495 // 2. in ai 20/40MHz BSS
5496 // 3. all STAs are 20MHz in a 20MHz BSS
5497 // Pure HT. no protection.
5498
5499 // MM20_PROT_CFG
5500 // Reserved (31:27)
5501 // PROT_TXOP(25:20) -- 010111
5502 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5503 // PROT_CTRL(17:16) -- 00 (None)
5504 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5505 Protect[2] = 0x01744004;
5506
5507 // MM40_PROT_CFG
5508 // Reserved (31:27)
5509 // PROT_TXOP(25:20) -- 111111
5510 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5511 // PROT_CTRL(17:16) -- 00 (None)
5512 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5513 Protect[3] = 0x03f44084;
5514
5515 // CF20_PROT_CFG
5516 // Reserved (31:27)
5517 // PROT_TXOP(25:20) -- 010111
5518 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5519 // PROT_CTRL(17:16) -- 00 (None)
5520 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5521 Protect[4] = 0x01744004;
5522
5523 // CF40_PROT_CFG
5524 // Reserved (31:27)
5525 // PROT_TXOP(25:20) -- 111111
5526 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5527 // PROT_CTRL(17:16) -- 00 (None)
5528 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5529 Protect[5] = 0x03f44084;
5530
5531 if (bNonGFExist)
5532 {
5533 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5534 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5535 Protect[4] = 0x01754004;
5536 Protect[5] = 0x03f54084;
5537 }
5538 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5539 break;
5540
5541 case 1:
5542 // This is "HT non-member protection mode."
5543 // If there may be non-HT STAs my BSS
5544 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5545 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5546 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5547 {
5548 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5549 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5550 }
5551 //Assign Protection method for 20&40 MHz packets
5552 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5553 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5554 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5555 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5556 Protect[2] = ProtCfg.word;
5557 Protect[3] = ProtCfg4.word;
5558 Protect[4] = ProtCfg.word;
5559 Protect[5] = ProtCfg4.word;
5560 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5561 break;
5562
5563 case 2:
5564 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5565 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5566 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5567
5568 //Assign Protection method for 40MHz packets
5569 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5570 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5571 Protect[2] = ProtCfg.word;
5572 Protect[3] = ProtCfg4.word;
5573 if (bNonGFExist)
5574 {
5575 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5576 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5577 }
5578 Protect[4] = ProtCfg.word;
5579 Protect[5] = ProtCfg4.word;
5580
5581 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5582 break;
5583
5584 case 3:
5585 // HT mixed mode. PROTECT ALL!
5586 // Assign Rate
5587 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5588 ProtCfg4.word = 0x03f44084;
5589 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5590 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5591 {
5592 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5593 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5594 }
5595 //Assign Protection method for 20&40 MHz packets
5596 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5597 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5598 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5599 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5600 Protect[2] = ProtCfg.word;
5601 Protect[3] = ProtCfg4.word;
5602 Protect[4] = ProtCfg.word;
5603 Protect[5] = ProtCfg4.word;
5604 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5605 break;
5606
5607 case 8:
5608 // Special on for Atheros problem n chip.
5609 Protect[2] = 0x01754004;
5610 Protect[3] = 0x03f54084;
5611 Protect[4] = 0x01754004;
5612 Protect[5] = 0x03f54084;
5613 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5614 break;
5615 }
5616 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005617
5618 offset = CCK_PROT_CFG;
5619 for (i = 0;i < 6;i++)
5620 {
5621 if ((SetMask & (1<< i)))
5622 {
5623 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5624 }
5625 }
5626}
5627
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005628#ifdef RT30xx
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005629// add by johnli, RF power sequence setup
5630/*
5631 ==========================================================================
5632 Description:
5633
5634 Load RF normal operation-mode setup
5635
5636 ==========================================================================
5637 */
5638VOID RT30xxLoadRFNormalModeSetup(
5639 IN PRTMP_ADAPTER pAd)
5640{
5641 UCHAR RFValue;
5642
5643 // 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
5644 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5645 RFValue = (RFValue & (~0x0C)) | 0x31;
5646 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5647
5648 // TX_LO2_en, RF R15 register Bit 3 to 0
5649 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5650 RFValue &= (~0x08);
5651 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5652
5653 // TX_LO1_en, RF R17 register Bit 3 to 0
5654 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5655 RFValue &= (~0x08);
5656 // to fix rx long range issue
5657 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5658 {
5659 RFValue |= 0x20;
5660 }
5661 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5662
5663 // RX_LO1_en, RF R20 register Bit 3 to 0
5664 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5665 RFValue &= (~0x08);
5666 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5667
5668 // RX_LO2_en, RF R21 register Bit 3 to 0
5669 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5670 RFValue &= (~0x08);
5671 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5672
5673 // LDORF_VC, RF R27 register Bit 2 to 0
5674 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5675 if ((pAd->MACVersion & 0xffff) < 0x0211)
5676 RFValue = (RFValue & (~0x77)) | 0x3;
5677 else
5678 RFValue = (RFValue & (~0x77));
5679 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5680 /* end johnli */
5681}
5682
5683/*
5684 ==========================================================================
5685 Description:
5686
5687 Load RF sleep-mode setup
5688
5689 ==========================================================================
5690 */
5691VOID RT30xxLoadRFSleepModeSetup(
5692 IN PRTMP_ADAPTER pAd)
5693{
5694 UCHAR RFValue;
5695 UINT32 MACValue;
5696
5697 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5698 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5699 RFValue &= (~0x01);
5700 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5701
5702 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5703 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5704 RFValue &= (~0x30);
5705 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5706
5707 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5708 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5709 RFValue &= (~0x0E);
5710 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5711
5712 // RX_CTB_en, RF R21 register Bit 7 to 0
5713 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5714 RFValue &= (~0x80);
5715 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5716
5717 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5718 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5719 RFValue |= 0x77;
5720 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5721
5722 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5723 MACValue |= 0x1D000000;
5724 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5725}
5726
5727/*
5728 ==========================================================================
5729 Description:
5730
5731 Reverse RF sleep-mode setup
5732
5733 ==========================================================================
5734 */
5735VOID RT30xxReverseRFSleepModeSetup(
5736 IN PRTMP_ADAPTER pAd)
5737{
5738 UCHAR RFValue;
5739 UINT32 MACValue;
5740
5741 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5742 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5743 RFValue |= 0x01;
5744 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5745
5746 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5747 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5748 RFValue |= 0x30;
5749 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5750
5751 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5752 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5753 RFValue |= 0x0E;
5754 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5755
5756 // RX_CTB_en, RF R21 register Bit 7 to 1
5757 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5758 RFValue |= 0x80;
5759 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5760
5761 // LDORF_VC, RF R27 register Bit 2 to 0
5762 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5763 if ((pAd->MACVersion & 0xffff) < 0x0211)
5764 RFValue = (RFValue & (~0x77)) | 0x3;
5765 else
5766 RFValue = (RFValue & (~0x77));
5767 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5768
5769 // RT3071 version E has fixed this issue
5770 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5771 {
5772 // patch tx EVM issue temporarily
5773 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5774 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5775 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5776 }
5777 else
5778 {
5779 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5780 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5781 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5782 }
5783}
5784// end johnli
5785#endif // RT30xx //
5786
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005787/*
5788 ==========================================================================
5789 Description:
5790
5791 IRQL = PASSIVE_LEVEL
5792 IRQL = DISPATCH_LEVEL
5793
5794 ==========================================================================
5795 */
5796VOID AsicSwitchChannel(
5797 IN PRTMP_ADAPTER pAd,
5798 IN UCHAR Channel,
5799 IN BOOLEAN bScan)
5800{
5801 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5802 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5803 UCHAR index;
5804 UINT32 Value = 0; //BbpReg, Value;
5805 RTMP_RF_REGS *RFRegTable;
5806
5807 // Search Tx power value
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005808#ifdef RT30xx
5809 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5810 // in ChannelList, so use TxPower array instead.
5811 //
5812 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5813 {
5814 if (Channel == pAd->TxPower[index].Channel)
5815 {
5816 TxPwer = pAd->TxPower[index].Power;
5817 TxPwer2 = pAd->TxPower[index].Power2;
5818 break;
5819 }
5820 }
5821#endif
5822#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005823 for (index = 0; index < pAd->ChannelListNum; index++)
5824 {
5825 if (Channel == pAd->ChannelList[index].Channel)
5826 {
5827 TxPwer = pAd->ChannelList[index].Power;
5828 TxPwer2 = pAd->ChannelList[index].Power2;
5829 break;
5830 }
5831 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005832#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005833
5834 if (index == MAX_NUM_OF_CHANNELS)
5835 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005836#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005837 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005838#endif
5839#ifdef RT30xx
5840 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5841#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005842 }
5843
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005844#ifdef RT2870
5845 // The RF programming sequence is difference between 3xxx and 2xxx
5846#ifdef RT30xx
5847 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5848 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5849#endif
5850#ifndef RT30xx
5851 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5852#endif
5853 {
5854 /* modify by WY for Read RF Reg. error */
5855 UCHAR RFValue;
5856
5857 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5858 {
5859 if (Channel == FreqItems3020[index].Channel)
5860 {
5861 // Programming channel parameters
5862 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5863 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5864
5865#ifndef RT30xx
5866 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5867 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5868 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5869
5870 // Set Tx Power
5871 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5872 RFValue = (RFValue & 0xE0) | TxPwer;
5873 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5874
5875 // Set RF offset
5876 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5877 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5878 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5879#endif
5880#ifdef RT30xx
5881 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5882 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5883 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5884
5885 // Set Tx0 Power
5886 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5887 RFValue = (RFValue & 0xE0) | TxPwer;
5888 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5889
5890 // Set Tx1 Power
5891 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5892 RFValue = (RFValue & 0xE0) | TxPwer2;
5893 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5894
5895 // Tx/Rx Stream setting
5896 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5897 //if (IS_RT3090(pAd))
5898 // RFValue |= 0x01; // Enable RF block.
5899 RFValue &= 0x03; //clear bit[7~2]
5900 if (pAd->Antenna.field.TxPath == 1)
5901 RFValue |= 0xA0;
5902 else if (pAd->Antenna.field.TxPath == 2)
5903 RFValue |= 0x80;
5904 if (pAd->Antenna.field.RxPath == 1)
5905 RFValue |= 0x50;
5906 else if (pAd->Antenna.field.RxPath == 2)
5907 RFValue |= 0x40;
5908 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5909
5910 // Set RF offset
5911 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5912 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5913 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5914#endif
5915
5916 // Set BW
5917 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5918 {
5919 RFValue = pAd->Mlme.CaliBW40RfR24;
5920 //DISABLE_11N_CHECK(pAd);
5921 }
5922 else
5923 {
5924 RFValue = pAd->Mlme.CaliBW20RfR24;
5925 }
5926#ifndef RT30xx
5927 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5928
5929 // Enable RF tuning
5930 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5931 RFValue = RFValue | 0x1;
5932 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5933
5934 // latch channel for future usage.
5935 pAd->LatchRfRegs.Channel = Channel;
5936#endif
5937#ifdef RT30xx
5938 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5939 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5940
5941 // Enable RF tuning
5942 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5943 RFValue = RFValue | 0x1;
5944 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5945
5946 // latch channel for future usage.
5947 pAd->LatchRfRegs.Channel = Channel;
5948
5949 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5950 Channel,
5951 pAd->RfIcType,
5952 TxPwer,
5953 TxPwer2,
5954 pAd->Antenna.field.TxPath,
5955 FreqItems3020[index].N,
5956 FreqItems3020[index].K,
5957 FreqItems3020[index].R));
5958#endif
5959
5960 break;
5961 }
5962 }
5963
5964#ifndef RT30xx
5965 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5966 Channel,
5967 pAd->RfIcType,
5968 TxPwer,
5969 TxPwer2,
5970 pAd->Antenna.field.TxPath,
5971 FreqItems3020[index].N,
5972 FreqItems3020[index].K,
5973 FreqItems3020[index].R));
5974#endif
5975 }
5976 else
5977#endif // RT2870 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005978 {
5979 RFRegTable = RF2850RegTable;
5980
5981 switch (pAd->RfIcType)
5982 {
5983 case RFIC_2820:
5984 case RFIC_2850:
5985 case RFIC_2720:
5986 case RFIC_2750:
5987
5988 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5989 {
5990 if (Channel == RFRegTable[index].Channel)
5991 {
5992 R2 = RFRegTable[index].R2;
5993 if (pAd->Antenna.field.TxPath == 1)
5994 {
5995 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5996 }
5997
5998 if (pAd->Antenna.field.RxPath == 2)
5999 {
6000 R2 |= 0x40; // write 1 to off Rxpath.
6001 }
6002 else if (pAd->Antenna.field.RxPath == 1)
6003 {
6004 R2 |= 0x20040; // write 1 to off RxPath
6005 }
6006
6007 if (Channel > 14)
6008 {
6009 // initialize R3, R4
6010 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
6011 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
6012
6013 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
6014 // R3
6015 if ((TxPwer >= -7) && (TxPwer < 0))
6016 {
6017 TxPwer = (7+TxPwer);
6018 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6019 R3 |= (TxPwer << 10);
6020 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
6021 }
6022 else
6023 {
6024 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6025 R3 |= (TxPwer << 10) | (1 << 9);
6026 }
6027
6028 // R4
6029 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
6030 {
6031 TxPwer2 = (7+TxPwer2);
6032 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6033 R4 |= (TxPwer2 << 7);
6034 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
6035 }
6036 else
6037 {
6038 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6039 R4 |= (TxPwer2 << 7) | (1 << 6);
6040 }
6041 }
6042 else
6043 {
6044 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6045 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6046 }
6047
6048 // Based on BBP current mode before changing RF channel.
6049 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6050 {
6051 R4 |=0x200000;
6052 }
6053
6054 // Update variables
6055 pAd->LatchRfRegs.Channel = Channel;
6056 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6057 pAd->LatchRfRegs.R2 = R2;
6058 pAd->LatchRfRegs.R3 = R3;
6059 pAd->LatchRfRegs.R4 = R4;
6060
6061 // Set RF value 1's set R3[bit2] = [0]
6062 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6063 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6064 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6065 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6066
6067 RTMPusecDelay(200);
6068
6069 // Set RF value 2's set R3[bit2] = [1]
6070 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6071 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6072 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6073 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6074
6075 RTMPusecDelay(200);
6076
6077 // Set RF value 3's set R3[bit2] = [0]
6078 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6079 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6080 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6081 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6082
6083 break;
6084 }
6085 }
6086 break;
6087
6088 default:
6089 break;
6090 }
6091 }
6092
6093 // Change BBP setting during siwtch from a->g, g->a
6094 if (Channel <= 14)
6095 {
6096 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6097
6098 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6099 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6100 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6101 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.
6102 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6103
6104 // Rx High power VGA offset for LNA select
6105 if (pAd->NicConfig2.field.ExternalLNAForG)
6106 {
6107 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6108 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6109 }
6110 else
6111 {
6112 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6113 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6114 }
6115
6116 // 5G band selection PIN, bit1 and bit2 are complement
6117 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6118 Value &= (~0x6);
6119 Value |= (0x04);
6120 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6121
6122 // Turn off unused PA or LNA when only 1T or 1R
6123 if (pAd->Antenna.field.TxPath == 1)
6124 {
6125 TxPinCfg &= 0xFFFFFFF3;
6126 }
6127 if (pAd->Antenna.field.RxPath == 1)
6128 {
6129 TxPinCfg &= 0xFFFFF3FF;
6130 }
6131
6132 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6133 }
6134 else
6135 {
6136 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6137
6138 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6139 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6140 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6141 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.
6142 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6143
6144 // Rx High power VGA offset for LNA select
6145 if (pAd->NicConfig2.field.ExternalLNAForA)
6146 {
6147 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6148 }
6149 else
6150 {
6151 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6152 }
6153
6154 // 5G band selection PIN, bit1 and bit2 are complement
6155 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6156 Value &= (~0x6);
6157 Value |= (0x02);
6158 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6159
6160 // Turn off unused PA or LNA when only 1T or 1R
6161 if (pAd->Antenna.field.TxPath == 1)
6162 {
6163 TxPinCfg &= 0xFFFFFFF3;
6164 }
6165 if (pAd->Antenna.field.RxPath == 1)
6166 {
6167 TxPinCfg &= 0xFFFFF3FF;
6168 }
6169
6170 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6171 }
6172
6173 // R66 should be set according to Channel and use 20MHz when scanning
6174 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6175 if (bScan)
6176 RTMPSetAGCInitValue(pAd, BW_20);
6177 else
6178 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6179
6180 //
6181 // On 11A, We should delay and wait RF/BBP to be stable
6182 // and the appropriate time should be 1000 micro seconds
6183 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6184 //
6185 RTMPusecDelay(1000);
6186
6187 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",
6188 Channel,
6189 pAd->RfIcType,
6190 (R3 & 0x00003e00) >> 9,
6191 (R4 & 0x000007c0) >> 6,
6192 pAd->Antenna.field.TxPath,
6193 pAd->LatchRfRegs.R1,
6194 pAd->LatchRfRegs.R2,
6195 pAd->LatchRfRegs.R3,
6196 pAd->LatchRfRegs.R4));
6197}
6198
6199/*
6200 ==========================================================================
6201 Description:
6202 This function is required for 2421 only, and should not be used during
6203 site survey. It's only required after NIC decided to stay at a channel
6204 for a longer period.
6205 When this function is called, it's always after AsicSwitchChannel().
6206
6207 IRQL = PASSIVE_LEVEL
6208 IRQL = DISPATCH_LEVEL
6209
6210 ==========================================================================
6211 */
6212VOID AsicLockChannel(
6213 IN PRTMP_ADAPTER pAd,
6214 IN UCHAR Channel)
6215{
6216}
6217
6218/*
6219 ==========================================================================
6220 Description:
6221
6222 IRQL = PASSIVE_LEVEL
6223 IRQL = DISPATCH_LEVEL
6224
6225 ==========================================================================
6226 */
6227VOID AsicAntennaSelect(
6228 IN PRTMP_ADAPTER pAd,
6229 IN UCHAR Channel)
6230{
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006231#ifdef RT30xx
6232 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6233 {
6234 // patch for AsicSetRxAnt failed
6235 pAd->RxAnt.EvaluatePeriod = 0;
6236
6237 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6238 // valid indication of the distance between this AP and its clients.
6239 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6240 {
6241 SHORT realavgrssi1;
6242
6243 // if no traffic then reset average rssi to trigger evaluation
6244 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6245 {
6246 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6247 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6248 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6249 }
6250
6251 pAd->StaCfg.NumOfAvgRssiSample = 0;
6252 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6253
6254 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6255
6256 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6257 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6258 {
6259 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6260 AsicEvaluateRxAnt(pAd);
6261 }
6262 }
6263 else
6264 {
6265 // if not connected, always switch antenna to try to connect
6266 UCHAR temp;
6267
6268 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6269 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6270 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6271
6272 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6273
6274 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6275 }
6276 }
6277#endif /* RT30xx */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006278}
6279
6280/*
6281 ========================================================================
6282
6283 Routine Description:
6284 Antenna miscellaneous setting.
6285
6286 Arguments:
6287 pAd Pointer to our adapter
6288 BandState Indicate current Band State.
6289
6290 Return Value:
6291 None
6292
6293 IRQL <= DISPATCH_LEVEL
6294
6295 Note:
6296 1.) Frame End type control
6297 only valid for G only (RF_2527 & RF_2529)
6298 0: means DPDT, set BBP R4 bit 5 to 1
6299 1: means SPDT, set BBP R4 bit 5 to 0
6300
6301
6302 ========================================================================
6303*/
6304VOID AsicAntennaSetting(
6305 IN PRTMP_ADAPTER pAd,
6306 IN ABGBAND_STATE BandState)
6307{
6308}
6309
6310VOID AsicRfTuningExec(
6311 IN PVOID SystemSpecific1,
6312 IN PVOID FunctionContext,
6313 IN PVOID SystemSpecific2,
6314 IN PVOID SystemSpecific3)
6315{
6316}
6317
6318/*
6319 ==========================================================================
6320 Description:
6321 Gives CCK TX rate 2 more dB TX power.
6322 This routine works only in LINK UP in INFRASTRUCTURE mode.
6323
6324 calculate desired Tx power in RF R3.Tx0~5, should consider -
6325 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6326 1. TxPowerPercentage
6327 2. auto calibration based on TSSI feedback
6328 3. extra 2 db for CCK
6329 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6330
6331 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6332 it should be called AFTER MlmeDynamicTxRatSwitching()
6333 ==========================================================================
6334 */
6335VOID AsicAdjustTxPower(
6336 IN PRTMP_ADAPTER pAd)
6337{
6338 INT i, j;
6339 CHAR DeltaPwr = 0;
6340 BOOLEAN bAutoTxAgc = FALSE;
6341 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6342 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6343 PCHAR pTxAgcCompensate;
6344 ULONG TxPwr[5];
6345 CHAR Value;
6346
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006347#ifdef RT2860
Adam McDanieled291e82009-02-23 08:01:07 -07006348 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6349 || (pAd->bPCIclkOff == TRUE)
6350 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6351 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6352 return;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006353#endif
Adam McDanieled291e82009-02-23 08:01:07 -07006354
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006355 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6356 {
6357 if (pAd->CommonCfg.CentralChannel > 14)
6358 {
6359 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6360 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6361 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6362 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6363 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6364 }
6365 else
6366 {
6367 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6368 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6369 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6370 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6371 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6372 }
6373 }
6374 else
6375 {
6376 if (pAd->CommonCfg.Channel > 14)
6377 {
6378 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6379 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6380 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6381 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6382 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6383 }
6384 else
6385 {
6386 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6387 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6388 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6389 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6390 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6391 }
6392 }
6393
6394 // TX power compensation for temperature variation based on TSSI. try every 4 second
6395 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6396 {
6397 if (pAd->CommonCfg.Channel <= 14)
6398 {
6399 /* bg channel */
6400 bAutoTxAgc = pAd->bAutoTxAgcG;
6401 TssiRef = pAd->TssiRefG;
6402 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6403 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6404 TxAgcStep = pAd->TxAgcStepG;
6405 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6406 }
6407 else
6408 {
6409 /* a channel */
6410 bAutoTxAgc = pAd->bAutoTxAgcA;
6411 TssiRef = pAd->TssiRefA;
6412 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6413 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6414 TxAgcStep = pAd->TxAgcStepA;
6415 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6416 }
6417
6418 if (bAutoTxAgc)
6419 {
6420 /* BbpR1 is unsigned char */
6421 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6422
6423 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6424 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6425 /* step value is defined in pAd->TxAgcStepG for tx power value */
6426
6427 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6428 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6429 above value are examined in mass factory production */
6430 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6431
6432 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6433 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6434 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6435
6436 if (BbpR49 > pTssiMinusBoundary[1])
6437 {
6438 // Reading is larger than the reference value
6439 // check for how large we need to decrease the Tx power
6440 for (idx = 1; idx < 5; idx++)
6441 {
6442 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6443 break;
6444 }
6445 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6446 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6447
6448 DeltaPwr += (*pTxAgcCompensate);
6449 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6450 BbpR49, TssiRef, TxAgcStep, idx-1));
6451 }
6452 else if (BbpR49 < pTssiPlusBoundary[1])
6453 {
6454 // Reading is smaller than the reference value
6455 // check for how large we need to increase the Tx power
6456 for (idx = 1; idx < 5; idx++)
6457 {
6458 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6459 break;
6460 }
6461 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6462 *pTxAgcCompensate = TxAgcStep * (idx-1);
6463 DeltaPwr += (*pTxAgcCompensate);
6464 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6465 BbpR49, TssiRef, TxAgcStep, idx-1));
6466 }
6467 else
6468 {
6469 *pTxAgcCompensate = 0;
6470 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6471 BbpR49, TssiRef, TxAgcStep, 0));
6472 }
6473 }
6474 }
6475 else
6476 {
6477 if (pAd->CommonCfg.Channel <= 14)
6478 {
6479 bAutoTxAgc = pAd->bAutoTxAgcG;
6480 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6481 }
6482 else
6483 {
6484 bAutoTxAgc = pAd->bAutoTxAgcA;
6485 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6486 }
6487
6488 if (bAutoTxAgc)
6489 DeltaPwr += (*pTxAgcCompensate);
6490 }
6491
6492 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6493 BbpR1 &= 0xFC;
6494
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006495 /* calculate delta power based on the percentage specified from UI */
6496 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6497 // We lower TX power here according to the percentage specified from UI
6498 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6499 ;
6500 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6501 ;
6502 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6503 {
6504 DeltaPwr -= 1;
6505 }
6506 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6507 {
6508 DeltaPwr -= 3;
6509 }
6510 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6511 {
6512 BbpR1 |= 0x01;
6513 }
6514 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6515 {
6516 BbpR1 |= 0x01;
6517 DeltaPwr -= 3;
6518 }
6519 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6520 {
6521 BbpR1 |= 0x02;
6522 }
6523
6524 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6525
6526 /* reset different new tx power for different TX rate */
6527 for(i=0; i<5; i++)
6528 {
6529 if (TxPwr[i] != 0xffffffff)
6530 {
6531 for (j=0; j<8; j++)
6532 {
6533 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6534
6535 if ((Value + DeltaPwr) < 0)
6536 {
6537 Value = 0; /* min */
6538 }
6539 else if ((Value + DeltaPwr) > 0xF)
6540 {
6541 Value = 0xF; /* max */
6542 }
6543 else
6544 {
6545 Value += DeltaPwr; /* temperature compensation */
6546 }
6547
6548 /* fill new value to CSR offset */
6549 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6550 }
6551
6552 /* write tx power value to CSR */
6553 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6554 TX power for OFDM 6M/9M
6555 TX power for CCK5.5M/11M
6556 TX power for CCK1M/2M */
6557 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6558 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6559 }
6560 }
6561
6562}
6563
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006564/*
6565 ==========================================================================
6566 Description:
6567 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6568 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6569 the wakeup timer timeout. Driver has to issue a separate command to wake
6570 PHY up.
6571
6572 IRQL = DISPATCH_LEVEL
6573
6574 ==========================================================================
6575 */
6576VOID AsicSleepThenAutoWakeup(
6577 IN PRTMP_ADAPTER pAd,
6578 IN USHORT TbttNumToNextWakeUp)
6579{
6580 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6581}
6582
6583/*
6584 ==========================================================================
6585 Description:
6586 AsicForceWakeup() is used whenever manual wakeup is required
6587 AsicForceSleep() should only be used when not in INFRA BSS. When
6588 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6589 ==========================================================================
6590 */
6591VOID AsicForceSleep(
6592 IN PRTMP_ADAPTER pAd)
6593{
6594
6595}
6596
6597/*
6598 ==========================================================================
6599 Description:
6600 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6601 expired.
6602
6603 IRQL = PASSIVE_LEVEL
6604 IRQL = DISPATCH_LEVEL
6605 ==========================================================================
6606 */
6607VOID AsicForceWakeup(
6608 IN PRTMP_ADAPTER pAd,
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006609#ifdef RT2860
Adam McDanieled291e82009-02-23 08:01:07 -07006610 IN UCHAR Level)
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006611#endif
6612#ifdef RT2870
6613 IN BOOLEAN bFromTx)
6614#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006615{
6616 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006617#ifdef RT2860
Adam McDanieled291e82009-02-23 08:01:07 -07006618 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006619#endif
6620#ifdef RT2870
6621 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6622#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006623}
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02006624
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006625/*
6626 ==========================================================================
6627 Description:
6628 Set My BSSID
6629
6630 IRQL = DISPATCH_LEVEL
6631
6632 ==========================================================================
6633 */
6634VOID AsicSetBssid(
6635 IN PRTMP_ADAPTER pAd,
6636 IN PUCHAR pBssid)
6637{
6638 ULONG Addr4;
6639 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6640 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6641
6642 Addr4 = (ULONG)(pBssid[0]) |
6643 (ULONG)(pBssid[1] << 8) |
6644 (ULONG)(pBssid[2] << 16) |
6645 (ULONG)(pBssid[3] << 24);
6646 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6647
6648 Addr4 = 0;
6649 // always one BSSID in STA mode
6650 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6651
6652 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6653}
6654
6655VOID AsicSetMcastWC(
6656 IN PRTMP_ADAPTER pAd)
6657{
6658 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6659 USHORT offset;
6660
6661 pEntry->Sst = SST_ASSOC;
6662 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6663 pEntry->PsMode = PWR_ACTIVE;
6664 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6665 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6666}
6667
6668/*
6669 ==========================================================================
6670 Description:
6671
6672 IRQL = DISPATCH_LEVEL
6673
6674 ==========================================================================
6675 */
6676VOID AsicDelWcidTab(
6677 IN PRTMP_ADAPTER pAd,
6678 IN UCHAR Wcid)
6679{
6680 ULONG Addr0 = 0x0, Addr1 = 0x0;
6681 ULONG offset;
6682
6683 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6684 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6685 RTMP_IO_WRITE32(pAd, offset, Addr0);
6686 offset += 4;
6687 RTMP_IO_WRITE32(pAd, offset, Addr1);
6688}
6689
6690/*
6691 ==========================================================================
6692 Description:
6693
6694 IRQL = DISPATCH_LEVEL
6695
6696 ==========================================================================
6697 */
6698VOID AsicEnableRDG(
6699 IN PRTMP_ADAPTER pAd)
6700{
6701 TX_LINK_CFG_STRUC TxLinkCfg;
6702 UINT32 Data = 0;
6703
6704 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6705 TxLinkCfg.field.TxRDGEn = 1;
6706 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6707
6708 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6709 Data &= 0xFFFFFF00;
6710 Data |= 0x80;
6711 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6712
6713 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6714}
6715
6716/*
6717 ==========================================================================
6718 Description:
6719
6720 IRQL = DISPATCH_LEVEL
6721
6722 ==========================================================================
6723 */
6724VOID AsicDisableRDG(
6725 IN PRTMP_ADAPTER pAd)
6726{
6727 TX_LINK_CFG_STRUC TxLinkCfg;
6728 UINT32 Data = 0;
6729
6730
6731 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6732 TxLinkCfg.field.TxRDGEn = 0;
6733 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6734
6735 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6736
6737 Data &= 0xFFFFFF00;
6738 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006739 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006740 )
6741 {
6742 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6743 if (pAd->CommonCfg.bEnableTxBurst)
6744 Data |= 0x20;
6745 }
6746 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6747}
6748
6749/*
6750 ==========================================================================
6751 Description:
6752
6753 IRQL = PASSIVE_LEVEL
6754 IRQL = DISPATCH_LEVEL
6755
6756 ==========================================================================
6757 */
6758VOID AsicDisableSync(
6759 IN PRTMP_ADAPTER pAd)
6760{
6761 BCN_TIME_CFG_STRUC csr;
6762
6763 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6764
6765 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6766 // that NIC will never wakes up because TSF stops and no more
6767 // TBTT interrupts
6768 pAd->TbttTickCount = 0;
6769 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6770 csr.field.bBeaconGen = 0;
6771 csr.field.bTBTTEnable = 0;
6772 csr.field.TsfSyncMode = 0;
6773 csr.field.bTsfTicking = 0;
6774 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6775
6776}
6777
6778/*
6779 ==========================================================================
6780 Description:
6781
6782 IRQL = DISPATCH_LEVEL
6783
6784 ==========================================================================
6785 */
6786VOID AsicEnableBssSync(
6787 IN PRTMP_ADAPTER pAd)
6788{
6789 BCN_TIME_CFG_STRUC csr;
6790
6791 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6792
6793 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02006794
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006795 {
6796 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6797 csr.field.bTsfTicking = 1;
6798 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6799 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6800 csr.field.bTBTTEnable = 1;
6801 }
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02006802
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006803 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6804}
6805
6806/*
6807 ==========================================================================
6808 Description:
6809 Note:
6810 BEACON frame in shared memory should be built ok before this routine
6811 can be called. Otherwise, a garbage frame maybe transmitted out every
6812 Beacon period.
6813
6814 IRQL = DISPATCH_LEVEL
6815
6816 ==========================================================================
6817 */
6818VOID AsicEnableIbssSync(
6819 IN PRTMP_ADAPTER pAd)
6820{
6821 BCN_TIME_CFG_STRUC csr9;
6822 PUCHAR ptr;
6823 UINT i;
6824
6825 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6826
6827 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6828 csr9.field.bBeaconGen = 0;
6829 csr9.field.bTBTTEnable = 0;
6830 csr9.field.bTsfTicking = 0;
6831 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6832
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006833#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006834 // move BEACON TXD and frame content to on-chip memory
6835 ptr = (PUCHAR)&pAd->BeaconTxWI;
6836 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6837 {
6838 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6839 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6840 ptr += 4;
6841 }
6842
6843 // start right after the 16-byte TXWI field
6844 ptr = pAd->BeaconBuf;
6845 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6846 {
6847 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6848 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6849 ptr +=4;
6850 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02006851#endif
6852#ifdef RT2870
6853 // move BEACON TXD and frame content to on-chip memory
6854 ptr = (PUCHAR)&pAd->BeaconTxWI;
6855 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6856 {
6857 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6858 ptr += 2;
6859 }
6860
6861 // start right after the 16-byte TXWI field
6862 ptr = pAd->BeaconBuf;
6863 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6864 {
6865 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6866 ptr +=2;
6867 }
6868#endif // RT2870 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006869
6870 // start sending BEACON
6871 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6872 csr9.field.bTsfTicking = 1;
6873 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6874 csr9.field.bTBTTEnable = 1;
6875 csr9.field.bBeaconGen = 1;
6876 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6877}
6878
6879/*
6880 ==========================================================================
6881 Description:
6882
6883 IRQL = PASSIVE_LEVEL
6884 IRQL = DISPATCH_LEVEL
6885
6886 ==========================================================================
6887 */
6888VOID AsicSetEdcaParm(
6889 IN PRTMP_ADAPTER pAd,
6890 IN PEDCA_PARM pEdcaParm)
6891{
6892 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6893 AC_TXOP_CSR0_STRUC csr0;
6894 AC_TXOP_CSR1_STRUC csr1;
6895 AIFSN_CSR_STRUC AifsnCsr;
6896 CWMIN_CSR_STRUC CwminCsr;
6897 CWMAX_CSR_STRUC CwmaxCsr;
6898 int i;
6899
6900 Ac0Cfg.word = 0;
6901 Ac1Cfg.word = 0;
6902 Ac2Cfg.word = 0;
6903 Ac3Cfg.word = 0;
6904 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6905 {
6906 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6907 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6908 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6909 {
6910 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6911 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6912 }
6913
6914 //========================================================
6915 // MAC Register has a copy .
6916 //========================================================
6917 if( pAd->CommonCfg.bEnableTxBurst )
6918 {
6919 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6920 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6921 }
6922 else
6923 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6924 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6925 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6926 Ac0Cfg.field.Aifsn = 2;
6927 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6928
6929 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6930 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6931 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6932 Ac1Cfg.field.Aifsn = 2;
6933 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6934
6935 if (pAd->CommonCfg.PhyMode == PHY_11B)
6936 {
6937 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6938 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6939 }
6940 else
6941 {
6942 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6943 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6944 }
6945 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6946 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6947 Ac2Cfg.field.Aifsn = 2;
6948 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6949 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6950 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6951 Ac3Cfg.field.Aifsn = 2;
6952 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6953
6954 //========================================================
6955 // DMA Register has a copy too.
6956 //========================================================
6957 csr0.field.Ac0Txop = 0; // QID_AC_BE
6958 csr0.field.Ac1Txop = 0; // QID_AC_BK
6959 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6960 if (pAd->CommonCfg.PhyMode == PHY_11B)
6961 {
6962 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6963 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6964 }
6965 else
6966 {
6967 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6968 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6969 }
6970 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6971
6972 CwminCsr.word = 0;
6973 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6974 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6975 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6976 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6977 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6978
6979 CwmaxCsr.word = 0;
6980 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6981 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6982 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6983 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6984 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6985
6986 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6987
6988 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6989 }
6990 else
6991 {
6992 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6993 //========================================================
6994 // MAC Register has a copy.
6995 //========================================================
6996 //
6997 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6998 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6999 //
7000 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
7001
7002 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
7003 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
7004 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
7005 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
7006
7007 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7008 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
7009 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
7010 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
7011
7012 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
7013 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
7014 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
7015 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02007016
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007017 {
7018 // Tuning for Wi-Fi WMM S06
7019 if (pAd->CommonCfg.bWiFiTest &&
7020 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7021 Ac2Cfg.field.Aifsn -= 1;
7022
7023 // Tuning for TGn Wi-Fi 5.2.32
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007024 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007025 if (STA_TGN_WIFI_ON(pAd) &&
7026 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7027 {
7028 Ac0Cfg.field.Aifsn = 3;
7029 Ac2Cfg.field.AcTxop = 5;
7030 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007031
7032#ifdef RT30xx
7033 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7034 {
7035 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
7036 Ac2Cfg.field.Aifsn = 5;
7037 }
7038#endif // RT30xx //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007039 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007040
7041 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7042 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7043 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7044 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7045
7046//#ifdef WIFI_TEST
7047 if (pAd->CommonCfg.bWiFiTest)
7048 {
7049 if (Ac3Cfg.field.AcTxop == 102)
7050 {
7051 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7052 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7053 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7054 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7055 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7056 } /* End of if */
7057 }
7058//#endif // WIFI_TEST //
7059
7060 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7061 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7062 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7063 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7064
7065
7066 //========================================================
7067 // DMA Register has a copy too.
7068 //========================================================
7069 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7070 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7071 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7072
7073 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7074 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7075 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7076
7077 CwminCsr.word = 0;
7078 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7079 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7080 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02007081
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02007082 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02007083
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007084 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7085
7086 CwmaxCsr.word = 0;
7087 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7088 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7089 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7090 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7091 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7092
7093 AifsnCsr.word = 0;
7094 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7095 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7096 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02007097
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007098 {
7099 // Tuning for Wi-Fi WMM S06
7100 if (pAd->CommonCfg.bWiFiTest &&
7101 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7102 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7103
7104 // Tuning for TGn Wi-Fi 5.2.32
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007105 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007106 if (STA_TGN_WIFI_ON(pAd) &&
7107 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7108 {
7109 AifsnCsr.field.Aifsn0 = 3;
7110 AifsnCsr.field.Aifsn2 = 7;
7111 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007112#ifdef RT2870
7113 if (INFRA_ON(pAd))
7114 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7115#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007116 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007117
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02007118 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007119#ifdef RT30xx
7120 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7121 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7122#endif // RT30xx //
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02007123
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007124 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7125
7126 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7127 if (!ADHOC_ON(pAd))
7128 {
7129 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7130 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7131 pEdcaParm->Aifsn[0],
7132 pEdcaParm->Cwmin[0],
7133 pEdcaParm->Cwmax[0],
7134 pEdcaParm->Txop[0]<<5,
7135 pEdcaParm->bACM[0]));
7136 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7137 pEdcaParm->Aifsn[1],
7138 pEdcaParm->Cwmin[1],
7139 pEdcaParm->Cwmax[1],
7140 pEdcaParm->Txop[1]<<5,
7141 pEdcaParm->bACM[1]));
7142 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7143 pEdcaParm->Aifsn[2],
7144 pEdcaParm->Cwmin[2],
7145 pEdcaParm->Cwmax[2],
7146 pEdcaParm->Txop[2]<<5,
7147 pEdcaParm->bACM[2]));
7148 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7149 pEdcaParm->Aifsn[3],
7150 pEdcaParm->Cwmin[3],
7151 pEdcaParm->Cwmax[3],
7152 pEdcaParm->Txop[3]<<5,
7153 pEdcaParm->bACM[3]));
7154 }
7155 }
7156}
7157
7158/*
7159 ==========================================================================
7160 Description:
7161
7162 IRQL = PASSIVE_LEVEL
7163 IRQL = DISPATCH_LEVEL
7164
7165 ==========================================================================
7166 */
7167VOID AsicSetSlotTime(
7168 IN PRTMP_ADAPTER pAd,
7169 IN BOOLEAN bUseShortSlotTime)
7170{
7171 ULONG SlotTime;
7172 UINT32 RegValue = 0;
7173
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007174 if (pAd->CommonCfg.Channel > 14)
7175 bUseShortSlotTime = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007176
7177 if (bUseShortSlotTime)
7178 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7179 else
7180 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7181
7182 SlotTime = (bUseShortSlotTime)? 9 : 20;
7183
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007184 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007185#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007186 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7187 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007188 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007189 )
7190 {
7191 // In this case, we will think it is doing Wi-Fi test
7192 // And we will not set to short slot when bEnableTxBurst is TRUE.
7193 }
7194 else if (pAd->CommonCfg.bEnableTxBurst)
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007195#endif
7196#ifdef RT30xx
7197 if (pAd->CommonCfg.bEnableTxBurst)
7198#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007199 SlotTime = 9;
7200 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007201
7202 //
7203 // For some reasons, always set it to short slot time.
7204 //
7205 // ToDo: Should consider capability with 11B
7206 //
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02007207 if (pAd->StaCfg.BssType == BSS_ADHOC)
7208 SlotTime = 20;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007209
7210 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7211 RegValue = RegValue & 0xFFFFFF00;
7212
7213 RegValue |= SlotTime;
7214
7215 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7216}
7217
7218/*
7219 ========================================================================
7220 Description:
7221 Add Shared key information into ASIC.
7222 Update shared key, TxMic and RxMic to Asic Shared key table
7223 Update its cipherAlg to Asic Shared key Mode.
7224
7225 Return:
7226 ========================================================================
7227*/
7228VOID AsicAddSharedKeyEntry(
7229 IN PRTMP_ADAPTER pAd,
7230 IN UCHAR BssIndex,
7231 IN UCHAR KeyIdx,
7232 IN UCHAR CipherAlg,
7233 IN PUCHAR pKey,
7234 IN PUCHAR pTxMic,
7235 IN PUCHAR pRxMic)
7236{
7237 ULONG offset; //, csr0;
7238 SHAREDKEY_MODE_STRUC csr1;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007239#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007240 INT i;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007241#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007242
7243 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7244//============================================================================================
7245
7246 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7247 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7248 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]));
7249 if (pRxMic)
7250 {
7251 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7252 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7253 }
7254 if (pTxMic)
7255 {
7256 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7257 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7258 }
7259//============================================================================================
7260 //
7261 // fill key material - key + TX MIC + RX MIC
7262 //
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007263
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007264 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007265#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007266 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7267 {
7268 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7269 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007270#endif
7271#ifdef RT2870
7272 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7273#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007274 offset += MAX_LEN_OF_SHARE_KEY;
7275 if (pTxMic)
7276 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007277#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007278 for (i=0; i<8; i++)
7279 {
7280 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7281 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007282#endif
7283#ifdef RT2870
7284 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7285#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007286 }
7287
7288 offset += 8;
7289 if (pRxMic)
7290 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007291#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007292 for (i=0; i<8; i++)
7293 {
7294 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7295 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007296#endif
7297#ifdef RT2870
7298 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7299#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007300 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007301
7302
7303 //
7304 // Update cipher algorithm. WSTA always use BSS0
7305 //
7306 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7307 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7308 if ((BssIndex%2) == 0)
7309 {
7310 if (KeyIdx == 0)
7311 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7312 else if (KeyIdx == 1)
7313 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7314 else if (KeyIdx == 2)
7315 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7316 else
7317 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7318 }
7319 else
7320 {
7321 if (KeyIdx == 0)
7322 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7323 else if (KeyIdx == 1)
7324 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7325 else if (KeyIdx == 2)
7326 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7327 else
7328 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7329 }
7330 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7331 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7332
7333}
7334
7335// IRQL = DISPATCH_LEVEL
7336VOID AsicRemoveSharedKeyEntry(
7337 IN PRTMP_ADAPTER pAd,
7338 IN UCHAR BssIndex,
7339 IN UCHAR KeyIdx)
7340{
7341 //ULONG SecCsr0;
7342 SHAREDKEY_MODE_STRUC csr1;
7343
7344 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7345
7346 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7347 if ((BssIndex%2) == 0)
7348 {
7349 if (KeyIdx == 0)
7350 csr1.field.Bss0Key0CipherAlg = 0;
7351 else if (KeyIdx == 1)
7352 csr1.field.Bss0Key1CipherAlg = 0;
7353 else if (KeyIdx == 2)
7354 csr1.field.Bss0Key2CipherAlg = 0;
7355 else
7356 csr1.field.Bss0Key3CipherAlg = 0;
7357 }
7358 else
7359 {
7360 if (KeyIdx == 0)
7361 csr1.field.Bss1Key0CipherAlg = 0;
7362 else if (KeyIdx == 1)
7363 csr1.field.Bss1Key1CipherAlg = 0;
7364 else if (KeyIdx == 2)
7365 csr1.field.Bss1Key2CipherAlg = 0;
7366 else
7367 csr1.field.Bss1Key3CipherAlg = 0;
7368 }
7369 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7370 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7371 ASSERT(BssIndex < 4);
7372 ASSERT(KeyIdx < 4);
7373
7374}
7375
7376
7377VOID AsicUpdateWCIDAttribute(
7378 IN PRTMP_ADAPTER pAd,
7379 IN USHORT WCID,
7380 IN UCHAR BssIndex,
7381 IN UCHAR CipherAlg,
7382 IN BOOLEAN bUsePairewiseKeyTable)
7383{
7384 ULONG WCIDAttri = 0, offset;
7385
7386 //
7387 // Update WCID attribute.
7388 // Only TxKey could update WCID attribute.
7389 //
7390 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7391 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7392 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7393}
7394
7395VOID AsicUpdateWCIDIVEIV(
7396 IN PRTMP_ADAPTER pAd,
7397 IN USHORT WCID,
7398 IN ULONG uIV,
7399 IN ULONG uEIV)
7400{
7401 ULONG offset;
7402
7403 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7404
7405 RTMP_IO_WRITE32(pAd, offset, uIV);
7406 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7407}
7408
7409VOID AsicUpdateRxWCIDTable(
7410 IN PRTMP_ADAPTER pAd,
7411 IN USHORT WCID,
7412 IN PUCHAR pAddr)
7413{
7414 ULONG offset;
7415 ULONG Addr;
7416
7417 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7418 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7419 RTMP_IO_WRITE32(pAd, offset, Addr);
7420 Addr = pAddr[4] + (pAddr[5] << 8);
7421 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7422}
7423
7424
7425/*
7426 ========================================================================
7427
7428 Routine Description:
7429 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7430
7431 Arguments:
7432 pAd Pointer to our adapter
7433 WCID WCID Entry number.
7434 BssIndex BSSID index, station or none multiple BSSID support
7435 this value should be 0.
7436 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7437 pCipherKey Pointer to Cipher Key.
7438 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7439 otherwise PairewiseKey table
7440 bTxKey This is the transmit key if enabled.
7441
7442 Return Value:
7443 None
7444
7445 Note:
7446 This routine will set the relative key stuff to Asic including WCID attribute,
7447 Cipher Key, Cipher algorithm and IV/EIV.
7448
7449 IV/EIV will be update if this CipherKey is the transmission key because
7450 ASIC will base on IV's KeyID value to select Cipher Key.
7451
7452 If bTxKey sets to FALSE, this is not the TX key, but it could be
7453 RX key
7454
7455 For AP mode bTxKey must be always set to TRUE.
7456 ========================================================================
7457*/
7458VOID AsicAddKeyEntry(
7459 IN PRTMP_ADAPTER pAd,
7460 IN USHORT WCID,
7461 IN UCHAR BssIndex,
7462 IN UCHAR KeyIdx,
7463 IN PCIPHER_KEY pCipherKey,
7464 IN BOOLEAN bUsePairewiseKeyTable,
7465 IN BOOLEAN bTxKey)
7466{
7467 ULONG offset;
7468 UCHAR IV4 = 0;
7469 PUCHAR pKey = pCipherKey->Key;
7470 PUCHAR pTxMic = pCipherKey->TxMic;
7471 PUCHAR pRxMic = pCipherKey->RxMic;
7472 PUCHAR pTxtsc = pCipherKey->TxTsc;
7473 UCHAR CipherAlg = pCipherKey->CipherAlg;
7474 SHAREDKEY_MODE_STRUC csr1;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007475#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007476 UCHAR i;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007477#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007478
7479 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7480 //
7481 // 1.) decide key table offset
7482 //
7483 if (bUsePairewiseKeyTable)
7484 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7485 else
7486 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7487
7488 //
7489 // 2.) Set Key to Asic
7490 //
7491 //for (i = 0; i < KeyLen; i++)
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007492#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007493 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7494 {
7495 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7496 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007497#endif
7498#ifdef RT2870
7499 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7500#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007501 offset += MAX_LEN_OF_PEER_KEY;
7502
7503 //
7504 // 3.) Set MIC key if available
7505 //
7506 if (pTxMic)
7507 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007508#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007509 for (i = 0; i < 8; i++)
7510 {
7511 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7512 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007513#endif
7514#ifdef RT2870
7515 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7516#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007517 }
7518 offset += LEN_TKIP_TXMICK;
7519
7520 if (pRxMic)
7521 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007522#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007523 for (i = 0; i < 8; i++)
7524 {
7525 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7526 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007527#endif
7528#ifdef RT2870
7529 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7530#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007531 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007532
7533
7534 //
7535 // 4.) Modify IV/EIV if needs
7536 // This will force Asic to use this key ID by setting IV.
7537 //
7538 if (bTxKey)
7539 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007540#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007541 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7542 //
7543 // Write IV
7544 //
7545 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7546 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7547 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7548
7549 IV4 = (KeyIdx << 6);
7550 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7551 IV4 |= 0x20; // turn on extension bit means EIV existence
7552
7553 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7554
7555 //
7556 // Write EIV
7557 //
7558 offset += 4;
7559 for (i = 0; i < 4; i++)
7560 {
7561 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7562 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007563
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007564#endif
7565#ifdef RT2870
7566 UINT32 tmpVal;
7567
7568 //
7569 // Write IV
7570 //
7571 IV4 = (KeyIdx << 6);
7572 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7573 IV4 |= 0x20; // turn on extension bit means EIV existence
7574
7575 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7576 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7577
7578 //
7579 // Write EIV
7580 //
7581 offset += 4;
7582 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7583#endif // RT2870 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007584 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7585 }
7586
7587 if (!bUsePairewiseKeyTable)
7588 {
7589 //
7590 // Only update the shared key security mode
7591 //
7592 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7593 if ((BssIndex % 2) == 0)
7594 {
7595 if (KeyIdx == 0)
7596 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7597 else if (KeyIdx == 1)
7598 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7599 else if (KeyIdx == 2)
7600 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7601 else
7602 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7603 }
7604 else
7605 {
7606 if (KeyIdx == 0)
7607 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7608 else if (KeyIdx == 1)
7609 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7610 else if (KeyIdx == 2)
7611 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7612 else
7613 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7614 }
7615 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7616 }
7617
7618 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7619}
7620
7621
7622/*
7623 ========================================================================
7624 Description:
7625 Add Pair-wise key material into ASIC.
7626 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7627
7628 Return:
7629 ========================================================================
7630*/
7631VOID AsicAddPairwiseKeyEntry(
7632 IN PRTMP_ADAPTER pAd,
7633 IN PUCHAR pAddr,
7634 IN UCHAR WCID,
7635 IN CIPHER_KEY *pCipherKey)
7636{
7637 INT i;
7638 ULONG offset;
7639 PUCHAR pKey = pCipherKey->Key;
7640 PUCHAR pTxMic = pCipherKey->TxMic;
7641 PUCHAR pRxMic = pCipherKey->RxMic;
7642#ifdef DBG
7643 UCHAR CipherAlg = pCipherKey->CipherAlg;
7644#endif // DBG //
7645
7646 // EKEY
7647 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007648#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007649 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7650 {
7651 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7652 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007653#endif
7654#ifdef RT2870
7655 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7656#endif // RT2870 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007657 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7658 {
7659 UINT32 Value;
7660 RTMP_IO_READ32(pAd, offset + i, &Value);
7661 }
7662
7663 offset += MAX_LEN_OF_PEER_KEY;
7664
7665 // MIC KEY
7666 if (pTxMic)
7667 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007668#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007669 for (i=0; i<8; i++)
7670 {
7671 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7672 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007673#endif
7674#ifdef RT2870
7675 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7676#endif // RT2870 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007677 }
7678 offset += 8;
7679 if (pRxMic)
7680 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007681#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007682 for (i=0; i<8; i++)
7683 {
7684 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7685 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007686#endif
7687#ifdef RT2870
7688 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7689#endif // RT2870 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007690 }
7691
7692 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7693 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7694 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]));
7695 if (pRxMic)
7696 {
7697 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7698 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7699 }
7700 if (pTxMic)
7701 {
7702 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7703 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7704 }
7705}
7706/*
7707 ========================================================================
7708 Description:
7709 Remove Pair-wise key material from ASIC.
7710
7711 Return:
7712 ========================================================================
7713*/
7714VOID AsicRemovePairwiseKeyEntry(
7715 IN PRTMP_ADAPTER pAd,
7716 IN UCHAR BssIdx,
7717 IN UCHAR Wcid)
7718{
7719 ULONG WCIDAttri;
7720 USHORT offset;
7721
7722 // re-set the entry's WCID attribute as OPEN-NONE.
7723 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7724 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7725 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7726}
7727
7728BOOLEAN AsicSendCommandToMcu(
7729 IN PRTMP_ADAPTER pAd,
7730 IN UCHAR Command,
7731 IN UCHAR Token,
7732 IN UCHAR Arg0,
7733 IN UCHAR Arg1)
7734{
7735 HOST_CMD_CSR_STRUC H2MCmd;
7736 H2M_MAILBOX_STRUC H2MMailbox;
7737 ULONG i = 0;
Bartlomiej Zolnierkiewicz063f22a2009-04-26 16:04:50 +02007738
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007739 do
7740 {
7741 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7742 if (H2MMailbox.field.Owner == 0)
7743 break;
7744
7745 RTMPusecDelay(2);
7746 } while(i++ < 100);
7747
Roel Kluinf991a652009-05-13 20:37:54 +02007748 if (i > 100)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007749 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007750 {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007751#ifdef RT2860
Adam McDanieled291e82009-02-23 08:01:07 -07007752 UINT32 Data;
7753
7754 // Reset DMA
7755 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7756 Data |= 0x2;
7757 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7758
7759 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7760 // Reset DMA/CPU ring index
7761 RTMPRingCleanUp(pAd, QID_AC_BK);
7762 RTMPRingCleanUp(pAd, QID_AC_BE);
7763 RTMPRingCleanUp(pAd, QID_AC_VI);
7764 RTMPRingCleanUp(pAd, QID_AC_VO);
7765 RTMPRingCleanUp(pAd, QID_HCCA);
7766 RTMPRingCleanUp(pAd, QID_MGMT);
7767 RTMPRingCleanUp(pAd, QID_RX);
7768
7769 // Clear Reset
7770 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7771 Data &= 0xfffffffd;
7772 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007773#endif /* RT2860 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007774 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7775 }
Adam McDanieled291e82009-02-23 08:01:07 -07007776 //return FALSE;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007777#ifdef RT2870
7778 return FALSE;
7779#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007780 }
7781
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007782 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7783 H2MMailbox.field.CmdToken = Token;
7784 H2MMailbox.field.HighByte = Arg1;
7785 H2MMailbox.field.LowByte = Arg0;
7786 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7787
7788 H2MCmd.word = 0;
7789 H2MCmd.field.HostCommand = Command;
7790 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7791
7792 if (Command != 0x80)
7793 {
7794 }
7795
7796 return TRUE;
7797}
7798
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007799#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007800BOOLEAN AsicCheckCommanOk(
7801 IN PRTMP_ADAPTER pAd,
7802 IN UCHAR Command)
7803{
7804 UINT32 CmdStatus = 0, CID = 0, i;
7805 UINT32 ThisCIDMask = 0;
7806
7807 i = 0;
7808 do
7809 {
7810 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7811 // Find where the command is. Because this is randomly specified by firmware.
7812 if ((CID & CID0MASK) == Command)
7813 {
7814 ThisCIDMask = CID0MASK;
7815 break;
7816 }
7817 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7818 {
7819 ThisCIDMask = CID1MASK;
7820 break;
7821 }
7822 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7823 {
7824 ThisCIDMask = CID2MASK;
7825 break;
7826 }
7827 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7828 {
7829 ThisCIDMask = CID3MASK;
7830 break;
7831 }
7832
7833 RTMPusecDelay(100);
7834 i++;
7835 }while (i < 200);
7836
7837 // Get CommandStatus Value
7838 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7839
7840 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7841 if (i < 200)
7842 {
7843 // If Status is 1, the comamnd is success.
7844 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7845 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7846 {
7847 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7848 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7849 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7850 return TRUE;
7851 }
7852 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7853 }
7854 else
7855 {
7856 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7857 }
7858 // Clear Command and Status.
7859 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7860 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7861
7862 return FALSE;
7863}
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02007864#endif /* RT8260 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007865
7866/*
7867 ========================================================================
7868
7869 Routine Description:
7870 Verify the support rate for different PHY type
7871
7872 Arguments:
7873 pAd Pointer to our adapter
7874
7875 Return Value:
7876 None
7877
7878 IRQL = PASSIVE_LEVEL
7879
7880 ========================================================================
7881*/
7882VOID RTMPCheckRates(
7883 IN PRTMP_ADAPTER pAd,
7884 IN OUT UCHAR SupRate[],
7885 IN OUT UCHAR *SupRateLen)
7886{
7887 UCHAR RateIdx, i, j;
7888 UCHAR NewRate[12], NewRateLen;
7889
7890 NewRateLen = 0;
7891
7892 if (pAd->CommonCfg.PhyMode == PHY_11B)
7893 RateIdx = 4;
7894 else
7895 RateIdx = 12;
7896
7897 // Check for support rates exclude basic rate bit
7898 for (i = 0; i < *SupRateLen; i++)
7899 for (j = 0; j < RateIdx; j++)
7900 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7901 NewRate[NewRateLen++] = SupRate[i];
7902
7903 *SupRateLen = NewRateLen;
7904 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7905}
7906
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07007907BOOLEAN RTMPCheckChannel(
7908 IN PRTMP_ADAPTER pAd,
7909 IN UCHAR CentralChannel,
7910 IN UCHAR Channel)
7911{
7912 UCHAR k;
7913 UCHAR UpperChannel = 0, LowerChannel = 0;
7914 UCHAR NoEffectChannelinList = 0;
7915
7916 // Find upper and lower channel according to 40MHz current operation.
7917 if (CentralChannel < Channel)
7918 {
7919 UpperChannel = Channel;
7920 if (CentralChannel > 2)
7921 LowerChannel = CentralChannel - 2;
7922 else
7923 return FALSE;
7924 }
7925 else if (CentralChannel > Channel)
7926 {
7927 UpperChannel = CentralChannel + 2;
7928 LowerChannel = Channel;
7929 }
7930
7931 for (k = 0;k < pAd->ChannelListNum;k++)
7932 {
7933 if (pAd->ChannelList[k].Channel == UpperChannel)
7934 {
7935 NoEffectChannelinList ++;
7936 }
7937 if (pAd->ChannelList[k].Channel == LowerChannel)
7938 {
7939 NoEffectChannelinList ++;
7940 }
7941 }
7942
7943 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7944 if (NoEffectChannelinList == 2)
7945 return TRUE;
7946 else
7947 return FALSE;
7948}
7949
7950/*
7951 ========================================================================
7952
7953 Routine Description:
7954 Verify the support rate for HT phy type
7955
7956 Arguments:
7957 pAd Pointer to our adapter
7958
7959 Return Value:
7960 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7961
7962 IRQL = PASSIVE_LEVEL
7963
7964 ========================================================================
7965*/
7966BOOLEAN RTMPCheckHt(
7967 IN PRTMP_ADAPTER pAd,
7968 IN UCHAR Wcid,
7969 IN HT_CAPABILITY_IE *pHtCapability,
7970 IN ADD_HT_INFO_IE *pAddHtInfo)
7971{
7972 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7973 return FALSE;
7974
7975 // If use AMSDU, set flag.
7976 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7977 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7978 // Save Peer Capability
7979 if (pHtCapability->HtCapInfo.ShortGIfor20)
7980 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7981 if (pHtCapability->HtCapInfo.ShortGIfor40)
7982 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7983 if (pHtCapability->HtCapInfo.TxSTBC)
7984 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7985 if (pHtCapability->HtCapInfo.RxSTBC)
7986 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7987 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7988 {
7989 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7990 }
7991
7992 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7993 {
7994 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7995 }
7996
7997 // Will check ChannelWidth for MCSSet[4] below
7998 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7999 switch (pAd->CommonCfg.RxStream)
8000 {
8001 case 1:
8002 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8003 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
8004 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8005 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8006 break;
8007 case 2:
8008 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8009 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8010 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8011 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8012 break;
8013 case 3:
8014 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8015 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8016 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
8017 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8018 break;
8019 }
8020
8021 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
8022
8023 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
8024 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
8025 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
8026
8027 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
8028
8029 // Send Assoc Req with my HT capability.
8030 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
8031 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
8032 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
8033 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
8034 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
8035 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
8036 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
8037 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
8038 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8039 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8040 if (pAd->CommonCfg.bRdg)
8041 {
8042 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8043 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8044 }
8045
8046 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8047 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8048
8049 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8050 return TRUE;
8051}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008052
8053/*
8054 ========================================================================
8055
8056 Routine Description:
8057 Verify the support rate for different PHY type
8058
8059 Arguments:
8060 pAd Pointer to our adapter
8061
8062 Return Value:
8063 None
8064
8065 IRQL = PASSIVE_LEVEL
8066
8067 ========================================================================
8068*/
8069VOID RTMPUpdateMlmeRate(
8070 IN PRTMP_ADAPTER pAd)
8071{
8072 UCHAR MinimumRate;
8073 UCHAR ProperMlmeRate; //= RATE_54;
8074 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8075 BOOLEAN bMatch = FALSE;
8076
8077 switch (pAd->CommonCfg.PhyMode)
8078 {
8079 case PHY_11B:
8080 ProperMlmeRate = RATE_11;
8081 MinimumRate = RATE_1;
8082 break;
8083 case PHY_11BG_MIXED:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008084 case PHY_11ABGN_MIXED:
8085 case PHY_11BGN_MIXED:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008086 if ((pAd->MlmeAux.SupRateLen == 4) &&
8087 (pAd->MlmeAux.ExtRateLen == 0))
8088 // B only AP
8089 ProperMlmeRate = RATE_11;
8090 else
8091 ProperMlmeRate = RATE_24;
8092
8093 if (pAd->MlmeAux.Channel <= 14)
8094 MinimumRate = RATE_1;
8095 else
8096 MinimumRate = RATE_6;
8097 break;
8098 case PHY_11A:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008099 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8100 case PHY_11GN_MIXED:
8101 case PHY_11AGN_MIXED:
8102 case PHY_11AN_MIXED:
8103 case PHY_11N_5G:
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008104 ProperMlmeRate = RATE_24;
8105 MinimumRate = RATE_6;
8106 break;
8107 case PHY_11ABG_MIXED:
8108 ProperMlmeRate = RATE_24;
8109 if (pAd->MlmeAux.Channel <= 14)
8110 MinimumRate = RATE_1;
8111 else
8112 MinimumRate = RATE_6;
8113 break;
8114 default: // error
8115 ProperMlmeRate = RATE_1;
8116 MinimumRate = RATE_1;
8117 break;
8118 }
8119
8120 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8121 {
8122 for (j = 0; j < RateIdx; j++)
8123 {
8124 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8125 {
8126 if (j == ProperMlmeRate)
8127 {
8128 bMatch = TRUE;
8129 break;
8130 }
8131 }
8132 }
8133
8134 if (bMatch)
8135 break;
8136 }
8137
8138 if (bMatch == FALSE)
8139 {
8140 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8141 {
8142 for (j = 0; j < RateIdx; j++)
8143 {
8144 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8145 {
8146 if (j == ProperMlmeRate)
8147 {
8148 bMatch = TRUE;
8149 break;
8150 }
8151 }
8152 }
8153
8154 if (bMatch)
8155 break;
8156 }
8157 }
8158
8159 if (bMatch == FALSE)
8160 {
8161 ProperMlmeRate = MinimumRate;
8162 }
8163
8164 pAd->CommonCfg.MlmeRate = MinimumRate;
8165 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8166 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8167 {
8168 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8169 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8170 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8171 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8172 }
8173 else
8174 {
8175 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8176 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8177 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8178 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8179 }
8180
8181 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8182}
8183
8184CHAR RTMPMaxRssi(
8185 IN PRTMP_ADAPTER pAd,
8186 IN CHAR Rssi0,
8187 IN CHAR Rssi1,
8188 IN CHAR Rssi2)
8189{
8190 CHAR larger = -127;
8191
8192 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8193 {
8194 larger = Rssi0;
8195 }
8196
8197 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8198 {
8199 larger = max(Rssi0, Rssi1);
8200 }
8201
8202 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8203 {
8204 larger = max(larger, Rssi2);
8205 }
8206
8207 if (larger == -127)
8208 larger = 0;
8209
8210 return larger;
8211}
8212
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008213#ifdef RT30xx
8214// Antenna divesity use GPIO3 and EESK pin for control
8215// Antenna and EEPROM access are both using EESK pin,
8216// Therefor we should avoid accessing EESK at the same time
8217// Then restore antenna after EEPROM access
8218VOID AsicSetRxAnt(
8219 IN PRTMP_ADAPTER pAd,
8220 IN UCHAR Ant)
8221{
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008222 UINT32 Value;
8223 UINT32 x;
8224
8225 if ((pAd->EepromAccess) ||
8226 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8227 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8228 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8229 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8230 {
8231 return;
8232 }
8233
8234 // the antenna selection is through firmware and MAC register(GPIO3)
8235 if (Ant == 0)
8236 {
8237 // Main antenna
8238 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8239 x |= (EESK);
8240 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8241
8242 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8243 Value &= ~(0x0808);
8244 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8245 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8246 }
8247 else
8248 {
8249 // Aux antenna
8250 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8251 x &= ~(EESK);
8252 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8253
8254 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8255 Value &= ~(0x0808);
8256 Value |= 0x08;
8257 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8258 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8259 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008260}
8261#endif /* RT30xx */
8262
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008263/*
8264 ========================================================================
8265 Routine Description:
8266 Periodic evaluate antenna link status
8267
8268 Arguments:
8269 pAd - Adapter pointer
8270
8271 Return Value:
8272 None
8273
8274 ========================================================================
8275*/
8276VOID AsicEvaluateRxAnt(
8277 IN PRTMP_ADAPTER pAd)
8278{
8279 UCHAR BBPR3 = 0;
8280
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008281#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008282 {
8283 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8284 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8285 fRTMP_ADAPTER_RADIO_OFF |
8286 fRTMP_ADAPTER_NIC_NOT_EXIST |
8287 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8288 return;
8289
8290 if (pAd->StaCfg.Psm == PWR_SAVE)
8291 return;
8292 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008293
8294 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8295 BBPR3 &= (~0x18);
8296 if(pAd->Antenna.field.RxPath == 3)
8297 {
8298 BBPR3 |= (0x10);
8299 }
8300 else if(pAd->Antenna.field.RxPath == 2)
8301 {
8302 BBPR3 |= (0x8);
8303 }
8304 else if(pAd->Antenna.field.RxPath == 1)
8305 {
8306 BBPR3 |= (0x0);
8307 }
8308 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02008309
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008310#ifdef RT2860
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008311 pAd->StaCfg.BBPR3 = BBPR3;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008312#endif
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008313#endif /* RT30xx */
8314#ifdef RT30xx
8315 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8316 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8317 fRTMP_ADAPTER_RADIO_OFF |
8318 fRTMP_ADAPTER_NIC_NOT_EXIST |
8319 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
8320 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008321 || (pAd->EepromAccess)
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008322 )
8323 return;
8324
8325
8326 {
8327 //if (pAd->StaCfg.Psm == PWR_SAVE)
8328 // return;
8329 }
8330
8331 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8332 // one is antenna diversity:there is only one antenna can rx and tx
8333 // the other is failed antenna remove:two physical antenna can rx and tx
8334 if (pAd->NicConfig2.field.AntDiversity)
8335 {
8336 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8337 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8338
8339 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8340
8341 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8342 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8343 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8344
8345 // a one-shot timer to end the evalution
8346 // dynamic adjust antenna evaluation period according to the traffic
8347 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8348 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8349 else
8350 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8351 }
8352 else
8353 {
8354 if (pAd->StaCfg.Psm == PWR_SAVE)
8355 return;
8356
8357 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8358 BBPR3 &= (~0x18);
8359 if(pAd->Antenna.field.RxPath == 3)
8360 {
8361 BBPR3 |= (0x10);
8362 }
8363 else if(pAd->Antenna.field.RxPath == 2)
8364 {
8365 BBPR3 |= (0x8);
8366 }
8367 else if(pAd->Antenna.field.RxPath == 1)
8368 {
8369 BBPR3 |= (0x0);
8370 }
8371 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8372 }
8373#endif /* RT30xx */
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02008374
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008375 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8376 )
8377 {
8378 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8379 pAd->RalinkCounters.OneSecTxRetryOkCount +
8380 pAd->RalinkCounters.OneSecTxFailCount;
8381
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008382 // dynamic adjust antenna evaluation period according to the traffic
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008383 if (TxTotalCnt > 50)
8384 {
8385 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8386 pAd->Mlme.bLowThroughput = FALSE;
8387 }
8388 else
8389 {
8390 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8391 pAd->Mlme.bLowThroughput = TRUE;
8392 }
8393 }
8394}
8395
8396/*
8397 ========================================================================
8398 Routine Description:
8399 After evaluation, check antenna link status
8400
8401 Arguments:
8402 pAd - Adapter pointer
8403
8404 Return Value:
8405 None
8406
8407 ========================================================================
8408*/
8409VOID AsicRxAntEvalTimeout(
8410 IN PVOID SystemSpecific1,
8411 IN PVOID FunctionContext,
8412 IN PVOID SystemSpecific2,
8413 IN PVOID SystemSpecific3)
8414{
8415 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008416 UCHAR BBPR3 = 0;
8417 CHAR larger = -127, rssi0, rssi1, rssi2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008418
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008419#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008420 {
8421 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8422 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8423 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8424 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8425 return;
8426
8427 if (pAd->StaCfg.Psm == PWR_SAVE)
8428 return;
8429
8430
8431 // if the traffic is low, use average rssi as the criteria
8432 if (pAd->Mlme.bLowThroughput == TRUE)
8433 {
8434 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8435 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8436 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8437 }
8438 else
8439 {
8440 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8441 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8442 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8443 }
8444
8445 if(pAd->Antenna.field.RxPath == 3)
8446 {
8447 larger = max(rssi0, rssi1);
8448
8449 if (larger > (rssi2 + 20))
8450 pAd->Mlme.RealRxPath = 2;
8451 else
8452 pAd->Mlme.RealRxPath = 3;
8453 }
8454 else if(pAd->Antenna.field.RxPath == 2)
8455 {
8456 if (rssi0 > (rssi1 + 20))
8457 pAd->Mlme.RealRxPath = 1;
8458 else
8459 pAd->Mlme.RealRxPath = 2;
8460 }
8461
8462 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8463 BBPR3 &= (~0x18);
8464 if(pAd->Mlme.RealRxPath == 3)
8465 {
8466 BBPR3 |= (0x10);
8467 }
8468 else if(pAd->Mlme.RealRxPath == 2)
8469 {
8470 BBPR3 |= (0x8);
8471 }
8472 else if(pAd->Mlme.RealRxPath == 1)
8473 {
8474 BBPR3 |= (0x0);
8475 }
8476 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008477#ifdef RT2860
Mark Einonbdc0a172009-03-13 23:28:15 +00008478 pAd->StaCfg.BBPR3 = BBPR3;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008479#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008480 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008481#endif /* RT30xx */
8482#ifdef RT30xx
8483 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8484 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8485 fRTMP_ADAPTER_RADIO_OFF |
8486 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8487 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8488#ifdef RT30xx
8489 || (pAd->EepromAccess)
8490#endif // RT30xx //
8491 )
8492 return;
8493
8494 {
8495 //if (pAd->StaCfg.Psm == PWR_SAVE)
8496 // return;
8497
8498 if (pAd->NicConfig2.field.AntDiversity)
8499 {
8500 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8501 {
8502 UCHAR temp;
8503
8504 //
8505 // select PrimaryRxAntPair
8506 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8507 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8508 //
8509 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8510 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8511 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8512
8513 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8514 pAd->RxAnt.EvaluateStableCnt = 0;
8515 }
8516 else
8517 {
8518 // if the evaluated antenna is not better than original, switch back to original antenna
8519 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8520 pAd->RxAnt.EvaluateStableCnt ++;
8521 }
8522
8523 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8524
8525 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8526 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8527 }
8528 else
8529 {
8530 if (pAd->StaCfg.Psm == PWR_SAVE)
8531 return;
8532
8533 // if the traffic is low, use average rssi as the criteria
8534 if (pAd->Mlme.bLowThroughput == TRUE)
8535 {
8536 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8537 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8538 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8539 }
8540 else
8541 {
8542 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8543 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8544 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8545 }
8546
8547 if(pAd->Antenna.field.RxPath == 3)
8548 {
8549 larger = max(rssi0, rssi1);
8550
8551 if (larger > (rssi2 + 20))
8552 pAd->Mlme.RealRxPath = 2;
8553 else
8554 pAd->Mlme.RealRxPath = 3;
8555 }
8556 else if(pAd->Antenna.field.RxPath == 2)
8557 {
8558 if (rssi0 > (rssi1 + 20))
8559 pAd->Mlme.RealRxPath = 1;
8560 else
8561 pAd->Mlme.RealRxPath = 2;
8562 }
8563
8564 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8565 BBPR3 &= (~0x18);
8566 if(pAd->Mlme.RealRxPath == 3)
8567 {
8568 BBPR3 |= (0x10);
8569 }
8570 else if(pAd->Mlme.RealRxPath == 2)
8571 {
8572 BBPR3 |= (0x8);
8573 }
8574 else if(pAd->Mlme.RealRxPath == 1)
8575 {
8576 BBPR3 |= (0x0);
8577 }
8578 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8579 }
8580 }
8581#endif /* RT30xx */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008582}
8583
8584
8585
8586VOID APSDPeriodicExec(
8587 IN PVOID SystemSpecific1,
8588 IN PVOID FunctionContext,
8589 IN PVOID SystemSpecific2,
8590 IN PVOID SystemSpecific3)
8591{
8592 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8593
8594 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8595 return;
8596
8597 pAd->CommonCfg.TriggerTimerCount++;
8598
8599}
8600
8601/*
8602 ========================================================================
8603 Routine Description:
8604 Set/reset MAC registers according to bPiggyBack parameter
8605
8606 Arguments:
8607 pAd - Adapter pointer
8608 bPiggyBack - Enable / Disable Piggy-Back
8609
8610 Return Value:
8611 None
8612
8613 ========================================================================
8614*/
8615VOID RTMPSetPiggyBack(
8616 IN PRTMP_ADAPTER pAd,
8617 IN BOOLEAN bPiggyBack)
8618{
8619 TX_LINK_CFG_STRUC TxLinkCfg;
8620
8621 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8622
8623 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8624 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8625}
8626
8627/*
8628 ========================================================================
8629 Routine Description:
8630 check if this entry need to switch rate automatically
8631
8632 Arguments:
8633 pAd
8634 pEntry
8635
8636 Return Value:
8637 TURE
8638 FALSE
8639
8640 ========================================================================
8641*/
8642BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8643 IN PRTMP_ADAPTER pAd,
8644 IN PMAC_TABLE_ENTRY pEntry)
8645{
8646 BOOLEAN result = TRUE;
8647
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008648 {
8649 // only associated STA counts
8650 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8651 {
8652 result = pAd->StaCfg.bAutoTxRateSwitch;
8653 }
8654 else
8655 result = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008656 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008657
8658 return result;
8659}
8660
8661
8662BOOLEAN RTMPAutoRateSwitchCheck(
8663 IN PRTMP_ADAPTER pAd)
8664{
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02008665 if (pAd->StaCfg.bAutoTxRateSwitch)
8666 return TRUE;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02008667
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008668 return FALSE;
8669}
8670
8671
8672/*
8673 ========================================================================
8674 Routine Description:
8675 check if this entry need to fix tx legacy rate
8676
8677 Arguments:
8678 pAd
8679 pEntry
8680
8681 Return Value:
8682 TURE
8683 FALSE
8684
8685 ========================================================================
8686*/
8687UCHAR RTMPStaFixedTxMode(
8688 IN PRTMP_ADAPTER pAd,
8689 IN PMAC_TABLE_ENTRY pEntry)
8690{
8691 UCHAR tx_mode = FIXED_TXMODE_HT;
8692
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02008693 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008694
8695 return tx_mode;
8696}
8697
8698/*
8699 ========================================================================
8700 Routine Description:
8701 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8702
8703 Arguments:
8704 pAd
8705 pEntry
8706
8707 Return Value:
8708 TURE
8709 FALSE
8710
8711 ========================================================================
8712*/
8713VOID RTMPUpdateLegacyTxSetting(
8714 UCHAR fixed_tx_mode,
8715 PMAC_TABLE_ENTRY pEntry)
8716{
8717 HTTRANSMIT_SETTING TransmitSetting;
8718
8719 if (fixed_tx_mode == FIXED_TXMODE_HT)
8720 return;
8721
8722 TransmitSetting.word = 0;
8723
8724 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8725 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8726
8727 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8728 {
8729 TransmitSetting.field.MODE = MODE_CCK;
8730 // CCK mode allow MCS 0~3
8731 if (TransmitSetting.field.MCS > MCS_3)
8732 TransmitSetting.field.MCS = MCS_3;
8733 }
8734 else
8735 {
8736 TransmitSetting.field.MODE = MODE_OFDM;
8737 // OFDM mode allow MCS 0~7
8738 if (TransmitSetting.field.MCS > MCS_7)
8739 TransmitSetting.field.MCS = MCS_7;
8740 }
8741
8742 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8743 {
8744 pEntry->HTPhyMode.word = TransmitSetting.word;
8745 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8746 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8747 }
8748}
8749
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008750/*
8751 ==========================================================================
8752 Description:
8753 dynamic tune BBP R66 to find a balance between sensibility and
8754 noise isolation
8755
8756 IRQL = DISPATCH_LEVEL
8757
8758 ==========================================================================
8759 */
8760VOID AsicStaBbpTuning(
8761 IN PRTMP_ADAPTER pAd)
8762{
8763 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8764 CHAR Rssi;
8765
8766 // 2860C did not support Fase CCA, therefore can't tune
8767 if (pAd->MACVersion == 0x28600100)
8768 return;
8769
8770 //
8771 // work as a STA
8772 //
8773 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8774 return;
8775
8776 if ((pAd->OpMode == OPMODE_STA)
8777 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8778 )
8779 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008780#ifdef RT2860
Mark Einonbdc0a172009-03-13 23:28:15 +00008781 && (pAd->bPCIclkOff == FALSE))
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008782#endif
8783#ifdef RT2870
8784 )
8785#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008786 {
8787 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8788 R66 = OrigR66Value;
8789
8790 if (pAd->Antenna.field.RxPath > 1)
8791 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8792 else
8793 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8794
8795 if (pAd->LatchRfRegs.Channel <= 14)
8796 { //BG band
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008797#ifdef RT2870
8798 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8799 // Otherwise, it will have some throughput side effect when low RSSI
8800#ifndef RT30xx
8801 if (IS_RT3070(pAd))
8802#endif
8803#ifdef RT30xx
8804 if (IS_RT30xx(pAd))
8805#endif
8806 {
8807 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8808 {
8809 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8810 if (OrigR66Value != R66)
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008811 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008812 }
8813 else
8814 {
8815 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8816 if (OrigR66Value != R66)
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008817 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008818 }
8819 }
8820 else
8821#endif // RT2870 //
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008822 {
8823 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8824 {
8825 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8826 if (OrigR66Value != R66)
8827 {
8828 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8829 }
8830 }
8831 else
8832 {
8833 R66 = 0x2E + GET_LNA_GAIN(pAd);
8834 if (OrigR66Value != R66)
8835 {
8836 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8837 }
8838 }
8839 }
8840 }
8841 else
8842 { //A band
8843 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8844 {
8845 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8846 {
8847 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8848 if (OrigR66Value != R66)
8849 {
8850 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8851 }
8852 }
8853 else
8854 {
8855 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8856 if (OrigR66Value != R66)
8857 {
8858 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8859 }
8860 }
8861 }
8862 else
8863 {
8864 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8865 {
8866 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8867 if (OrigR66Value != R66)
8868 {
8869 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8870 }
8871 }
8872 else
8873 {
8874 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8875 if (OrigR66Value != R66)
8876 {
8877 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8878 }
8879 }
8880 }
8881 }
8882
8883
8884 }
8885}
Adam McDanieled291e82009-02-23 08:01:07 -07008886
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008887#ifdef RT2860
Adam McDanieled291e82009-02-23 08:01:07 -07008888VOID AsicResetFromDMABusy(
8889 IN PRTMP_ADAPTER pAd)
8890{
8891 UINT32 Data;
8892 BOOLEAN bCtrl = FALSE;
8893
8894 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8895
8896 // Be sure restore link control value so we can write register.
8897 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8898 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8899 {
8900 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8901 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8902 RTMPusecDelay(6000);
8903 pAd->bPCIclkOff = FALSE;
8904 bCtrl = TRUE;
8905 }
8906 // Reset DMA
8907 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8908 Data |= 0x2;
8909 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8910
8911 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8912 // Reset DMA/CPU ring index
8913 RTMPRingCleanUp(pAd, QID_AC_BK);
8914 RTMPRingCleanUp(pAd, QID_AC_BE);
8915 RTMPRingCleanUp(pAd, QID_AC_VI);
8916 RTMPRingCleanUp(pAd, QID_AC_VO);
8917 RTMPRingCleanUp(pAd, QID_HCCA);
8918 RTMPRingCleanUp(pAd, QID_MGMT);
8919 RTMPRingCleanUp(pAd, QID_RX);
8920
8921 // Clear Reset
8922 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8923 Data &= 0xfffffffd;
8924 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8925
8926 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8927 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8928 RTMPPCIeLinkCtrlSetting(pAd, 3);
8929
8930 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8931 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8932 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8933}
8934
8935VOID AsicResetBBP(
8936 IN PRTMP_ADAPTER pAd)
8937{
8938 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8939
8940 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8941 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8942 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8943
8944 // After hard-reset BBP, initialize all BBP values.
8945 NICRestoreBBPValue(pAd);
8946 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8947}
8948
8949VOID AsicResetMAC(
8950 IN PRTMP_ADAPTER pAd)
8951{
8952 ULONG Data;
8953
8954 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8955 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8956 Data |= 0x4;
8957 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8958 Data &= 0xfffffffb;
8959 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8960
8961 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8962}
8963
8964VOID AsicResetPBF(
8965 IN PRTMP_ADAPTER pAd)
8966{
8967 ULONG Value1, Value2;
8968 ULONG Data;
8969
8970 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8971 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8972
8973 Value2 &= 0xff;
8974 // sum should be equals to 0xff, which is the total buffer size.
8975 if ((Value1 + Value2) < 0xff)
8976 {
8977 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8978 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8979 Data |= 0x8;
8980 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8981 Data &= 0xfffffff7;
8982 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8983
8984 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8985 }
8986}
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02008987#endif /* RT2860 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07008988
8989VOID RTMPSetAGCInitValue(
8990 IN PRTMP_ADAPTER pAd,
8991 IN UCHAR BandWidth)
8992{
8993 UCHAR R66 = 0x30;
8994
8995 if (pAd->LatchRfRegs.Channel <= 14)
8996 { // BG band
8997 R66 = 0x2E + GET_LNA_GAIN(pAd);
8998 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8999 }
9000 else
9001 { //A band
9002 if (BandWidth == BW_20)
9003 {
9004 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
9005 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9006 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07009007 else
9008 {
9009 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
9010 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
9011 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07009012 }
9013
9014}
9015
9016VOID AsicTurnOffRFClk(
9017 IN PRTMP_ADAPTER pAd,
9018 IN UCHAR Channel)
9019{
9020
9021 // RF R2 bit 18 = 0
9022 UINT32 R1 = 0, R2 = 0, R3 = 0;
9023 UCHAR index;
9024 RTMP_RF_REGS *RFRegTable;
9025
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02009026 // The RF programming sequence is difference between 3xxx and 2xxx
9027 if (IS_RT3090(pAd))
9028 {
9029 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02009030 return;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02009031 }
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02009032
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07009033 RFRegTable = RF2850RegTable;
9034
9035 switch (pAd->RfIcType)
9036 {
9037 case RFIC_2820:
9038 case RFIC_2850:
9039 case RFIC_2720:
9040 case RFIC_2750:
9041
9042 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9043 {
9044 if (Channel == RFRegTable[index].Channel)
9045 {
9046 R1 = RFRegTable[index].R1 & 0xffffdfff;
9047 R2 = RFRegTable[index].R2 & 0xfffbffff;
9048 R3 = RFRegTable[index].R3 & 0xfff3ffff;
9049
9050 RTMP_RF_IO_WRITE32(pAd, R1);
9051 RTMP_RF_IO_WRITE32(pAd, R2);
9052
9053 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
9054 // Set RF R2 bit18=0, R3 bit[18:19]=0
9055 //if (pAd->StaCfg.bRadio == FALSE)
9056 if (1)
9057 {
9058 RTMP_RF_IO_WRITE32(pAd, R3);
9059
9060 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
9061 Channel, pAd->RfIcType, R2, R3));
9062 }
9063 else
9064 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
9065 Channel, pAd->RfIcType, R2));
9066 break;
9067 }
9068 }
9069 break;
9070
9071 default:
9072 break;
9073 }
9074}
9075
9076
9077VOID AsicTurnOnRFClk(
9078 IN PRTMP_ADAPTER pAd,
9079 IN UCHAR Channel)
9080{
9081
9082 // RF R2 bit 18 = 0
9083 UINT32 R1 = 0, R2 = 0, R3 = 0;
9084 UCHAR index;
9085 RTMP_RF_REGS *RFRegTable;
9086
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02009087 // The RF programming sequence is difference between 3xxx and 2xxx
9088 if (IS_RT3090(pAd))
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02009089 return;
9090
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07009091 RFRegTable = RF2850RegTable;
9092
9093 switch (pAd->RfIcType)
9094 {
9095 case RFIC_2820:
9096 case RFIC_2850:
9097 case RFIC_2720:
9098 case RFIC_2750:
9099
9100 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9101 {
9102 if (Channel == RFRegTable[index].Channel)
9103 {
9104 R3 = pAd->LatchRfRegs.R3;
9105 R3 &= 0xfff3ffff;
9106 R3 |= 0x00080000;
9107 RTMP_RF_IO_WRITE32(pAd, R3);
9108
9109 R1 = RFRegTable[index].R1;
9110 RTMP_RF_IO_WRITE32(pAd, R1);
9111
9112 R2 = RFRegTable[index].R2;
9113 if (pAd->Antenna.field.TxPath == 1)
9114 {
9115 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
9116 }
9117
9118 if (pAd->Antenna.field.RxPath == 2)
9119 {
9120 R2 |= 0x40; // write 1 to off Rxpath.
9121 }
9122 else if (pAd->Antenna.field.RxPath == 1)
9123 {
9124 R2 |= 0x20040; // write 1 to off RxPath
9125 }
9126 RTMP_RF_IO_WRITE32(pAd, R2);
9127
9128 break;
9129 }
9130 }
9131 break;
9132
9133 default:
9134 break;
9135 }
9136
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02009137#ifndef RT30xx
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07009138 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
9139 Channel,
9140 pAd->RfIcType,
9141 R2));
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02009142#endif
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07009143}
9144