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