blob: 8cd8f53ed0e63abaac01317f239d4fa75d6a1609 [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
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080042u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070043
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080044u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
45u8 RSN_OUI[] = { 0x00, 0x0f, 0xac };
46u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
47u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
48u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 };
49u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 };
50u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c };
51u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
52u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070053
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080054u8 RateSwitchTable[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080055/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
56 0x11, 0x00, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080057 0x00, 0x00, 0, 40, 101,
58 0x01, 0x00, 1, 40, 50,
59 0x02, 0x00, 2, 35, 45,
60 0x03, 0x00, 3, 20, 45,
61 0x04, 0x21, 0, 30, 50,
62 0x05, 0x21, 1, 20, 50,
63 0x06, 0x21, 2, 20, 50,
64 0x07, 0x21, 3, 15, 50,
65 0x08, 0x21, 4, 15, 30,
66 0x09, 0x21, 5, 10, 25,
67 0x0a, 0x21, 6, 8, 25,
68 0x0b, 0x21, 7, 8, 25,
69 0x0c, 0x20, 12, 15, 30,
70 0x0d, 0x20, 13, 8, 20,
71 0x0e, 0x20, 14, 8, 20,
72 0x0f, 0x20, 15, 8, 25,
73 0x10, 0x22, 15, 8, 25,
74 0x11, 0x00, 0, 0, 0,
75 0x12, 0x00, 0, 0, 0,
76 0x13, 0x00, 0, 0, 0,
77 0x14, 0x00, 0, 0, 0,
78 0x15, 0x00, 0, 0, 0,
79 0x16, 0x00, 0, 0, 0,
80 0x17, 0x00, 0, 0, 0,
81 0x18, 0x00, 0, 0, 0,
82 0x19, 0x00, 0, 0, 0,
83 0x1a, 0x00, 0, 0, 0,
84 0x1b, 0x00, 0, 0, 0,
85 0x1c, 0x00, 0, 0, 0,
86 0x1d, 0x00, 0, 0, 0,
87 0x1e, 0x00, 0, 0, 0,
88 0x1f, 0x00, 0, 0, 0,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070089};
90
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080091u8 RateSwitchTable11B[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080092/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
93 0x04, 0x03, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080094 0x00, 0x00, 0, 40, 101,
95 0x01, 0x00, 1, 40, 50,
96 0x02, 0x00, 2, 35, 45,
97 0x03, 0x00, 3, 20, 45,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -070098};
99
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800100u8 RateSwitchTable11BG[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800101/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
102 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800103 0x00, 0x00, 0, 40, 101,
104 0x01, 0x00, 1, 40, 50,
105 0x02, 0x00, 2, 35, 45,
106 0x03, 0x00, 3, 20, 45,
107 0x04, 0x10, 2, 20, 35,
108 0x05, 0x10, 3, 16, 35,
109 0x06, 0x10, 4, 10, 25,
110 0x07, 0x10, 5, 16, 25,
111 0x08, 0x10, 6, 10, 25,
112 0x09, 0x10, 7, 10, 13,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700113};
114
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800115u8 RateSwitchTable11G[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800116/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
117 0x08, 0x00, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800118 0x00, 0x10, 0, 20, 101,
119 0x01, 0x10, 1, 20, 35,
120 0x02, 0x10, 2, 20, 35,
121 0x03, 0x10, 3, 16, 35,
122 0x04, 0x10, 4, 10, 25,
123 0x05, 0x10, 5, 16, 25,
124 0x06, 0x10, 6, 10, 25,
125 0x07, 0x10, 7, 10, 13,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700126};
127
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800128u8 RateSwitchTable11N1S[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800129/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
130 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800131 0x00, 0x00, 0, 40, 101,
132 0x01, 0x00, 1, 40, 50,
133 0x02, 0x00, 2, 25, 45,
134 0x03, 0x21, 0, 20, 35,
135 0x04, 0x21, 1, 20, 35,
136 0x05, 0x21, 2, 20, 35,
137 0x06, 0x21, 3, 15, 35,
138 0x07, 0x21, 4, 15, 30,
139 0x08, 0x21, 5, 10, 25,
140 0x09, 0x21, 6, 8, 14,
141 0x0a, 0x21, 7, 8, 14,
142 0x0b, 0x23, 7, 8, 14,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700143};
144
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800145u8 RateSwitchTable11N2S[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800146/* 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) */
147 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800148 0x00, 0x00, 0, 40, 101,
149 0x01, 0x00, 1, 40, 50,
150 0x02, 0x00, 2, 25, 45,
151 0x03, 0x21, 0, 20, 35,
152 0x04, 0x21, 1, 20, 35,
153 0x05, 0x21, 2, 20, 35,
154 0x06, 0x21, 3, 15, 35,
155 0x07, 0x21, 4, 15, 30,
156 0x08, 0x20, 11, 15, 30,
157 0x09, 0x20, 12, 15, 30,
158 0x0a, 0x20, 13, 8, 20,
159 0x0b, 0x20, 14, 8, 20,
160 0x0c, 0x20, 15, 8, 25,
161 0x0d, 0x22, 15, 8, 15,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700162};
163
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800164u8 RateSwitchTable11N3S[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800165/* 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) */
166 0x0b, 0x00, 0, 0, 0, /* 0x0a, 0x00, 0, 0, 0, // Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800167 0x00, 0x21, 0, 30, 101,
168 0x01, 0x21, 1, 20, 50,
169 0x02, 0x21, 2, 20, 50,
170 0x03, 0x21, 3, 15, 50,
171 0x04, 0x21, 4, 15, 30,
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800172 0x05, 0x20, 11, 15, 30, /* Required by System-Alan @ 20080812 */
173 0x06, 0x20, 12, 15, 30, /* 0x05, 0x20, 12, 15, 30, */
174 0x07, 0x20, 13, 8, 20, /* 0x06, 0x20, 13, 8, 20, */
175 0x08, 0x20, 14, 8, 20, /* 0x07, 0x20, 14, 8, 20, */
176 0x09, 0x20, 15, 8, 25, /* 0x08, 0x20, 15, 8, 25, */
177 0x0a, 0x22, 15, 8, 25, /* 0x09, 0x22, 15, 8, 25, */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700178};
179
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800180u8 RateSwitchTable11N2SForABand[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800181/* 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) */
182 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800183 0x00, 0x21, 0, 30, 101,
184 0x01, 0x21, 1, 20, 50,
185 0x02, 0x21, 2, 20, 50,
186 0x03, 0x21, 3, 15, 50,
187 0x04, 0x21, 4, 15, 30,
188 0x05, 0x21, 5, 15, 30,
189 0x06, 0x20, 12, 15, 30,
190 0x07, 0x20, 13, 8, 20,
191 0x08, 0x20, 14, 8, 20,
192 0x09, 0x20, 15, 8, 25,
193 0x0a, 0x22, 15, 8, 25,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700194};
195
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800196u8 RateSwitchTable11N3SForABand[] = { /* 3*3 */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800197/* 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) */
198 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800199 0x00, 0x21, 0, 30, 101,
200 0x01, 0x21, 1, 20, 50,
201 0x02, 0x21, 2, 20, 50,
202 0x03, 0x21, 3, 15, 50,
203 0x04, 0x21, 4, 15, 30,
204 0x05, 0x21, 5, 15, 30,
205 0x06, 0x20, 12, 15, 30,
206 0x07, 0x20, 13, 8, 20,
207 0x08, 0x20, 14, 8, 20,
208 0x09, 0x20, 15, 8, 25,
209 0x0a, 0x22, 15, 8, 25,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700210};
211
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800212u8 RateSwitchTable11BGN1S[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800213/* 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) */
214 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800215 0x00, 0x00, 0, 40, 101,
216 0x01, 0x00, 1, 40, 50,
217 0x02, 0x00, 2, 25, 45,
218 0x03, 0x21, 0, 20, 35,
219 0x04, 0x21, 1, 20, 35,
220 0x05, 0x21, 2, 20, 35,
221 0x06, 0x21, 3, 15, 35,
222 0x07, 0x21, 4, 15, 30,
223 0x08, 0x21, 5, 10, 25,
224 0x09, 0x21, 6, 8, 14,
225 0x0a, 0x21, 7, 8, 14,
226 0x0b, 0x23, 7, 8, 14,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700227};
228
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800229u8 RateSwitchTable11BGN2S[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800230/* 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) */
231 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800232 0x00, 0x00, 0, 40, 101,
233 0x01, 0x00, 1, 40, 50,
234 0x02, 0x00, 2, 25, 45,
235 0x03, 0x21, 0, 20, 35,
236 0x04, 0x21, 1, 20, 35,
237 0x05, 0x21, 2, 20, 35,
238 0x06, 0x21, 3, 15, 35,
239 0x07, 0x21, 4, 15, 30,
240 0x08, 0x20, 11, 15, 30,
241 0x09, 0x20, 12, 15, 30,
242 0x0a, 0x20, 13, 8, 20,
243 0x0b, 0x20, 14, 8, 20,
244 0x0c, 0x20, 15, 8, 25,
245 0x0d, 0x22, 15, 8, 15,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700246};
247
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800248u8 RateSwitchTable11BGN3S[] = { /* 3*3 */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800249/* 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) */
250 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */
251 0x00, 0x21, 0, 30, 101, /*50 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800252 0x01, 0x21, 1, 20, 50,
253 0x02, 0x21, 2, 20, 50,
254 0x03, 0x21, 3, 20, 50,
255 0x04, 0x21, 4, 15, 50,
256 0x05, 0x20, 20, 15, 30,
257 0x06, 0x20, 21, 8, 20,
258 0x07, 0x20, 22, 8, 20,
259 0x08, 0x20, 23, 8, 25,
260 0x09, 0x22, 23, 8, 25,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700261};
262
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800263u8 RateSwitchTable11BGN2SForABand[] = {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800264/* 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) */
265 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
266 0x00, 0x21, 0, 30, 101, /*50 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800267 0x01, 0x21, 1, 20, 50,
268 0x02, 0x21, 2, 20, 50,
269 0x03, 0x21, 3, 15, 50,
270 0x04, 0x21, 4, 15, 30,
271 0x05, 0x21, 5, 15, 30,
272 0x06, 0x20, 12, 15, 30,
273 0x07, 0x20, 13, 8, 20,
274 0x08, 0x20, 14, 8, 20,
275 0x09, 0x20, 15, 8, 25,
276 0x0a, 0x22, 15, 8, 25,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700277};
278
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800279u8 RateSwitchTable11BGN3SForABand[] = { /* 3*3 */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800280/* 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) */
281 0x0c, 0x09, 0, 0, 0, /* Initial used item after association */
282 0x00, 0x21, 0, 30, 101, /*50 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800283 0x01, 0x21, 1, 20, 50,
284 0x02, 0x21, 2, 20, 50,
285 0x03, 0x21, 3, 15, 50,
286 0x04, 0x21, 4, 15, 30,
287 0x05, 0x21, 5, 15, 30,
288 0x06, 0x21, 12, 15, 30,
289 0x07, 0x20, 20, 15, 30,
290 0x08, 0x20, 21, 8, 20,
291 0x09, 0x20, 22, 8, 20,
292 0x0a, 0x20, 23, 8, 25,
293 0x0b, 0x22, 23, 8, 25,
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700294};
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700295
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800296extern u8 OfdmRateToRxwiMCS[];
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800297/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */
298/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800299unsigned long BasicRateMask[12] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800300 { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ ,
3010xfffff00f /* 11 */ ,
302 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ ,
303 0xfffff0ff /* 18 */ ,
304 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ ,
305 0xffffffff /* 54 */
306};
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700307
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800308u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
309u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700310
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800311/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */
312/* this value, then it's quaranteed capable of operating in 36 mbps TX rate in */
313/* clean environment. */
314/* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800315char RssiSafeLevelForTxRate[] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800316 { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700317
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800318u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
319u16 RateIdTo500Kbps[] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800320 { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700321
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800322u8 SsidIe = IE_SSID;
323u8 SupRateIe = IE_SUPP_RATES;
324u8 ExtRateIe = IE_EXT_SUPP_RATES;
325u8 HtCapIe = IE_HT_CAP;
326u8 AddHtInfoIe = IE_ADD_HT;
327u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET;
328u8 ErpIe = IE_ERP;
329u8 DsIe = IE_DS_PARM;
330u8 TimIe = IE_TIM;
331u8 WpaIe = IE_WPA;
332u8 Wpa2Ie = IE_WPA2;
333u8 IbssIe = IE_IBSS_PARM;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700334
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800335extern u8 WPA_OUI[];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700336
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800337u8 SES_OUI[] = { 0x00, 0x90, 0x4c };
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700338
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800339u8 ZeroSsid[32] =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800340 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3410x00, 0x00, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00
344};
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700345
346/*
347 ==========================================================================
348 Description:
349 initialize the MLME task and its data structure (queue, spinlock,
350 timer, state machines).
351
352 IRQL = PASSIVE_LEVEL
353
354 Return:
355 always return NDIS_STATUS_SUCCESS
356
357 ==========================================================================
358*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800359int MlmeInit(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700360{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800361 int Status = NDIS_STATUS_SUCCESS;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700362
363 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
364
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800365 do {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700366 Status = MlmeQueueInit(&pAd->Mlme.Queue);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800367 if (Status != NDIS_STATUS_SUCCESS)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700368 break;
369
370 pAd->Mlme.bRunning = FALSE;
371 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
372
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700373 {
374 BssTableInit(&pAd->ScanTab);
375
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800376 /* init STA state machines */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800377 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine,
378 pAd->Mlme.AssocFunc);
379 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine,
380 pAd->Mlme.AuthFunc);
381 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine,
382 pAd->Mlme.AuthRspFunc);
383 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine,
384 pAd->Mlme.SyncFunc);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700385
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800386 /* Since we are using switch/case to implement it, the init is different from the above */
387 /* state machine init */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700388 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
389 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700390
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800391 WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine,
392 pAd->Mlme.WpaFunc);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200393
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800394 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine,
395 pAd->Mlme.ActFunc);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700396
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800397 /* Init mlme periodic timer */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800398 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer,
399 GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700400
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800401 /* Set mlme periodic timer */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700402 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
403
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800404 /* software-based RX Antenna diversity */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800405 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer,
406 GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd,
407 FALSE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700408
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700409 {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200410#ifdef RTMP_PCI_SUPPORT
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800411 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800412 /* only PCIe cards need these two timers */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800413 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer,
414 GET_TIMER_FUNCTION
415 (PsPollWakeExec), pAd, FALSE);
416 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer,
417 GET_TIMER_FUNCTION(RadioOnExec),
418 pAd, FALSE);
419 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800420#endif /* RTMP_PCI_SUPPORT // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200421
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800422 RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer,
423 GET_TIMER_FUNCTION(LinkDownExec), pAd,
424 FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200425
426#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800427 RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer,
428 GET_TIMER_FUNCTION
429 (RtmpUsbStaAsicForceWakeupTimeout), pAd,
430 FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200431 pAd->Mlme.AutoWakeupTimerRunning = FALSE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800432#endif /* RTMP_MAC_USB // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700433 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200434
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700435 } while (FALSE);
436
437 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
438
439 return Status;
440}
441
442/*
443 ==========================================================================
444 Description:
445 main loop of the MLME
446 Pre:
447 Mlme has to be initialized, and there are something inside the queue
448 Note:
449 This function is invoked from MPSetInformation and MPReceive;
450 This task guarantee only one MlmeHandler will run.
451
452 IRQL = DISPATCH_LEVEL
453
454 ==========================================================================
455 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800456void MlmeHandler(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700457{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800458 struct rt_mlme_queue_elem *Elem = NULL;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700459
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800460 /* Only accept MLME and Frame from peer side, no other (control/data) frame should */
461 /* get into this state machine */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700462
463 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800464 if (pAd->Mlme.bRunning) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700465 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
466 return;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800467 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700468 pAd->Mlme.bRunning = TRUE;
469 }
470 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
471
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800472 while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700473 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800474 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
475 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
476 DBGPRINT(RT_DEBUG_TRACE,
477 ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n",
478 pAd->Mlme.Queue.Num));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700479 break;
480 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800481 /*From message type, determine which state machine I should drive */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800482 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200483#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800484 if (Elem->MsgType == MT2_RESET_CONF) {
485 DBGPRINT_RAW(RT_DEBUG_TRACE,
486 ("!!! reset MLME state machine !!!\n"));
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +0200487 MlmeRestartStateMachine(pAd);
488 Elem->Occupied = FALSE;
489 Elem->MsgLen = 0;
490 continue;
491 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800492#endif /* RTMP_MAC_USB // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700493
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800494 /* if dequeue success */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800495 switch (Elem->Machine) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800496 /* STA state machines */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800497 case ASSOC_STATE_MACHINE:
498 StateMachinePerformAction(pAd,
499 &pAd->Mlme.
500 AssocMachine, Elem);
501 break;
502 case AUTH_STATE_MACHINE:
503 StateMachinePerformAction(pAd,
504 &pAd->Mlme.
505 AuthMachine, Elem);
506 break;
507 case AUTH_RSP_STATE_MACHINE:
508 StateMachinePerformAction(pAd,
509 &pAd->Mlme.
510 AuthRspMachine, Elem);
511 break;
512 case SYNC_STATE_MACHINE:
513 StateMachinePerformAction(pAd,
514 &pAd->Mlme.
515 SyncMachine, Elem);
516 break;
517 case MLME_CNTL_STATE_MACHINE:
518 MlmeCntlMachinePerformAction(pAd,
519 &pAd->Mlme.
520 CntlMachine, Elem);
521 break;
522 case WPA_PSK_STATE_MACHINE:
523 StateMachinePerformAction(pAd,
524 &pAd->Mlme.
525 WpaPskMachine, Elem);
526 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200527
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800528 case ACTION_STATE_MACHINE:
529 StateMachinePerformAction(pAd,
530 &pAd->Mlme.ActMachine,
531 Elem);
532 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200533
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800534 case WPA_STATE_MACHINE:
535 StateMachinePerformAction(pAd,
536 &pAd->Mlme.WpaMachine,
537 Elem);
538 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200539
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800540 default:
541 DBGPRINT(RT_DEBUG_TRACE,
542 ("ERROR: Illegal machine %ld in MlmeHandler()\n",
543 Elem->Machine));
544 break;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800545 } /* end of switch */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700546
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800547 /* free MLME element */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700548 Elem->Occupied = FALSE;
549 Elem->MsgLen = 0;
550
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800551 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700552 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
553 }
554 }
555
556 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
557 pAd->Mlme.bRunning = FALSE;
558 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
559}
560
561/*
562 ==========================================================================
563 Description:
564 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
565 Parameters:
566 Adapter - NIC Adapter pointer
567 Post:
568 The MLME task will no longer work properly
569
570 IRQL = PASSIVE_LEVEL
571
572 ==========================================================================
573 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800574void MlmeHalt(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700575{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800576 BOOLEAN Cancelled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700577
578 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
579
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800580 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800581 /* disable BEACON generation and other BEACON related hardware timers */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700582 AsicDisableSync(pAd);
583 }
584
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700585 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800586 /* Cancel pending timers */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800587 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
588 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
589 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
590 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
591 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
592 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200593
594#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800595 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
596 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) {
597 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
598 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700599 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800600#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200601
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800602 RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200603
604#ifdef RTMP_MAC_USB
605 RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800606#endif /* RTMP_MAC_USB // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700607 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700608
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800609 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
610 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700611
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800612 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800613 struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200614
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800615 /* Set LED */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700616 RTMPSetLED(pAd, LED_HALT);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800617 RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200618#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800619 {
620 LED_CFG_STRUC LedCfg;
621 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
622 LedCfg.field.LedPolar = 0;
623 LedCfg.field.RLedMode = 0;
624 LedCfg.field.GLedMode = 0;
625 LedCfg.field.YLedMode = 0;
626 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
627 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800628#endif /* RTMP_MAC_USB // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200629
630 if (pChipOps->AsicHaltAction)
631 pChipOps->AsicHaltAction(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700632 }
633
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800634 RTMPusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700635
636 MlmeQueueDestroy(&pAd->Mlme.Queue);
637 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
638
639 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
640}
641
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800642void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700643{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800644 pAd->RalinkCounters.LastOneSecRxOkDataCnt =
645 pAd->RalinkCounters.OneSecRxOkDataCnt;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800646 /* clear all OneSecxxx counters. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700647 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
648 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
649 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
650 pAd->RalinkCounters.OneSecRxOkCnt = 0;
651 pAd->RalinkCounters.OneSecTxFailCount = 0;
652 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
653 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
654 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200655 pAd->RalinkCounters.OneSecReceivedByteCount = 0;
656 pAd->RalinkCounters.OneSecTransmittedByteCount = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700657
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800658 /* TODO: for debug only. to be removed */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700659 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
660 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
661 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
662 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
663 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
664 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
665 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
666 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
667 pAd->RalinkCounters.OneSecTxDoneCount = 0;
668 pAd->RalinkCounters.OneSecRxCount = 0;
669 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
670 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
671
672 return;
673}
674
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700675/*
676 ==========================================================================
677 Description:
678 This routine is executed periodically to -
679 1. Decide if it's a right time to turn on PwrMgmt bit of all
680 outgoiing frames
681 2. Calculate ChannelQuality based on statistics of the last
682 period, so that TX rate won't toggling very frequently between a
683 successful TX and a failed TX.
684 3. If the calculated ChannelQuality indicated current connection not
685 healthy, then a ROAMing attempt is tried here.
686
687 IRQL = DISPATCH_LEVEL
688
689 ==========================================================================
690 */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800691#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800692void MlmePeriodicExec(void *SystemSpecific1,
693 void *FunctionContext,
694 void *SystemSpecific2, void *SystemSpecific3)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700695{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800696 unsigned long TxTotalCnt;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800697 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700698
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200699#ifdef RTMP_MAC_PCI
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700700 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800701 /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */
702 /* Move code to here, because following code will return when radio is off */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800703 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) ==
704 0) && (pAd->StaCfg.bHardwareRadio == TRUE)
705 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
706 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
707 /*&&(pAd->bPCIclkOff == FALSE) */
708 ) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800709 u32 data = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700710
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800711 /* Read GPIO pin2 as Hardware controlled radio state */
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +0200712#ifndef RT3090
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200713 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800714#endif /* RT3090 // */
715/*KH(PCIE PS):Added based on Jane<-- */
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +0200716#ifdef RT3090
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800717/* Read GPIO pin2 as Hardware controlled radio state */
718/* We need to Read GPIO if HW said so no mater what advance power saving */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800719 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
720 &&
721 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
722 && (pAd->StaCfg.PSControl.field.EnablePSinIdle ==
723 TRUE)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800724 /* Want to make sure device goes to L0 state before reading register. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800725 RTMPPCIeLinkCtrlValueRestore(pAd, 0);
726 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
727 RTMPPCIeLinkCtrlSetting(pAd, 3);
728 } else
729 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800730#endif /* RT3090 // */
731/*KH(PCIE PS):Added based on Jane--> */
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +0200732
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800733 if (data & 0x04) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700734 pAd->StaCfg.bHwRadio = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800735 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700736 pAd->StaCfg.bHwRadio = FALSE;
737 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800738 if (pAd->StaCfg.bRadio !=
739 (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) {
740 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio
741 && pAd->StaCfg.bSwRadio);
742 if (pAd->StaCfg.bRadio == TRUE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700743 MlmeRadioOn(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800744 /* Update extra information */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700745 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800746 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700747 MlmeRadioOff(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800748 /* Update extra information */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700749 pAd->ExtraInfo = HW_RADIO_OFF;
750 }
751 }
752 }
753 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800754#endif /* RTMP_MAC_PCI // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700755
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800756 /* Do nothing if the driver is starting halt state. */
757 /* This might happen when timer already been fired before cancel timer with mlmehalt */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700758 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800759 fRTMP_ADAPTER_RADIO_OFF |
760 fRTMP_ADAPTER_RADIO_MEASUREMENT |
761 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700762 return;
763
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200764 RTMP_MLME_PRE_SANITY_CHECK(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700765
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700766 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800767 /* Do nothing if monitor mode is on */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700768 if (MONITOR_ON(pAd))
769 return;
770
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800771 if (pAd->Mlme.PeriodicRound & 0x1) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800772 /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700773 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800774 (STA_TGN_WIFI_ON(pAd)) &&
775 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
776 {
777 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
778 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
779 } else if ((STA_TGN_WIFI_ON(pAd)) &&
780 ((pAd->MACVersion & 0xffff) == 0x0101)) {
781 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
782 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
783 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700784 }
785 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700786
787 pAd->bUpdateBcnCntDone = FALSE;
788
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800789/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800790 pAd->Mlme.PeriodicRound++;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700791
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200792#ifdef RTMP_MAC_USB
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800793 /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +0200794 NICUpdateFifoStaCounters(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800795#endif /* RTMP_MAC_USB // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200796
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800797 /* execute every 500ms */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800798 if ((pAd->Mlme.PeriodicRound % 5 == 0)
799 && RTMPAutoRateSwitchCheck(pAd)
800 /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ )
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700801 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800802 /* perform dynamic tx rate switching based on past TX history */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700803 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800804 if ((OPSTATUS_TEST_FLAG
805 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
806 )
807 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700808 MlmeDynamicTxRateSwitching(pAd);
809 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700810 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800811 /* Normal 1 second Mlme PeriodicExec. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800812 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) {
813 pAd->Mlme.OneSecPeriodicRound++;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200814
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800815 /*ORIBATimerTimeout(pAd); */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700816
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800817 /* Media status changed, report to NDIS */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800818 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700819 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800820 if (OPSTATUS_TEST_FLAG
821 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
822 pAd->IndicateMediaState =
823 NdisMediaStateConnected;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700824 RTMP_IndicateMediaState(pAd);
825
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800826 } else {
827 pAd->IndicateMediaState =
828 NdisMediaStateDisconnected;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700829 RTMP_IndicateMediaState(pAd);
830 }
831 }
832
833 NdisGetSystemUpTime(&pAd->Mlme.Now32);
834
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800835 /* add the most up-to-date h/w raw counters into software variable, so that */
836 /* the dynamic tuning mechanism below are based on most up-to-date information */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700837 NICUpdateRawCounters(pAd);
838
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200839#ifdef RTMP_MAC_USB
840 RTUSBWatchDog(pAd);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800841#endif /* RTMP_MAC_USB // */
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +0200842
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800843 /* Need statistics after read counter. So put after NICUpdateRawCounters */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700844 ORIBATimerTimeout(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700845
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800846 /* if MGMT RING is full more than twice within 1 second, we consider there's */
847 /* a hardware problem stucking the TX path. In this case, try a hardware reset */
848 /* to recover the system */
849 /* if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */
850 /* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */
851 /* else */
852 /* pAd->RalinkCounters.MgmtRingFullCount = 0; */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200853
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800854 /* The time period for checking antenna is according to traffic */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200855 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800856 if (pAd->Mlme.bEnableAutoAntennaCheck) {
857 TxTotalCnt =
858 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
859 pAd->RalinkCounters.OneSecTxRetryOkCount +
860 pAd->RalinkCounters.OneSecTxFailCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700861
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800862 /* dynamic adjust antenna evaluation period according to the traffic */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800863 if (TxTotalCnt > 50) {
864 if (pAd->Mlme.OneSecPeriodicRound %
865 10 == 0) {
866 AsicEvaluateRxAnt(pAd);
867 }
868 } else {
869 if (pAd->Mlme.OneSecPeriodicRound % 3 ==
870 0) {
871 AsicEvaluateRxAnt(pAd);
872 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700873 }
874 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200875 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700876
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +0200877 STAMlmePeriodicExec(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700878
879 MlmeResetRalinkCounters(pAd);
880
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700881 {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200882#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800883 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
884 && (pAd->bPCIclkOff == FALSE))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800885#endif /* RTMP_MAC_PCI // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700886 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800887 /* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */
888 /* and sending CTS-to-self over and over. */
889 /* Software Patch Solution: */
890 /* 1. Polling debug state register 0x10F4 every one second. */
891 /* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */
892 /* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700893
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800894 u32 MacReg = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700895
896 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800897 if (((MacReg & 0x20000000) && (MacReg & 0x80))
898 || ((MacReg & 0x20000000)
899 && (MacReg & 0x20))) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700900 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
901 RTMPusecDelay(1);
902 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
903
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800904 DBGPRINT(RT_DEBUG_WARN,
905 ("Warning, MAC specific condition occurs \n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700906 }
907 }
908 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700909
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200910 RTMP_MLME_HANDLER(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700911 }
912
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700913 pAd->bUpdateBcnCntDone = FALSE;
914}
915
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700916/*
917 ==========================================================================
918 Validate SSID for connection try and rescan purpose
919 Valid SSID will have visible chars only.
920 The valid length is from 0 to 32.
921 IRQL = DISPATCH_LEVEL
922 ==========================================================================
923 */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800924BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700925{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800926 int index;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700927
928 if (SsidLen > MAX_LEN_OF_SSID)
929 return (FALSE);
930
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800931 /* Check each character value */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800932 for (index = 0; index < SsidLen; index++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700933 if (pSsid[index] < 0x20)
934 return (FALSE);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800935 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700936
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800937 /* All checked */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700938 return (TRUE);
939}
940
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800941void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd,
942 struct rt_mac_table_entry *pEntry,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800943 u8 ** ppTable,
944 u8 *pTableSize, u8 *pInitTxRateIdx)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700945{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800946 do {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800947 /* decide the rate table for tuning */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800948 if (pAd->CommonCfg.TxRateTableSize > 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700949 *ppTable = RateSwitchTable;
950 *pTableSize = RateSwitchTable[0];
951 *pInitTxRateIdx = RateSwitchTable[1];
952
953 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800954 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700955
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800956 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800957 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) { /* 11N 1S Adhoc */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700958 *ppTable = RateSwitchTable11N1S;
959 *pTableSize = RateSwitchTable11N1S[0];
960 *pInitTxRateIdx = RateSwitchTable11N1S[1];
961
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800962 } else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) { /* 11N 2S Adhoc */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800963 if (pAd->LatchRfRegs.Channel <= 14) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700964 *ppTable = RateSwitchTable11N2S;
965 *pTableSize = RateSwitchTable11N2S[0];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800966 *pInitTxRateIdx =
967 RateSwitchTable11N2S[1];
968 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700969 *ppTable = RateSwitchTable11N2SForABand;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800970 *pTableSize =
971 RateSwitchTable11N2SForABand[0];
972 *pInitTxRateIdx =
973 RateSwitchTable11N2SForABand[1];
974 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700975
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800976 } else if ((pEntry->RateLen == 4)
977 && (pEntry->HTCapability.MCSSet[0] == 0)
978 && (pEntry->HTCapability.MCSSet[1] == 0)
979 ) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700980 *ppTable = RateSwitchTable11B;
981 *pTableSize = RateSwitchTable11B[0];
982 *pInitTxRateIdx = RateSwitchTable11B[1];
983
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800984 } else if (pAd->LatchRfRegs.Channel <= 14) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700985 *ppTable = RateSwitchTable11BG;
986 *pTableSize = RateSwitchTable11BG[0];
987 *pInitTxRateIdx = RateSwitchTable11BG[1];
988
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800989 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -0700990 *ppTable = RateSwitchTable11G;
991 *pTableSize = RateSwitchTable11G[0];
992 *pInitTxRateIdx = RateSwitchTable11G[1];
993
994 }
995 break;
996 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800997 /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
998 /* ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
999 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11BGN 1S AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001000 *ppTable = RateSwitchTable11BGN1S;
1001 *pTableSize = RateSwitchTable11BGN1S[0];
1002 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1003
1004 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001005 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001006 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
1007 /* (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1008 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11BGN 2S AP */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001009 if (pAd->LatchRfRegs.Channel <= 14) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001010 *ppTable = RateSwitchTable11BGN2S;
1011 *pTableSize = RateSwitchTable11BGN2S[0];
1012 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1013
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001014 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001015 *ppTable = RateSwitchTable11BGN2SForABand;
1016 *pTableSize = RateSwitchTable11BGN2SForABand[0];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001017 *pInitTxRateIdx =
1018 RateSwitchTable11BGN2SForABand[1];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001019
1020 }
1021 break;
1022 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001023 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1024 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11N 1S AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001025 *ppTable = RateSwitchTable11N1S;
1026 *pTableSize = RateSwitchTable11N1S[0];
1027 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1028
1029 break;
1030 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001031 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1032 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11N 2S AP */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001033 if (pAd->LatchRfRegs.Channel <= 14) {
1034 *ppTable = RateSwitchTable11N2S;
1035 *pTableSize = RateSwitchTable11N2S[0];
1036 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1037 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001038 *ppTable = RateSwitchTable11N2SForABand;
1039 *pTableSize = RateSwitchTable11N2SForABand[0];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001040 *pInitTxRateIdx =
1041 RateSwitchTable11N2SForABand[1];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001042 }
1043
1044 break;
1045 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001046 /*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001047 if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode == PHY_11B)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001048 /*Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001049 /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001050 ) { /* B only AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001051 *ppTable = RateSwitchTable11B;
1052 *pTableSize = RateSwitchTable11B[0];
1053 *pInitTxRateIdx = RateSwitchTable11B[1];
1054
1055 break;
1056 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001057 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001058 if ((pEntry->RateLen > 8)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001059 && (pEntry->HTCapability.MCSSet[0] == 0)
1060 && (pEntry->HTCapability.MCSSet[1] == 0)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001061 ) { /* B/G mixed AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001062 *ppTable = RateSwitchTable11BG;
1063 *pTableSize = RateSwitchTable11BG[0];
1064 *pInitTxRateIdx = RateSwitchTable11BG[1];
1065
1066 break;
1067 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001068 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001069 if ((pEntry->RateLen == 8)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001070 && (pEntry->HTCapability.MCSSet[0] == 0)
1071 && (pEntry->HTCapability.MCSSet[1] == 0)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001072 ) { /* G only AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001073 *ppTable = RateSwitchTable11G;
1074 *pTableSize = RateSwitchTable11G[0];
1075 *pInitTxRateIdx = RateSwitchTable11G[1];
1076
1077 break;
1078 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001079
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001080 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001081 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1082 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) { /* Legacy mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001083 if (pAd->CommonCfg.MaxTxRate <= RATE_11) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001084 *ppTable = RateSwitchTable11B;
1085 *pTableSize = RateSwitchTable11B[0];
1086 *pInitTxRateIdx = RateSwitchTable11B[1];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001087 } else if ((pAd->CommonCfg.MaxTxRate > RATE_11)
1088 && (pAd->CommonCfg.MinTxRate >
1089 RATE_11)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001090 *ppTable = RateSwitchTable11G;
1091 *pTableSize = RateSwitchTable11G[0];
1092 *pInitTxRateIdx = RateSwitchTable11G[1];
1093
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001094 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001095 *ppTable = RateSwitchTable11BG;
1096 *pTableSize = RateSwitchTable11BG[0];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001097 *pInitTxRateIdx =
1098 RateSwitchTable11BG[1];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001099 }
1100 break;
1101 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001102 if (pAd->LatchRfRegs.Channel <= 14) {
1103 if (pAd->CommonCfg.TxStream == 1) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001104 *ppTable = RateSwitchTable11N1S;
1105 *pTableSize = RateSwitchTable11N1S[0];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001106 *pInitTxRateIdx =
1107 RateSwitchTable11N1S[1];
1108 DBGPRINT_RAW(RT_DEBUG_ERROR,
1109 ("DRS: unkown mode,default use 11N 1S AP \n"));
1110 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001111 *ppTable = RateSwitchTable11N2S;
1112 *pTableSize = RateSwitchTable11N2S[0];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001113 *pInitTxRateIdx =
1114 RateSwitchTable11N2S[1];
1115 DBGPRINT_RAW(RT_DEBUG_ERROR,
1116 ("DRS: unkown mode,default use 11N 2S AP \n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001117 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001118 } else {
1119 if (pAd->CommonCfg.TxStream == 1) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001120 *ppTable = RateSwitchTable11N1S;
1121 *pTableSize = RateSwitchTable11N1S[0];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001122 *pInitTxRateIdx =
1123 RateSwitchTable11N1S[1];
1124 DBGPRINT_RAW(RT_DEBUG_ERROR,
1125 ("DRS: unkown mode,default use 11N 1S AP \n"));
1126 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001127 *ppTable = RateSwitchTable11N2SForABand;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001128 *pTableSize =
1129 RateSwitchTable11N2SForABand[0];
1130 *pInitTxRateIdx =
1131 RateSwitchTable11N2SForABand[1];
1132 DBGPRINT_RAW(RT_DEBUG_ERROR,
1133 ("DRS: unkown mode,default use 11N 2S AP \n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001134 }
1135 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001136 DBGPRINT_RAW(RT_DEBUG_ERROR,
1137 ("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1138 pAd->StaActive.SupRateLen,
1139 pAd->StaActive.ExtRateLen,
1140 pAd->StaActive.SupportedPhyInfo.MCSSet[0],
1141 pAd->StaActive.SupportedPhyInfo.
1142 MCSSet[1]));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001143 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001144 } while (FALSE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001145}
1146
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001147void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001148{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001149 unsigned long TxTotalCnt;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001150 int i;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001151
1152 /*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001153 We return here in ATE mode, because the statistics
1154 that ATE need are not collected via this routine.
1155 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001156#if defined(RT305x)||defined(RT3070)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001157 /* request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001158 if (!pAd->CommonCfg.HighPowerPatchDisabled) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001159#ifdef RT3070
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001160 if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201)))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001161#endif /* RT3070 // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001162 {
1163 if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0)
1164 && (pAd->StaCfg.RssiSample.AvgRssi0 >
1165 (pAd->BbpRssiToDbmDelta - 35))) {
1166 RT30xxWriteRFRegister(pAd, RF_R27, 0x20);
1167 } else {
1168 RT30xxWriteRFRegister(pAd, RF_R27, 0x23);
1169 }
1170 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001171 }
1172#endif
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +02001173#ifdef PCIE_PS_SUPPORT
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001174/* don't perform idle-power-save mechanism within 3 min after driver initialization. */
1175/* This can make rebooter test more robust */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001176 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
1177 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
1178 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1179 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1180 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) {
1181 if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) {
1182 if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1183 TRUE) {
1184 DBGPRINT(RT_DEBUG_TRACE,
1185 ("%s\n", __func__));
1186 RT28xxPciAsicRadioOff(pAd,
1187 GUI_IDLE_POWER_SAVE,
1188 0);
1189 } else {
1190 AsicSendCommandToMcu(pAd, 0x30,
1191 PowerSafeCID, 0xff,
1192 0x2);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001193 /* Wait command success */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001194 AsicCheckCommanOk(pAd, PowerSafeCID);
1195 RTMP_SET_FLAG(pAd,
1196 fRTMP_ADAPTER_IDLE_RADIO_OFF);
1197 DBGPRINT(RT_DEBUG_TRACE,
1198 ("PSM - rt30xx Issue Sleep command)\n"));
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +02001199 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001200 } else if (pAd->Mlme.OneSecPeriodicRound > 180) {
1201 if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1202 TRUE) {
1203 DBGPRINT(RT_DEBUG_TRACE,
1204 ("%s\n", __func__));
1205 RT28xxPciAsicRadioOff(pAd,
1206 GUI_IDLE_POWER_SAVE,
1207 0);
1208 } else {
1209 AsicSendCommandToMcu(pAd, 0x30,
1210 PowerSafeCID, 0xff,
1211 0x02);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001212 /* Wait command success */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001213 AsicCheckCommanOk(pAd, PowerSafeCID);
1214 RTMP_SET_FLAG(pAd,
1215 fRTMP_ADAPTER_IDLE_RADIO_OFF);
1216 DBGPRINT(RT_DEBUG_TRACE,
1217 ("PSM - rt28xx Issue Sleep command)\n"));
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +02001218 }
1219 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001220 } else {
1221 DBGPRINT(RT_DEBUG_TRACE,
1222 ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1223 pAd->CommonCfg.SsidLen,
1224 pAd->CommonCfg.Ssid[0],
1225 pAd->CommonCfg.Ssid[1],
1226 pAd->CommonCfg.Ssid[2],
1227 pAd->CommonCfg.Ssid[3], pAd->MlmeAux.SsidLen,
1228 pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1],
1229 pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +02001230 }
1231 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001232#endif /* PCIE_PS_SUPPORT // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001233
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001234 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001235 /* WPA MIC error should block association attempt for 60 seconds */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001236 if (pAd->StaCfg.bBlockAssoc &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001237 RTMP_TIME_AFTER(pAd->Mlme.Now32,
1238 pAd->StaCfg.LastMicErrorTime +
1239 (60 * OS_HZ)))
1240 pAd->StaCfg.bBlockAssoc = FALSE;
1241 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001242
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001243 if ((pAd->PreMediaState != pAd->IndicateMediaState)
1244 && (pAd->CommonCfg.bWirelessEvent)) {
1245 if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1246 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1247 pAd->MacTab.Content[BSSID_WCID].
1248 Addr, BSS0, 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001249 }
1250 pAd->PreMediaState = pAd->IndicateMediaState;
1251 }
1252
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001253 if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) {
1254 } else {
1255 AsicStaBbpTuning(pAd);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001256 }
1257
1258 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001259 pAd->RalinkCounters.OneSecTxRetryOkCount +
1260 pAd->RalinkCounters.OneSecTxFailCount;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001261
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001262 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001263 /* update channel quality for Roaming and UI LinkQuality display */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001264 MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32);
1265 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001266 /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */
1267 /* Radio is currently in noisy environment */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001268 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001269 AsicAdjustTxPower(pAd);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001270
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001271 if (INFRA_ON(pAd)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001272
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001273 /* Is PSM bit consistent with user power management policy? */
1274 /* This is the only place that will set PSM bit ON. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001275 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001276 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001277
1278 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1279
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001280 if ((RTMP_TIME_AFTER
1281 (pAd->Mlme.Now32,
1282 pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ)))
1283 &&
1284 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1285 &&
1286 (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) <
1287 600))) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001288 RTMPSetAGCInitValue(pAd, BW_20);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001289 DBGPRINT(RT_DEBUG_TRACE,
1290 ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n",
1291 (0x2E + GET_LNA_GAIN(pAd))));
1292 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001293 /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */
1294 /* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001295 {
1296 if (pAd->CommonCfg.bAPSDCapable
1297 && pAd->CommonCfg.APEdcaParm.bAPSDCapable) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001298 /* When APSD is enabled, the period changes as 20 sec */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001299 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1300 RTMPSendNullFrame(pAd,
1301 pAd->CommonCfg.TxRate,
1302 TRUE);
1303 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001304 /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001305 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) {
1306 if (pAd->CommonCfg.bWmmCapable)
1307 RTMPSendNullFrame(pAd,
1308 pAd->
1309 CommonCfg.
1310 TxRate, TRUE);
1311 else
1312 RTMPSendNullFrame(pAd,
1313 pAd->
1314 CommonCfg.
1315 TxRate,
1316 FALSE);
1317 }
1318 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001319 }
1320
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001321 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) {
1322 DBGPRINT(RT_DEBUG_TRACE,
1323 ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n",
1324 pAd->RalinkCounters.BadCQIAutoRecoveryCount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001325
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001326 /* Lost AP, send disconnect & link down event */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001327 LinkDown(pAd, FALSE);
1328
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001329 RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL,
1330 0);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001331
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001332 /* RTMPPatchMacBbpBug(pAd); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001333 MlmeAutoReconnectLastSSID(pAd);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001334 } else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) {
1335 pAd->RalinkCounters.BadCQIAutoRecoveryCount++;
1336 DBGPRINT(RT_DEBUG_TRACE,
1337 ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n",
1338 pAd->RalinkCounters.BadCQIAutoRecoveryCount));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001339 MlmeAutoReconnectLastSSID(pAd);
1340 }
1341
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001342 if (pAd->StaCfg.bAutoRoaming) {
1343 BOOLEAN rv = FALSE;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001344 char dBmToRoam = pAd->StaCfg.dBmToRoam;
1345 char MaxRssi = RTMPMaxRssi(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001346 pAd->StaCfg.RssiSample.
1347 LastRssi0,
1348 pAd->StaCfg.RssiSample.
1349 LastRssi1,
1350 pAd->StaCfg.RssiSample.
1351 LastRssi2);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001352
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001353 /* Scanning, ignore Roaming */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001354 if (!RTMP_TEST_FLAG
1355 (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
1356 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1357 && (MaxRssi <= dBmToRoam)) {
1358 DBGPRINT(RT_DEBUG_TRACE,
1359 ("Rssi=%d, dBmToRoam=%d\n", MaxRssi,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001360 (char)dBmToRoam));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001361
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001362 /* Add auto seamless roaming */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001363 if (rv == FALSE)
1364 rv = MlmeCheckForFastRoaming(pAd);
1365
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001366 if (rv == FALSE) {
1367 if ((pAd->StaCfg.LastScanTime +
1368 10 * OS_HZ) < pAd->Mlme.Now32) {
1369 DBGPRINT(RT_DEBUG_TRACE,
1370 ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001371 pAd->StaCfg.ScanCnt = 2;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001372 pAd->StaCfg.LastScanTime =
1373 pAd->Mlme.Now32;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001374 MlmeAutoScan(pAd);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001375 }
1376 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001377 }
1378 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001379 } else if (ADHOC_ON(pAd)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001380 /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */
1381 /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */
1382 /* join later. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001383 if (RTMP_TIME_AFTER
1384 (pAd->Mlme.Now32,
1385 pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)
1386 && OPSTATUS_TEST_FLAG(pAd,
1387 fOP_STATUS_MEDIA_STATE_CONNECTED)) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001388 struct rt_mlme_start_req StartReq;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001389
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001390 DBGPRINT(RT_DEBUG_TRACE,
1391 ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001392 LinkDown(pAd, FALSE);
1393
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001394 StartParmFill(pAd, &StartReq,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001395 (char *) pAd->MlmeAux.Ssid,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001396 pAd->MlmeAux.SsidLen);
1397 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001398 sizeof(struct rt_mlme_start_req), &StartReq);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001399 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1400 }
1401
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001402 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001403 struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001404
1405 if (pEntry->ValidAsCLI == FALSE)
1406 continue;
1407
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001408 if (RTMP_TIME_AFTER
1409 (pAd->Mlme.Now32,
1410 pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1411 MacTableDeleteEntry(pAd, pEntry->Aid,
1412 pEntry->Addr);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001413 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001414 } else /* no INFRA nor ADHOC connection */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001415 {
1416
1417 if (pAd->StaCfg.bScanReqIsFromWebUI &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001418 RTMP_TIME_BEFORE(pAd->Mlme.Now32,
1419 pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001420 goto SKIP_AUTO_SCAN_CONN;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001421 else
1422 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001423
1424 if ((pAd->StaCfg.bAutoReconnect == TRUE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001425 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1426 &&
1427 (MlmeValidateSSID
1428 (pAd->MlmeAux.AutoReconnectSsid,
1429 pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1430 if ((pAd->ScanTab.BssNr == 0)
1431 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001432 struct rt_mlme_scan_req ScanReq;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001433
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001434 if (RTMP_TIME_AFTER
1435 (pAd->Mlme.Now32,
1436 pAd->StaCfg.LastScanTime + (10 * OS_HZ))) {
1437 DBGPRINT(RT_DEBUG_TRACE,
1438 ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n",
1439 pAd->MlmeAux.
1440 AutoReconnectSsid));
1441 ScanParmFill(pAd, &ScanReq,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001442 (char *)pAd->MlmeAux.
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001443 AutoReconnectSsid,
1444 pAd->MlmeAux.
1445 AutoReconnectSsidLen,
1446 BSS_ANY, SCAN_ACTIVE);
1447 MlmeEnqueue(pAd, SYNC_STATE_MACHINE,
1448 MT2_MLME_SCAN_REQ,
1449 sizeof
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001450 (struct rt_mlme_scan_req),
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001451 &ScanReq);
1452 pAd->Mlme.CntlMachine.CurrState =
1453 CNTL_WAIT_OID_LIST_SCAN;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001454 /* Reset Missed scan number */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001455 pAd->StaCfg.LastScanTime =
1456 pAd->Mlme.Now32;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001457 } else if (pAd->StaCfg.BssType == BSS_ADHOC) /* Quit the forever scan when in a very clean room */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001458 MlmeAutoReconnectLastSSID(pAd);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001459 } else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1460 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001461 MlmeAutoScan(pAd);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001462 pAd->StaCfg.LastScanTime =
1463 pAd->Mlme.Now32;
1464 } else {
1465 MlmeAutoReconnectLastSSID(pAd);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001466 }
1467 }
1468 }
1469 }
1470
1471SKIP_AUTO_SCAN_CONN:
1472
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001473 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap != 0)
1474 && (pAd->MacTab.fAnyBASession == FALSE)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001475 pAd->MacTab.fAnyBASession = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001476 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE,
1477 FALSE);
1478 } else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap == 0)
1479 && (pAd->MacTab.fAnyBASession == TRUE)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001480 pAd->MacTab.fAnyBASession = FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001481 AsicUpdateProtect(pAd,
1482 pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1483 OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001484 }
1485
1486 return;
1487}
1488
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001489/* Link down report */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001490void LinkDownExec(void *SystemSpecific1,
1491 void *FunctionContext,
1492 void *SystemSpecific2, void *SystemSpecific3)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001493{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001494 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001495
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001496 if (pAd != NULL) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001497 struct rt_mlme_disassoc_req DisassocReq;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001498
1499 if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001500 (INFRA_ON(pAd))) {
1501 DBGPRINT(RT_DEBUG_TRACE,
1502 ("LinkDownExec(): disassociate with current AP...\n"));
1503 DisassocParmFill(pAd, &DisassocReq,
1504 pAd->CommonCfg.Bssid,
1505 REASON_DISASSOC_STA_LEAVING);
1506 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
1507 MT2_MLME_DISASSOC_REQ,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001508 sizeof(struct rt_mlme_disassoc_req),
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001509 &DisassocReq);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001510 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1511
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001512 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1513 RTMP_IndicateMediaState(pAd);
1514 pAd->ExtraInfo = GENERAL_LINK_DOWN;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001515 }
1516 }
1517}
1518
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001519/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001520void MlmeAutoScan(struct rt_rtmp_adapter *pAd)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001521{
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001522 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001523 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001524 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1525 MlmeEnqueue(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001526 MLME_CNTL_STATE_MACHINE,
1527 OID_802_11_BSSID_LIST_SCAN,
1528 pAd->MlmeAux.AutoReconnectSsidLen,
1529 pAd->MlmeAux.AutoReconnectSsid);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001530 RTMP_MLME_HANDLER(pAd);
1531 }
1532}
1533
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001534/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001535void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001536{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001537 if (pAd->StaCfg.bAutoConnectByBssid) {
1538 DBGPRINT(RT_DEBUG_TRACE,
1539 ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n",
1540 pAd->MlmeAux.Bssid[0], pAd->MlmeAux.Bssid[1],
1541 pAd->MlmeAux.Bssid[2], pAd->MlmeAux.Bssid[3],
1542 pAd->MlmeAux.Bssid[4], pAd->MlmeAux.Bssid[5]));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001543
1544 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1545 MlmeEnqueue(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001546 MLME_CNTL_STATE_MACHINE,
1547 OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001548
1549 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1550
1551 RTMP_MLME_HANDLER(pAd);
1552 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001553 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001554 else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001555 (MlmeValidateSSID
1556 (pAd->MlmeAux.AutoReconnectSsid,
1557 pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001558 struct rt_ndis_802_11_ssid OidSsid;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001559 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001560 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid,
1561 pAd->MlmeAux.AutoReconnectSsidLen);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001562
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001563 DBGPRINT(RT_DEBUG_TRACE,
1564 ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
1565 pAd->MlmeAux.AutoReconnectSsid,
1566 pAd->MlmeAux.AutoReconnectSsidLen));
1567 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001568 sizeof(struct rt_ndis_802_11_ssid), &OidSsid);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001569 RTMP_MLME_HANDLER(pAd);
1570 }
1571}
1572
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001573/*
1574 ==========================================================================
1575 Description:
1576 This routine checks if there're other APs out there capable for
1577 roaming. Caller should call this routine only when Link up in INFRA mode
1578 and channel quality is below CQI_GOOD_THRESHOLD.
1579
1580 IRQL = DISPATCH_LEVEL
1581
1582 Output:
1583 ==========================================================================
1584 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001585void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001586{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001587 u16 i;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001588 struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1589 struct rt_bss_entry *pBss;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001590
1591 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001592 /* put all roaming candidates into RoamTab, and sort in RSSI order */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001593 BssTableInit(pRoamTab);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001594 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001595 pBss = &pAd->ScanTab.BssEntry[i];
1596
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001597 if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) <
1598 Now32)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001599 continue; /* AP disappear */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001600 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001601 continue; /* RSSI too weak. forget it. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001602 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001603 continue; /* skip current AP */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001604 if (pBss->Rssi <
1605 (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001606 continue; /* only AP with stronger RSSI is eligible for roaming */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001607
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001608 /* AP passing all above rules is put into roaming candidate table */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001609 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001610 sizeof(struct rt_bss_entry));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001611 pRoamTab->BssNr += 1;
1612 }
1613
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001614 if (pRoamTab->BssNr > 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001615 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001616 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1617 pAd->RalinkCounters.PoorCQIRoamingCount++;
1618 DBGPRINT(RT_DEBUG_TRACE,
1619 ("MMCHK - Roaming attempt #%ld\n",
1620 pAd->RalinkCounters.PoorCQIRoamingCount));
1621 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1622 MT2_MLME_ROAMING_REQ, 0, NULL);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001623 RTMP_MLME_HANDLER(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001624 }
1625 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001626 DBGPRINT(RT_DEBUG_TRACE,
1627 ("<== MlmeCheckForRoaming(# of candidate= %d)\n",
1628 pRoamTab->BssNr));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001629}
1630
1631/*
1632 ==========================================================================
1633 Description:
1634 This routine checks if there're other APs out there capable for
1635 roaming. Caller should call this routine only when link up in INFRA mode
1636 and channel quality is below CQI_GOOD_THRESHOLD.
1637
1638 IRQL = DISPATCH_LEVEL
1639
1640 Output:
1641 ==========================================================================
1642 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001643BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001644{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001645 u16 i;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001646 struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1647 struct rt_bss_entry *pBss;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001648
1649 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001650 /* put all roaming candidates into RoamTab, and sort in RSSI order */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001651 BssTableInit(pRoamTab);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001652 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001653 pBss = &pAd->ScanTab.BssEntry[i];
1654
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001655 if ((pBss->Rssi <= -50)
1656 && (pBss->Channel == pAd->CommonCfg.Channel))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001657 continue; /* RSSI too weak. forget it. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001658 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001659 continue; /* skip current AP */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001660 if (!SSID_EQUAL
1661 (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid,
1662 pAd->CommonCfg.SsidLen))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001663 continue; /* skip different SSID */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001664 if (pBss->Rssi <
1665 (RTMPMaxRssi
1666 (pAd, pAd->StaCfg.RssiSample.LastRssi0,
1667 pAd->StaCfg.RssiSample.LastRssi1,
1668 pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001669 continue; /* skip AP without better RSSI */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001670
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001671 DBGPRINT(RT_DEBUG_TRACE,
1672 ("LastRssi0 = %d, pBss->Rssi = %d\n",
1673 RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0,
1674 pAd->StaCfg.RssiSample.LastRssi1,
1675 pAd->StaCfg.RssiSample.LastRssi2),
1676 pBss->Rssi));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001677 /* AP passing all above rules is put into roaming candidate table */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001678 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001679 sizeof(struct rt_bss_entry));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001680 pRoamTab->BssNr += 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001681 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001682
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001683 DBGPRINT(RT_DEBUG_TRACE,
1684 ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1685 if (pRoamTab->BssNr > 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001686 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001687 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1688 pAd->RalinkCounters.PoorCQIRoamingCount++;
1689 DBGPRINT(RT_DEBUG_TRACE,
1690 ("MMCHK - Roaming attempt #%ld\n",
1691 pAd->RalinkCounters.PoorCQIRoamingCount));
1692 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1693 MT2_MLME_ROAMING_REQ, 0, NULL);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001694 RTMP_MLME_HANDLER(pAd);
1695 return TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001696 }
1697 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001698
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001699 return FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001700}
1701
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001702void MlmeSetTxRate(struct rt_rtmp_adapter *pAd,
1703 struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001704{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001705 u8 MaxMode = MODE_OFDM;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001706
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001707 MaxMode = MODE_HTGREENFIELD;
1708
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001709 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC)
1710 && (pAd->Antenna.field.TxPath == 2))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001711 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001712 else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001713 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1714
1715 if (pTxRate->CurrMCS < MCS_AUTO)
1716 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1717
1718 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1719 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1720
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001721 if (ADHOC_ON(pAd)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001722 /* If peer adhoc is b-only mode, we can't send 11g rate. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001723 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001724 pEntry->HTPhyMode.field.STBC = STBC_NONE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001725
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001726 /* */
1727 /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */
1728 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001729 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1730 pEntry->HTPhyMode.field.ShortGI =
1731 pAd->StaCfg.HTPhyMode.field.ShortGI;
1732 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001733
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001734 /* Patch speed error in status page */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001735 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001736 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001737 if (pTxRate->Mode <= MaxMode)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001738 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001739
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001740 if (pTxRate->ShortGI
1741 && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001742 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1743 else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001744 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1745
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001746 /* Reexam each bandwidth's SGI support. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001747 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) {
1748 if ((pEntry->HTPhyMode.field.BW == BW_20)
1749 &&
1750 (!CLIENT_STATUS_TEST_FLAG
1751 (pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001752 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001753 if ((pEntry->HTPhyMode.field.BW == BW_40)
1754 &&
1755 (!CLIENT_STATUS_TEST_FLAG
1756 (pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001757 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1758 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001759 /* Turn RTS/CTS rate to 6Mbps. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001760 if ((pEntry->HTPhyMode.field.MCS == 0)
1761 && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) {
1762 pEntry->HTPhyMode.field.MCS =
1763 pAd->StaCfg.HTPhyMode.field.MCS;
1764 if (pAd->MacTab.fAnyBASession) {
1765 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1766 ALLN_SETPROTECT, TRUE,
1767 (BOOLEAN) pAd->MlmeAux.
1768 AddHtInfo.AddHtInfo2.
1769 NonGfPresent);
1770 } else {
1771 AsicUpdateProtect(pAd,
1772 pAd->MlmeAux.AddHtInfo.
1773 AddHtInfo2.OperaionMode,
1774 ALLN_SETPROTECT, TRUE,
1775 (BOOLEAN) pAd->MlmeAux.
1776 AddHtInfo.AddHtInfo2.
1777 NonGfPresent);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001778 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001779 } else if ((pEntry->HTPhyMode.field.MCS == 8)
1780 && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) {
1781 pEntry->HTPhyMode.field.MCS =
1782 pAd->StaCfg.HTPhyMode.field.MCS;
1783 if (pAd->MacTab.fAnyBASession) {
1784 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1785 ALLN_SETPROTECT, TRUE,
1786 (BOOLEAN) pAd->MlmeAux.
1787 AddHtInfo.AddHtInfo2.
1788 NonGfPresent);
1789 } else {
1790 AsicUpdateProtect(pAd,
1791 pAd->MlmeAux.AddHtInfo.
1792 AddHtInfo2.OperaionMode,
1793 ALLN_SETPROTECT, TRUE,
1794 (BOOLEAN) pAd->MlmeAux.
1795 AddHtInfo.AddHtInfo2.
1796 NonGfPresent);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001797 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001798 } else if ((pEntry->HTPhyMode.field.MCS != 0)
1799 && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) {
1800 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1801 TRUE,
1802 (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1803 AddHtInfo2.NonGfPresent);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001804
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001805 } else if ((pEntry->HTPhyMode.field.MCS != 8)
1806 && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) {
1807 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1808 TRUE,
1809 (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1810 AddHtInfo2.NonGfPresent);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001811 }
Bartlomiej Zolnierkiewicz16232672009-04-26 16:06:00 +02001812
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001813 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1814 pEntry->HTPhyMode.field.ShortGI =
1815 pAd->StaCfg.HTPhyMode.field.ShortGI;
1816 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1817 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1818 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD)
1819 && pAd->WIFItestbed.bGreenField)
1820 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1821 }
1822
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001823 pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001824}
1825
1826/*
1827 ==========================================================================
1828 Description:
1829 This routine calculates the acumulated TxPER of eaxh TxRate. And
1830 according to the calculation result, change CommonCfg.TxRate which
1831 is the stable TX Rate we expect the Radio situation could sustained.
1832
1833 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1834 Output:
1835 CommonCfg.TxRate -
1836
1837 IRQL = DISPATCH_LEVEL
1838
1839 NOTE:
1840 call this routine every second
1841 ==========================================================================
1842 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001843void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001844{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001845 u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1846 unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt;
1847 unsigned long TxErrorRatio = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001848 BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001849 struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001850 u8 *pTable;
1851 u8 TableSize = 0;
1852 u8 InitTxRateIdx = 0, TrainUp, TrainDown;
1853 char Rssi, RssiOffset = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001854 TX_STA_CNT1_STRUC StaTx1;
1855 TX_STA_CNT0_STRUC TxStaCnt0;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001856 unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001857 struct rt_mac_table_entry *pEntry;
1858 struct rt_rssi_sample *pRssi = &pAd->StaCfg.RssiSample;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001859
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001860 /* */
1861 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
1862 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001863 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001864 pEntry = &pAd->MacTab.Content[i];
1865
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001866 /* check if this entry need to switch rate automatically */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001867 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1868 continue;
1869
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001870 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02001871 Rssi = RTMPMaxRssi(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001872 pRssi->AvgRssi0,
1873 pRssi->AvgRssi1, pRssi->AvgRssi2);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001874
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001875 /* Update statistic counter */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001876 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1877 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1878 pAd->bUpdateBcnCntDone = TRUE;
1879 TxRetransmit = StaTx1.field.TxRetransmit;
1880 TxSuccess = StaTx1.field.TxSuccess;
1881 TxFailCount = TxStaCnt0.field.TxFailCount;
1882 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1883
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001884 pAd->RalinkCounters.OneSecTxRetryOkCount +=
1885 StaTx1.field.TxRetransmit;
1886 pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
1887 StaTx1.field.TxSuccess;
1888 pAd->RalinkCounters.OneSecTxFailCount +=
1889 TxStaCnt0.field.TxFailCount;
1890 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
1891 StaTx1.field.TxSuccess;
1892 pAd->WlanCounters.RetryCount.u.LowPart +=
1893 StaTx1.field.TxRetransmit;
1894 pAd->WlanCounters.FailedCount.u.LowPart +=
1895 TxStaCnt0.field.TxFailCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001896
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001897 /* if no traffic in the past 1-sec period, don't change TX rate, */
1898 /* but clear all bad history. because the bad history may affect the next */
1899 /* Chariot throughput test */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001900 AccuTxTotalCnt =
1901 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1902 pAd->RalinkCounters.OneSecTxRetryOkCount +
1903 pAd->RalinkCounters.OneSecTxFailCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001904
1905 if (TxTotalCnt)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001906 TxErrorRatio =
1907 ((TxRetransmit +
1908 TxFailCount) * 100) / TxTotalCnt;
1909 } else {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02001910 if (INFRA_ON(pAd) && (i == 1))
1911 Rssi = RTMPMaxRssi(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001912 pRssi->AvgRssi0,
1913 pRssi->AvgRssi1,
1914 pRssi->AvgRssi2);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02001915 else
1916 Rssi = RTMPMaxRssi(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001917 pEntry->RssiSample.AvgRssi0,
1918 pEntry->RssiSample.AvgRssi1,
1919 pEntry->RssiSample.AvgRssi2);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001920
1921 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001922 pEntry->OneSecTxRetryOkCount +
1923 pEntry->OneSecTxFailCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001924
1925 if (TxTotalCnt)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001926 TxErrorRatio =
1927 ((pEntry->OneSecTxRetryOkCount +
1928 pEntry->OneSecTxFailCount) * 100) /
1929 TxTotalCnt;
1930 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001931
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001932 if (TxTotalCnt) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001933 /*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001934 Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1935 We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1936 */
1937 if (TxErrorRatio == 100) {
1938 TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001939 unsigned long Index;
1940 unsigned long MACValue;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001941
1942 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1943 TxRtyCfgtmp.word = TxRtyCfg.word;
1944 TxRtyCfg.field.LongRtyLimit = 0x0;
1945 TxRtyCfg.field.ShortRtyLimit = 0x0;
1946 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1947
1948 RTMPusecDelay(1);
1949
1950 Index = 0;
1951 MACValue = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001952 do {
1953 RTMP_IO_READ32(pAd, TXRXQ_PCNT,
1954 &MACValue);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001955 if ((MACValue & 0xffffff) == 0)
1956 break;
1957 Index++;
1958 RTMPusecDelay(1000);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001959 } while ((Index < 330)
1960 &&
1961 (!RTMP_TEST_FLAG
1962 (pAd,
1963 fRTMP_ADAPTER_HALT_IN_PROGRESS)));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001964
1965 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001966 TxRtyCfg.field.LongRtyLimit =
1967 TxRtyCfgtmp.field.LongRtyLimit;
1968 TxRtyCfg.field.ShortRtyLimit =
1969 TxRtyCfgtmp.field.ShortRtyLimit;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001970 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001971 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001972 }
1973
1974 CurrRateIdx = pEntry->CurrTxRateIndex;
1975
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001976 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
1977 &InitTxRateIdx);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001978
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001979 if (CurrRateIdx >= TableSize) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001980 CurrRateIdx = TableSize - 1;
1981 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001982 /* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */
1983 /* So need to sync here. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001984 pCurrTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001985 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001986 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001987 /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001988 ) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001989
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001990 /* Need to sync Real Tx rate and our record. */
1991 /* Then return for next DRS. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001992 pCurrTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001993 (struct rt_rtmp_tx_rate_switch *) & pTable[(InitTxRateIdx + 1)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001994 * 5];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001995 pEntry->CurrTxRateIndex = InitTxRateIdx;
1996 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1997
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001998 /* reset all OneSecTx counters */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07001999 RESET_ONE_SEC_TX_CNT(pEntry);
2000 continue;
2001 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002002 /* decide the next upgrade rate and downgrade rate, if any */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002003 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002004 UpRateIdx = CurrRateIdx + 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002005 DownRateIdx = CurrRateIdx - 1;
2006 } else if (CurrRateIdx == 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002007 UpRateIdx = CurrRateIdx + 1;
2008 DownRateIdx = CurrRateIdx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002009 } else if (CurrRateIdx == (TableSize - 1)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002010 UpRateIdx = CurrRateIdx;
2011 DownRateIdx = CurrRateIdx - 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002012 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002013
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002014 pCurrTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002015 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002016
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002017 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2018 TrainUp =
2019 (pCurrTxRate->TrainUp +
2020 (pCurrTxRate->TrainUp >> 1));
2021 TrainDown =
2022 (pCurrTxRate->TrainDown +
2023 (pCurrTxRate->TrainDown >> 1));
2024 } else {
2025 TrainUp = pCurrTxRate->TrainUp;
2026 TrainDown = pCurrTxRate->TrainDown;
2027 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002028
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002029 /*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002030
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002031 /* */
2032 /* Keep the last time TxRateChangeAction status. */
2033 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002034 pEntry->LastTimeTxRateChangeAction =
2035 pEntry->LastSecTxRateChangeAction;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002036
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002037 /* */
2038 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2039 /* (criteria copied from RT2500 for Netopia case) */
2040 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002041 if (TxTotalCnt <= 15) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002042 char idx = 0;
2043 u8 TxRateIdx;
2044 u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002045 0, MCS5 = 0, MCS6 = 0, MCS7 = 0;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002046 u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2047 u8 MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; /* 3*3 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002048
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002049 /* check the existence and index of each needed MCS */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002050 while (idx < pTable[0]) {
2051 pCurrTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002052 (struct rt_rtmp_tx_rate_switch *) & pTable[(idx + 1) *
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002053 5];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002054
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002055 if (pCurrTxRate->CurrMCS == MCS_0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002056 MCS0 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002057 } else if (pCurrTxRate->CurrMCS == MCS_1) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002058 MCS1 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002059 } else if (pCurrTxRate->CurrMCS == MCS_2) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002060 MCS2 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002061 } else if (pCurrTxRate->CurrMCS == MCS_3) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002062 MCS3 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002063 } else if (pCurrTxRate->CurrMCS == MCS_4) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002064 MCS4 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002065 } else if (pCurrTxRate->CurrMCS == MCS_5) {
2066 MCS5 = idx;
2067 } else if (pCurrTxRate->CurrMCS == MCS_6) {
2068 MCS6 = idx;
2069 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002070 /*else if (pCurrTxRate->CurrMCS == MCS_7) */
2071 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) /* prevent the highest MCS using short GI when 1T and low throughput */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002072 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002073 MCS7 = idx;
2074 } else if (pCurrTxRate->CurrMCS == MCS_12) {
2075 MCS12 = idx;
2076 } else if (pCurrTxRate->CurrMCS == MCS_13) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002077 MCS13 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002078 } else if (pCurrTxRate->CurrMCS == MCS_14) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002079 MCS14 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002080 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002081 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 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002082 {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002083 MCS15 = idx;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002084 } else if (pCurrTxRate->CurrMCS == MCS_20) /* 3*3 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002085 {
2086 MCS20 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002087 } else if (pCurrTxRate->CurrMCS == MCS_21) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002088 MCS21 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002089 } else if (pCurrTxRate->CurrMCS == MCS_22) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002090 MCS22 = idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002091 } else if (pCurrTxRate->CurrMCS == MCS_23) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002092 MCS23 = idx;
2093 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002094 idx++;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002095 }
2096
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002097 if (pAd->LatchRfRegs.Channel <= 14) {
2098 if (pAd->NicConfig2.field.ExternalLNAForG) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002099 RssiOffset = 2;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002100 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002101 RssiOffset = 5;
2102 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002103 } else {
2104 if (pAd->NicConfig2.field.ExternalLNAForA) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002105 RssiOffset = 5;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002106 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002107 RssiOffset = 8;
2108 }
2109 }
Bartlomiej Zolnierkiewicz16232672009-04-26 16:06:00 +02002110
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002111 /*if (MCS15) */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002112 if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) { /* N mode with 3 stream // 3*3 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002113 if (MCS23 && (Rssi >= -70))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002114 TxRateIdx = MCS23;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002115 else if (MCS22 && (Rssi >= -72))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002116 TxRateIdx = MCS22;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002117 else if (MCS21 && (Rssi >= -76))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002118 TxRateIdx = MCS21;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002119 else if (MCS20 && (Rssi >= -78))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002120 TxRateIdx = MCS20;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002121 else if (MCS4 && (Rssi >= -82))
2122 TxRateIdx = MCS4;
2123 else if (MCS3 && (Rssi >= -84))
2124 TxRateIdx = MCS3;
2125 else if (MCS2 && (Rssi >= -86))
2126 TxRateIdx = MCS2;
2127 else if (MCS1 && (Rssi >= -88))
2128 TxRateIdx = MCS1;
2129 else
2130 TxRateIdx = MCS0;
2131 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002132/* else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */
2133 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand)) /* 3*3 */
2134 { /* N mode with 2 stream */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002135 if (MCS15 && (Rssi >= (-70 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002136 TxRateIdx = MCS15;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002137 else if (MCS14 && (Rssi >= (-72 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002138 TxRateIdx = MCS14;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002139 else if (MCS13 && (Rssi >= (-76 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002140 TxRateIdx = MCS13;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002141 else if (MCS12 && (Rssi >= (-78 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002142 TxRateIdx = MCS12;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002143 else if (MCS4 && (Rssi >= (-82 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002144 TxRateIdx = MCS4;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002145 else if (MCS3 && (Rssi >= (-84 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002146 TxRateIdx = MCS3;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002147 else if (MCS2 && (Rssi >= (-86 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002148 TxRateIdx = MCS2;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002149 else if (MCS1 && (Rssi >= (-88 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002150 TxRateIdx = MCS1;
2151 else
2152 TxRateIdx = MCS0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002153 } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) { /* N mode with 1 stream */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002154 if (MCS7 && (Rssi > (-72 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002155 TxRateIdx = MCS7;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002156 else if (MCS6 && (Rssi > (-74 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002157 TxRateIdx = MCS6;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002158 else if (MCS5 && (Rssi > (-77 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002159 TxRateIdx = MCS5;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002160 else if (MCS4 && (Rssi > (-79 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002161 TxRateIdx = MCS4;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002162 else if (MCS3 && (Rssi > (-81 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002163 TxRateIdx = MCS3;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002164 else if (MCS2 && (Rssi > (-83 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002165 TxRateIdx = MCS2;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002166 else if (MCS1 && (Rssi > (-86 + RssiOffset)))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002167 TxRateIdx = MCS1;
2168 else
2169 TxRateIdx = MCS0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002170 } else { /* Legacy mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002171 if (MCS7 && (Rssi > -70))
2172 TxRateIdx = MCS7;
2173 else if (MCS6 && (Rssi > -74))
2174 TxRateIdx = MCS6;
2175 else if (MCS5 && (Rssi > -78))
2176 TxRateIdx = MCS5;
2177 else if (MCS4 && (Rssi > -82))
2178 TxRateIdx = MCS4;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002179 else if (MCS4 == 0) /* for B-only mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002180 TxRateIdx = MCS3;
2181 else if (MCS3 && (Rssi > -85))
2182 TxRateIdx = MCS3;
2183 else if (MCS2 && (Rssi > -87))
2184 TxRateIdx = MCS2;
2185 else if (MCS1 && (Rssi > -90))
2186 TxRateIdx = MCS1;
2187 else
2188 TxRateIdx = MCS0;
2189 }
2190
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002191 /* if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002192 {
2193 pEntry->CurrTxRateIndex = TxRateIdx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002194 pNextTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002195 (struct rt_rtmp_tx_rate_switch *) &
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002196 pTable[(pEntry->CurrTxRateIndex + 1) * 5];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002197 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2198 }
2199
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002200 NdisZeroMemory(pEntry->TxQuality,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002201 sizeof(u16)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002202 MAX_STEP_OF_TX_RATE_SWITCH);
2203 NdisZeroMemory(pEntry->PER,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002204 sizeof(u8)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002205 MAX_STEP_OF_TX_RATE_SWITCH);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002206 pEntry->fLastSecAccordingRSSI = TRUE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002207 /* reset all OneSecTx counters */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002208 RESET_ONE_SEC_TX_CNT(pEntry);
2209
2210 continue;
2211 }
2212
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002213 if (pEntry->fLastSecAccordingRSSI == TRUE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002214 pEntry->fLastSecAccordingRSSI = FALSE;
2215 pEntry->LastSecTxRateChangeAction = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002216 /* reset all OneSecTx counters */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002217 RESET_ONE_SEC_TX_CNT(pEntry);
2218
2219 continue;
2220 }
2221
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002222 do {
2223 BOOLEAN bTrainUpDown = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002224
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002225 pEntry->CurrTxRateStableTime++;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002226
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002227 /* downgrade TX quality if PER >= Rate-Down threshold */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002228 if (TxErrorRatio >= TrainDown) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002229 bTrainUpDown = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002230 pEntry->TxQuality[CurrRateIdx] =
2231 DRS_TX_QUALITY_WORST_BOUND;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002232 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002233 /* upgrade TX quality if PER <= Rate-Up threshold */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002234 else if (TxErrorRatio <= TrainUp) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002235 bTrainUpDown = TRUE;
2236 bUpgradeQuality = TRUE;
2237 if (pEntry->TxQuality[CurrRateIdx])
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002238 pEntry->TxQuality[CurrRateIdx]--; /* quality very good in CurrRate */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002239
2240 if (pEntry->TxRateUpPenalty)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002241 pEntry->TxRateUpPenalty--;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002242 else if (pEntry->TxQuality[UpRateIdx])
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002243 pEntry->TxQuality[UpRateIdx]--; /* may improve next UP rate's quality */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002244 }
2245
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002246 pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002247
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002248 if (bTrainUpDown) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002249 /* perform DRS - consider TxRate Down first, then rate up. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002250 if ((CurrRateIdx != DownRateIdx)
2251 && (pEntry->TxQuality[CurrRateIdx] >=
2252 DRS_TX_QUALITY_WORST_BOUND)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002253 pEntry->CurrTxRateIndex = DownRateIdx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002254 } else if ((CurrRateIdx != UpRateIdx)
2255 && (pEntry->TxQuality[UpRateIdx] <=
2256 0)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002257 pEntry->CurrTxRateIndex = UpRateIdx;
2258 }
2259 }
2260 } while (FALSE);
2261
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002262 /* if rate-up happen, clear all bad history of all TX rates */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002263 if (pEntry->CurrTxRateIndex > CurrRateIdx) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002264 pEntry->CurrTxRateStableTime = 0;
2265 pEntry->TxRateUpPenalty = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002266 pEntry->LastSecTxRateChangeAction = 1; /* rate UP */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002267 NdisZeroMemory(pEntry->TxQuality,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002268 sizeof(u16)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002269 MAX_STEP_OF_TX_RATE_SWITCH);
2270 NdisZeroMemory(pEntry->PER,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002271 sizeof(u8)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002272 MAX_STEP_OF_TX_RATE_SWITCH);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002273
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002274 /* */
2275 /* For TxRate fast train up */
2276 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002277 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2278 RTMPSetTimer(&pAd->StaCfg.
2279 StaQuickResponeForRateUpTimer,
2280 100);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002281
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002282 pAd->StaCfg.
2283 StaQuickResponeForRateUpTimerRunning = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002284 }
2285 bTxRateChanged = TRUE;
2286 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002287 /* if rate-down happen, only clear DownRate's bad history */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002288 else if (pEntry->CurrTxRateIndex < CurrRateIdx) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002289 pEntry->CurrTxRateStableTime = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002290 pEntry->TxRateUpPenalty = 0; /* no penalty */
2291 pEntry->LastSecTxRateChangeAction = 2; /* rate DOWN */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002292 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2293 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2294
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002295 /* */
2296 /* For TxRate fast train down */
2297 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002298 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2299 RTMPSetTimer(&pAd->StaCfg.
2300 StaQuickResponeForRateUpTimer,
2301 100);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002302
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002303 pAd->StaCfg.
2304 StaQuickResponeForRateUpTimerRunning = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002305 }
2306 bTxRateChanged = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002307 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002308 pEntry->LastSecTxRateChangeAction = 0; /* rate no change */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002309 bTxRateChanged = FALSE;
2310 }
2311
2312 pEntry->LastTxOkCount = TxSuccess;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002313 {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002314 u8 tmpTxRate;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002315
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002316 /* to fix tcp ack issue */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002317 if (!bTxRateChanged
2318 && (pAd->RalinkCounters.OneSecReceivedByteCount >
2319 (pAd->RalinkCounters.
2320 OneSecTransmittedByteCount * 5))) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002321 tmpTxRate = DownRateIdx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002322 DBGPRINT_RAW(RT_DEBUG_TRACE,
2323 ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2324 pAd->RalinkCounters.
2325 OneSecReceivedByteCount,
2326 pAd->RalinkCounters.
2327 OneSecTransmittedByteCount,
2328 pEntry->CurrTxRateIndex,
2329 tmpTxRate));
2330 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002331 tmpTxRate = pEntry->CurrTxRateIndex;
2332 }
2333
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002334 pNextTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002335 (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) *
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002336 5];
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002337 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002338 if (bTxRateChanged && pNextTxRate) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002339 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2340 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002341 /* reset all OneSecTx counters */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002342 RESET_ONE_SEC_TX_CNT(pEntry);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002343 }
2344}
2345
2346/*
2347 ========================================================================
2348 Routine Description:
2349 Station side, Auto TxRate faster train up timer call back function.
2350
2351 Arguments:
2352 SystemSpecific1 - Not used.
2353 FunctionContext - Pointer to our Adapter context.
2354 SystemSpecific2 - Not used.
2355 SystemSpecific3 - Not used.
2356
2357 Return Value:
2358 None
2359
2360 ========================================================================
2361*/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002362void StaQuickResponeForRateUpExec(void *SystemSpecific1,
2363 void *FunctionContext,
2364 void *SystemSpecific2,
2365 void *SystemSpecific3)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002366{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002367 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002368 u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2369 unsigned long TxTotalCnt;
2370 unsigned long TxErrorRatio = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002371 BOOLEAN bTxRateChanged; /*, bUpgradeQuality = FALSE; */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002372 struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002373 u8 *pTable;
2374 u8 TableSize = 0;
2375 u8 InitTxRateIdx = 0, TrainUp, TrainDown;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002376 TX_STA_CNT1_STRUC StaTx1;
2377 TX_STA_CNT0_STRUC TxStaCnt0;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002378 char Rssi, ratio;
2379 unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002380 struct rt_mac_table_entry *pEntry;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002381 unsigned long i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002382
2383 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2384
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002385 /* */
2386 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
2387 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002388 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002389 pEntry = &pAd->MacTab.Content[i];
2390
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002391 /* check if this entry need to switch rate automatically */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002392 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2393 continue;
2394
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002395 if (INFRA_ON(pAd) && (i == 1))
2396 Rssi = RTMPMaxRssi(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002397 pAd->StaCfg.RssiSample.AvgRssi0,
2398 pAd->StaCfg.RssiSample.AvgRssi1,
2399 pAd->StaCfg.RssiSample.AvgRssi2);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002400 else
2401 Rssi = RTMPMaxRssi(pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002402 pEntry->RssiSample.AvgRssi0,
2403 pEntry->RssiSample.AvgRssi1,
2404 pEntry->RssiSample.AvgRssi2);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002405
2406 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2407
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002408 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
2409 &InitTxRateIdx);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002410
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002411 /* decide the next upgrade rate and downgrade rate, if any */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002412 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002413 UpRateIdx = CurrRateIdx + 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002414 DownRateIdx = CurrRateIdx - 1;
2415 } else if (CurrRateIdx == 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002416 UpRateIdx = CurrRateIdx + 1;
2417 DownRateIdx = CurrRateIdx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002418 } else if (CurrRateIdx == (TableSize - 1)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002419 UpRateIdx = CurrRateIdx;
2420 DownRateIdx = CurrRateIdx - 1;
2421 }
2422
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002423 pCurrTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002424 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002425
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002426 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2427 TrainUp =
2428 (pCurrTxRate->TrainUp +
2429 (pCurrTxRate->TrainUp >> 1));
2430 TrainDown =
2431 (pCurrTxRate->TrainDown +
2432 (pCurrTxRate->TrainDown >> 1));
2433 } else {
2434 TrainUp = pCurrTxRate->TrainUp;
2435 TrainDown = pCurrTxRate->TrainDown;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002436 }
2437
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002438 if (pAd->MacTab.Size == 1) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002439 /* Update statistic counter */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002440 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2441 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2442
2443 TxRetransmit = StaTx1.field.TxRetransmit;
2444 TxSuccess = StaTx1.field.TxSuccess;
2445 TxFailCount = TxStaCnt0.field.TxFailCount;
2446 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2447
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002448 pAd->RalinkCounters.OneSecTxRetryOkCount +=
2449 StaTx1.field.TxRetransmit;
2450 pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
2451 StaTx1.field.TxSuccess;
2452 pAd->RalinkCounters.OneSecTxFailCount +=
2453 TxStaCnt0.field.TxFailCount;
2454 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
2455 StaTx1.field.TxSuccess;
2456 pAd->WlanCounters.RetryCount.u.LowPart +=
2457 StaTx1.field.TxRetransmit;
2458 pAd->WlanCounters.FailedCount.u.LowPart +=
2459 TxStaCnt0.field.TxFailCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002460
2461 if (TxTotalCnt)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002462 TxErrorRatio =
2463 ((TxRetransmit +
2464 TxFailCount) * 100) / TxTotalCnt;
2465 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002466 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002467 pEntry->OneSecTxRetryOkCount +
2468 pEntry->OneSecTxFailCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002469
2470 if (TxTotalCnt)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002471 TxErrorRatio =
2472 ((pEntry->OneSecTxRetryOkCount +
2473 pEntry->OneSecTxFailCount) * 100) /
2474 TxTotalCnt;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002475 }
2476
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002477 /* */
2478 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2479 /* (criteria copied from RT2500 for Netopia case) */
2480 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002481 if (TxTotalCnt <= 12) {
2482 NdisZeroMemory(pAd->DrsCounters.TxQuality,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002483 sizeof(u16)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002484 MAX_STEP_OF_TX_RATE_SWITCH);
2485 NdisZeroMemory(pAd->DrsCounters.PER,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002486 sizeof(u8)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002487 MAX_STEP_OF_TX_RATE_SWITCH);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002488
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002489 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2490 && (CurrRateIdx != DownRateIdx)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002491 pAd->CommonCfg.TxRateIndex = DownRateIdx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002492 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2493 DRS_TX_QUALITY_WORST_BOUND;
2494 } else
2495 if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2496 2) && (CurrRateIdx != UpRateIdx)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002497 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2498 }
2499
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002500 DBGPRINT_RAW(RT_DEBUG_TRACE,
2501 ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002502 return;
2503 }
2504
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002505 do {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002506 unsigned long OneSecTxNoRetryOKRationCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002507
2508 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2509 ratio = 5;
2510 else
2511 ratio = 4;
2512
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002513 /* downgrade TX quality if PER >= Rate-Down threshold */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002514 if (TxErrorRatio >= TrainDown) {
2515 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2516 DRS_TX_QUALITY_WORST_BOUND;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002517 }
2518
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002519 pAd->DrsCounters.PER[CurrRateIdx] =
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002520 (u8)TxErrorRatio;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002521
2522 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2523
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002524 /* perform DRS - consider TxRate Down first, then rate up. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002525 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2526 && (CurrRateIdx != DownRateIdx)) {
2527 if ((pAd->DrsCounters.LastTxOkCount + 2) >=
2528 OneSecTxNoRetryOKRationCount) {
2529 pAd->CommonCfg.TxRateIndex =
2530 DownRateIdx;
2531 pAd->DrsCounters.
2532 TxQuality[CurrRateIdx] =
2533 DRS_TX_QUALITY_WORST_BOUND;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002534
2535 }
2536
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002537 } else
2538 if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2539 2) && (CurrRateIdx != UpRateIdx)) {
2540 if ((TxErrorRatio >= 50)
2541 || (TxErrorRatio >= TrainDown)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002542
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002543 } else if ((pAd->DrsCounters.LastTxOkCount + 2)
2544 >= OneSecTxNoRetryOKRationCount) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002545 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2546 }
2547 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002548 } while (FALSE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002549
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002550 /* if rate-up happen, clear all bad history of all TX rates */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002551 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002552 pAd->DrsCounters.TxRateUpPenalty = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002553 NdisZeroMemory(pAd->DrsCounters.TxQuality,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002554 sizeof(u16)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002555 MAX_STEP_OF_TX_RATE_SWITCH);
2556 NdisZeroMemory(pAd->DrsCounters.PER,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002557 sizeof(u8)*
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002558 MAX_STEP_OF_TX_RATE_SWITCH);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002559 bTxRateChanged = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002560 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002561 /* if rate-down happen, only clear DownRate's bad history */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002562 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) {
2563 DBGPRINT_RAW(RT_DEBUG_TRACE,
2564 ("QuickDRS: --TX rate from %d to %d \n",
2565 CurrRateIdx, pAd->CommonCfg.TxRateIndex));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002566
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002567 pAd->DrsCounters.TxRateUpPenalty = 0; /* no penalty */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002568 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] =
2569 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002570 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002571 bTxRateChanged = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002572 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002573 bTxRateChanged = FALSE;
2574 }
2575
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002576 pNextTxRate =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002577 (struct rt_rtmp_tx_rate_switch *) &
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002578 pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5];
2579 if (bTxRateChanged && pNextTxRate) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002580 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2581 }
2582 }
2583}
2584
2585/*
2586 ==========================================================================
2587 Description:
2588 This routine is executed periodically inside MlmePeriodicExec() after
2589 association with an AP.
2590 It checks if StaCfg.Psm is consistent with user policy (recorded in
2591 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2592 there're some conditions to consider:
2593 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2594 the time when Mibss==TRUE
2595 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2596 if outgoing traffic available in TxRing or MgmtRing.
2597 Output:
2598 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2599
2600 IRQL = DISPATCH_LEVEL
2601
2602 ==========================================================================
2603 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002604void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002605{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002606 unsigned long PowerMode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002607
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002608 /* condition - */
2609 /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */
2610 /* 2. user wants either MAX_PSP or FAST_PSP */
2611 /* 3. but current psm is not in PWR_SAVE */
2612 /* 4. CNTL state machine is not doing SCANning */
2613 /* 5. no TX SUCCESS event for the past 1-sec period */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002614 PowerMode = pAd->StaCfg.WindowsPowerMode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002615
2616 if (INFRA_ON(pAd) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002617 (PowerMode != Ndis802_11PowerModeCAM) &&
2618 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002619/* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002620 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
2621 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2622 /*&&
2623 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2624 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2625 ) {
2626 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2627 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002628 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002629 if (!
2630 (pAd->CommonCfg.bAPSDCapable
2631 && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
2632 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2633 } else {
2634 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02002635 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002636 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002637}
2638
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002639/* IRQL = PASSIVE_LEVEL */
2640/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002641void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002642{
2643 AUTO_RSP_CFG_STRUC csr4;
2644
2645 pAd->StaCfg.Psm = psm;
2646 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002647 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002648 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
Bartlomiej Zolnierkiewicze96e9462009-08-16 21:31:36 +02002649
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002650 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2651}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002652
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002653/*
2654 ==========================================================================
2655 Description:
2656 This routine calculates TxPER, RxPER of the past N-sec period. And
2657 according to the calculation result, ChannelQuality is calculated here
2658 to decide if current AP is still doing the job.
2659
2660 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2661 Output:
2662 StaCfg.ChannelQuality - 0..100
2663
2664 IRQL = DISPATCH_LEVEL
2665
2666 NOTE: This routine decide channle quality based on RX CRC error ratio.
2667 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2668 is performed right before this routine, so that this routine can decide
2669 channel quality based on the most up-to-date information
2670 ==========================================================================
2671 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002672void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd,
2673 struct rt_mac_table_entry *pMacEntry, unsigned long Now32)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002674{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002675 unsigned long TxOkCnt, TxCnt, TxPER, TxPRR;
2676 unsigned long RxCnt, RxPER;
2677 u8 NorRssi;
2678 char MaxRssi;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002679 struct rt_rssi_sample *pRssiSample = NULL;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002680 u32 OneSecTxNoRetryOkCount = 0;
2681 u32 OneSecTxRetryOkCount = 0;
2682 u32 OneSecTxFailCount = 0;
2683 u32 OneSecRxOkCnt = 0;
2684 u32 OneSecRxFcsErrCnt = 0;
2685 unsigned long ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming */
2686 unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002687
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002688 if (pAd->OpMode == OPMODE_STA) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002689 pRssiSample = &pAd->StaCfg.RssiSample;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002690 OneSecTxNoRetryOkCount =
2691 pAd->RalinkCounters.OneSecTxNoRetryOkCount;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002692 OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2693 OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2694 OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2695 OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
2696 }
2697
2698 MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002699 pRssiSample->LastRssi1, pRssiSample->LastRssi2);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002700
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002701 /* */
2702 /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */
2703 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002704 TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2705 TxCnt = TxOkCnt + OneSecTxFailCount;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002706 if (TxCnt < 5) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002707 TxPER = 0;
2708 TxPRR = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002709 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002710 TxPER = (OneSecTxFailCount * 100) / TxCnt;
2711 TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2712 }
2713
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002714 /* */
2715 /* calculate RX PER - don't take RxPER into consideration if too few sample */
2716 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002717 RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2718 if (RxCnt < 5)
2719 RxPER = 0;
2720 else
2721 RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
2722
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002723 /* */
2724 /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */
2725 /* */
2726 if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) && /* no heavy traffic */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002727 ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) {
2728 DBGPRINT(RT_DEBUG_TRACE,
2729 ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2730 BeaconLostTime, TxOkCnt));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002731 ChannelQuality = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002732 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002733 /* Normalize Rssi */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002734 if (MaxRssi > -40)
2735 NorRssi = 100;
2736 else if (MaxRssi < -90)
2737 NorRssi = 0;
2738 else
2739 NorRssi = (MaxRssi + 90) * 2;
2740
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002741 /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002742 ChannelQuality = (RSSI_WEIGHTING * NorRssi +
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002743 TX_WEIGHTING * (100 - TxPRR) +
2744 RX_WEIGHTING * (100 - RxPER)) / 100;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002745 }
2746
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002747 if (pAd->OpMode == OPMODE_STA)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002748 pAd->Mlme.ChannelQuality =
2749 (ChannelQuality > 100) ? 100 : ChannelQuality;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02002750
2751}
2752
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002753/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002754void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002755{
2756 AUTO_RSP_CFG_STRUC csr4;
2757
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002758 /* */
2759 /* Always use Long preamble before verifiation short preamble functionality works well. */
2760 /* Todo: remove the following line if short preamble functionality works */
2761 /* */
2762 /*TxPreamble = Rt802_11PreambleLong; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002763
2764 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002765 if (TxPreamble == Rt802_11PreambleLong) {
2766 DBGPRINT(RT_DEBUG_TRACE,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002767 ("MlmeSetTxPreamble (= long PREAMBLE)\n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002768 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2769 csr4.field.AutoResponderPreamble = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002770 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002771 /* NOTE: 1Mbps should always use long preamble */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002772 DBGPRINT(RT_DEBUG_TRACE,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002773 ("MlmeSetTxPreamble (= short PREAMBLE)\n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002774 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2775 csr4.field.AutoResponderPreamble = 1;
2776 }
2777
2778 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2779}
2780
2781/*
2782 ==========================================================================
2783 Description:
2784 Update basic rate bitmap
2785 ==========================================================================
2786 */
2787
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002788void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002789{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002790 int i, j;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002791 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002792 u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2793 u8 *sup_p = pAdapter->CommonCfg.SupRate;
2794 u8 *ext_p = pAdapter->CommonCfg.ExtRate;
2795 unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002796
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002797 /* if A mode, always use fix BasicRateBitMap */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002798 /*if (pAdapter->CommonCfg.Channel == PHY_11A) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002799 if (pAdapter->CommonCfg.Channel > 14)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002800 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2801 /* End of if */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002802
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002803 if (pAdapter->CommonCfg.BasicRateBitmap > 4095) {
2804 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2805 return;
2806 }
2807 /* End of if */
2808 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2809 sup_p[i] &= 0x7f;
2810 ext_p[i] &= 0x7f;
2811 } /* End of for */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002812
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002813 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2814 if (bitmap & (1 << i)) {
2815 for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2816 if (sup_p[j] == rate[i])
2817 sup_p[j] |= 0x80;
2818 /* End of if */
2819 } /* End of for */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002820
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002821 for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2822 if (ext_p[j] == rate[i])
2823 ext_p[j] |= 0x80;
2824 /* End of if */
2825 } /* End of for */
2826 } /* End of if */
2827 } /* End of for */
2828} /* End of UpdateBasicRateBitmap */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002829
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002830/* IRQL = PASSIVE_LEVEL */
2831/* IRQL = DISPATCH_LEVEL */
2832/* bLinkUp is to identify the inital link speed. */
2833/* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08002834void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002835{
2836 int i, num;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002837 u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2838 u8 MinSupport = RATE_54;
2839 unsigned long BasicRateBitmap = 0;
2840 u8 CurrBasicRate = RATE_1;
2841 u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002842 PHTTRANSMIT_SETTING pHtPhy = NULL;
2843 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2844 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2845 BOOLEAN *auto_rate_cur_p;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08002846 u8 HtMcs = MCS_AUTO;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002847
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002848 /* find max desired rate */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002849 UpdateBasicRateBitmap(pAd);
2850
2851 num = 0;
2852 auto_rate_cur_p = NULL;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002853 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2854 switch (pAd->CommonCfg.DesireRate[i] & 0x7f) {
2855 case 2:
2856 Rate = RATE_1;
2857 num++;
2858 break;
2859 case 4:
2860 Rate = RATE_2;
2861 num++;
2862 break;
2863 case 11:
2864 Rate = RATE_5_5;
2865 num++;
2866 break;
2867 case 22:
2868 Rate = RATE_11;
2869 num++;
2870 break;
2871 case 12:
2872 Rate = RATE_6;
2873 num++;
2874 break;
2875 case 18:
2876 Rate = RATE_9;
2877 num++;
2878 break;
2879 case 24:
2880 Rate = RATE_12;
2881 num++;
2882 break;
2883 case 36:
2884 Rate = RATE_18;
2885 num++;
2886 break;
2887 case 48:
2888 Rate = RATE_24;
2889 num++;
2890 break;
2891 case 72:
2892 Rate = RATE_36;
2893 num++;
2894 break;
2895 case 96:
2896 Rate = RATE_48;
2897 num++;
2898 break;
2899 case 108:
2900 Rate = RATE_54;
2901 num++;
2902 break;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002903 /*default: Rate = RATE_1; break; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002904 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002905 if (MaxDesire < Rate)
2906 MaxDesire = Rate;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002907 }
2908
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002909/*=========================================================================== */
2910/*=========================================================================== */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002911 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002912 pHtPhy = &pAd->StaCfg.HTPhyMode;
2913 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2914 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002915
2916 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002917 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002918
2919 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002920 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2921 (MaxDesire > RATE_11)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002922 MaxDesire = RATE_11;
2923 }
2924 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002925
2926 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2927 pMinHtPhy->word = 0;
2928 pMaxHtPhy->word = 0;
2929 pHtPhy->word = 0;
2930
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002931 /* Auto rate switching is enabled only if more than one DESIRED RATES are */
2932 /* specified; otherwise disabled */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002933 if (num <= 1) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002934 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2935 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002936 *auto_rate_cur_p = FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002937 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002938 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2939 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002940 *auto_rate_cur_p = TRUE;
2941 }
2942
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002943 if (HtMcs != MCS_AUTO) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002944 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2945 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002946 *auto_rate_cur_p = FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002947 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002948 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2949 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002950 *auto_rate_cur_p = TRUE;
2951 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002952
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002953 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002954 pSupRate = &pAd->StaActive.SupRate[0];
2955 pExtRate = &pAd->StaActive.ExtRate[0];
2956 SupRateLen = pAd->StaActive.SupRateLen;
2957 ExtRateLen = pAd->StaActive.ExtRateLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002958 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07002959 pSupRate = &pAd->CommonCfg.SupRate[0];
2960 pExtRate = &pAd->CommonCfg.ExtRate[0];
2961 SupRateLen = pAd->CommonCfg.SupRateLen;
2962 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2963 }
2964
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08002965 /* find max supported rate */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08002966 for (i = 0; i < SupRateLen; i++) {
2967 switch (pSupRate[i] & 0x7f) {
2968 case 2:
2969 Rate = RATE_1;
2970 if (pSupRate[i] & 0x80)
2971 BasicRateBitmap |= 0x0001;
2972 break;
2973 case 4:
2974 Rate = RATE_2;
2975 if (pSupRate[i] & 0x80)
2976 BasicRateBitmap |= 0x0002;
2977 break;
2978 case 11:
2979 Rate = RATE_5_5;
2980 if (pSupRate[i] & 0x80)
2981 BasicRateBitmap |= 0x0004;
2982 break;
2983 case 22:
2984 Rate = RATE_11;
2985 if (pSupRate[i] & 0x80)
2986 BasicRateBitmap |= 0x0008;
2987 break;
2988 case 12:
2989 Rate = RATE_6; /*if (pSupRate[i] & 0x80) */
2990 BasicRateBitmap |= 0x0010;
2991 break;
2992 case 18:
2993 Rate = RATE_9;
2994 if (pSupRate[i] & 0x80)
2995 BasicRateBitmap |= 0x0020;
2996 break;
2997 case 24:
2998 Rate = RATE_12; /*if (pSupRate[i] & 0x80) */
2999 BasicRateBitmap |= 0x0040;
3000 break;
3001 case 36:
3002 Rate = RATE_18;
3003 if (pSupRate[i] & 0x80)
3004 BasicRateBitmap |= 0x0080;
3005 break;
3006 case 48:
3007 Rate = RATE_24; /*if (pSupRate[i] & 0x80) */
3008 BasicRateBitmap |= 0x0100;
3009 break;
3010 case 72:
3011 Rate = RATE_36;
3012 if (pSupRate[i] & 0x80)
3013 BasicRateBitmap |= 0x0200;
3014 break;
3015 case 96:
3016 Rate = RATE_48;
3017 if (pSupRate[i] & 0x80)
3018 BasicRateBitmap |= 0x0400;
3019 break;
3020 case 108:
3021 Rate = RATE_54;
3022 if (pSupRate[i] & 0x80)
3023 BasicRateBitmap |= 0x0800;
3024 break;
3025 default:
3026 Rate = RATE_1;
3027 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003028 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003029 if (MaxSupport < Rate)
3030 MaxSupport = Rate;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003031
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003032 if (MinSupport > Rate)
3033 MinSupport = Rate;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003034 }
3035
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003036 for (i = 0; i < ExtRateLen; i++) {
3037 switch (pExtRate[i] & 0x7f) {
3038 case 2:
3039 Rate = RATE_1;
3040 if (pExtRate[i] & 0x80)
3041 BasicRateBitmap |= 0x0001;
3042 break;
3043 case 4:
3044 Rate = RATE_2;
3045 if (pExtRate[i] & 0x80)
3046 BasicRateBitmap |= 0x0002;
3047 break;
3048 case 11:
3049 Rate = RATE_5_5;
3050 if (pExtRate[i] & 0x80)
3051 BasicRateBitmap |= 0x0004;
3052 break;
3053 case 22:
3054 Rate = RATE_11;
3055 if (pExtRate[i] & 0x80)
3056 BasicRateBitmap |= 0x0008;
3057 break;
3058 case 12:
3059 Rate = RATE_6; /*if (pExtRate[i] & 0x80) */
3060 BasicRateBitmap |= 0x0010;
3061 break;
3062 case 18:
3063 Rate = RATE_9;
3064 if (pExtRate[i] & 0x80)
3065 BasicRateBitmap |= 0x0020;
3066 break;
3067 case 24:
3068 Rate = RATE_12; /*if (pExtRate[i] & 0x80) */
3069 BasicRateBitmap |= 0x0040;
3070 break;
3071 case 36:
3072 Rate = RATE_18;
3073 if (pExtRate[i] & 0x80)
3074 BasicRateBitmap |= 0x0080;
3075 break;
3076 case 48:
3077 Rate = RATE_24; /*if (pExtRate[i] & 0x80) */
3078 BasicRateBitmap |= 0x0100;
3079 break;
3080 case 72:
3081 Rate = RATE_36;
3082 if (pExtRate[i] & 0x80)
3083 BasicRateBitmap |= 0x0200;
3084 break;
3085 case 96:
3086 Rate = RATE_48;
3087 if (pExtRate[i] & 0x80)
3088 BasicRateBitmap |= 0x0400;
3089 break;
3090 case 108:
3091 Rate = RATE_54;
3092 if (pExtRate[i] & 0x80)
3093 BasicRateBitmap |= 0x0800;
3094 break;
3095 default:
3096 Rate = RATE_1;
3097 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003098 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003099 if (MaxSupport < Rate)
3100 MaxSupport = Rate;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003101
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003102 if (MinSupport > Rate)
3103 MinSupport = Rate;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003104 }
3105
3106 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3107
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003108 /* bug fix */
3109 /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003110
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003111 /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */
3112 /* the DURATION field of outgoing uniicast DATA/MGMT frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003113 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003114 if (BasicRateBitmap & (0x01 << i))
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003115 CurrBasicRate = (u8)i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003116 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3117 }
3118
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003119 DBGPRINT(RT_DEBUG_TRACE,
3120 ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3121 RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003122 /* max tx rate = min {max desire rate, max supported rate} */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003123 if (MaxSupport < MaxDesire)
3124 pAd->CommonCfg.MaxTxRate = MaxSupport;
3125 else
3126 pAd->CommonCfg.MaxTxRate = MaxDesire;
3127
3128 pAd->CommonCfg.MinTxRate = MinSupport;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003129 /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */
3130 /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */
3131 /* on average RSSI */
3132 /* 1. RSSI >= -70db, start at 54 Mbps (short distance) */
3133 /* 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */
3134 /* 3. -75 > RSSI, start at 11 Mbps (long distance) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003135 if (*auto_rate_cur_p) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003136 short dbm = 0;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02003137
Bartlomiej Zolnierkiewicz5a911fd2009-04-26 16:06:04 +02003138 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
Bartlomiej Zolnierkiewicz6a28a69a2009-04-26 16:05:46 +02003139
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003140 if (bLinkUp == TRUE)
3141 pAd->CommonCfg.TxRate = RATE_24;
3142 else
3143 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3144
3145 if (dbm < -75)
3146 pAd->CommonCfg.TxRate = RATE_11;
3147 else if (dbm < -70)
3148 pAd->CommonCfg.TxRate = RATE_24;
3149
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003150 /* should never exceed MaxTxRate (consider 11B-only mode) */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003151 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3152 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3153
3154 pAd->CommonCfg.TxRateIndex = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003155 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003156 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003157 pHtPhy->field.MCS =
3158 (pAd->CommonCfg.MaxTxRate >
3159 3) ? (pAd->CommonCfg.MaxTxRate -
3160 4) : pAd->CommonCfg.MaxTxRate;
3161 pHtPhy->field.MODE =
3162 (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003163
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003164 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC =
3165 pHtPhy->field.STBC;
3166 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI =
3167 pHtPhy->field.ShortGI;
3168 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS =
3169 pHtPhy->field.MCS;
3170 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE =
3171 pHtPhy->field.MODE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003172 }
3173
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003174 if (pAd->CommonCfg.TxRate <= RATE_11) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003175 pMaxHtPhy->field.MODE = MODE_CCK;
3176 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3177 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003178 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003179 pMaxHtPhy->field.MODE = MODE_OFDM;
3180 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003181 if (pAd->CommonCfg.MinTxRate >= RATE_6
3182 && (pAd->CommonCfg.MinTxRate <= RATE_54)) {
3183 pMinHtPhy->field.MCS =
3184 OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
3185 } else {
3186 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3187 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003188 }
3189
3190 pHtPhy->word = (pMaxHtPhy->word);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003191 if (bLinkUp && (pAd->OpMode == OPMODE_STA)) {
3192 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3193 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word =
3194 pMaxHtPhy->word;
3195 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word =
3196 pMinHtPhy->word;
3197 } else {
3198 switch (pAd->CommonCfg.PhyMode) {
3199 case PHY_11BG_MIXED:
3200 case PHY_11B:
3201 case PHY_11BGN_MIXED:
3202 pAd->CommonCfg.MlmeRate = RATE_1;
3203 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3204 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003205
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003206/*#ifdef WIFI_TEST */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003207 pAd->CommonCfg.RtsRate = RATE_11;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003208/*#else */
3209/* pAd->CommonCfg.RtsRate = RATE_1; */
3210/*#endif */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003211 break;
3212 case PHY_11G:
3213 case PHY_11A:
3214 case PHY_11AGN_MIXED:
3215 case PHY_11GN_MIXED:
3216 case PHY_11N_2_4G:
3217 case PHY_11AN_MIXED:
3218 case PHY_11N_5G:
3219 pAd->CommonCfg.MlmeRate = RATE_6;
3220 pAd->CommonCfg.RtsRate = RATE_6;
3221 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3222 pAd->CommonCfg.MlmeTransmit.field.MCS =
3223 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3224 break;
3225 case PHY_11ABG_MIXED:
3226 case PHY_11ABGN_MIXED:
3227 if (pAd->CommonCfg.Channel <= 14) {
3228 pAd->CommonCfg.MlmeRate = RATE_1;
3229 pAd->CommonCfg.RtsRate = RATE_1;
3230 pAd->CommonCfg.MlmeTransmit.field.MODE =
3231 MODE_CCK;
3232 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3233 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003234 pAd->CommonCfg.MlmeRate = RATE_6;
3235 pAd->CommonCfg.RtsRate = RATE_6;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003236 pAd->CommonCfg.MlmeTransmit.field.MODE =
3237 MODE_OFDM;
3238 pAd->CommonCfg.MlmeTransmit.field.MCS =
3239 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3240 }
3241 break;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003242 default: /* error */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003243 pAd->CommonCfg.MlmeRate = RATE_6;
3244 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3245 pAd->CommonCfg.MlmeTransmit.field.MCS =
3246 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3247 pAd->CommonCfg.RtsRate = RATE_1;
3248 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003249 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003250 /* */
3251 /* Keep Basic Mlme Rate. */
3252 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003253 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word =
3254 pAd->CommonCfg.MlmeTransmit.word;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003255 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003256 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3257 OfdmRateToRxwiMCS[RATE_24];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003258 else
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003259 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3260 RATE_1;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003261 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3262 }
3263
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003264 DBGPRINT(RT_DEBUG_TRACE,
3265 (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3266 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
3267 RateIdToMbps[pAd->CommonCfg.MaxTxRate],
3268 RateIdToMbps[pAd->CommonCfg.MinTxRate],
3269 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3270 *auto_rate_cur_p));
3271 DBGPRINT(RT_DEBUG_TRACE,
3272 (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3273 RateIdToMbps[pAd->CommonCfg.TxRate],
3274 RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3275 DBGPRINT(RT_DEBUG_TRACE,
3276 ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3277 pAd->CommonCfg.MlmeTransmit.word,
3278 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
3279 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
3280 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003281}
3282
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003283/*
3284 ==========================================================================
3285 Description:
3286 This function update HT Rate setting.
3287 Input Wcid value is valid for 2 case :
3288 1. it's used for Station in infra mode that copy AP rate to Mactable.
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003289 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003290
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003291 IRQL = DISPATCH_LEVEL
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003292
3293 ==========================================================================
3294 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003295void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003296{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003297 u8 StbcMcs; /*j, StbcMcs, bitmask; */
3298 char i; /* 3*3 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003299 struct rt_ht_capability *pRtHtCap = NULL;
3300 struct rt_ht_phy_info *pActiveHtPhy = NULL;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003301 unsigned long BasicMCS;
3302 u8 j, bitmask;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003303 struct rt_ht_phy_info *pDesireHtPhy = NULL;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003304 PHTTRANSMIT_SETTING pHtPhy = NULL;
3305 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3306 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3307 BOOLEAN *auto_rate_cur_p;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003308
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003309 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003310
3311 auto_rate_cur_p = NULL;
3312
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003313 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003314 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3315 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3316 pHtPhy = &pAd->StaCfg.HTPhyMode;
3317 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3318 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003319
3320 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3321 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003322
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003323 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003324 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3325 return;
3326
3327 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3328 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003329 StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003330 BasicMCS =
3331 pAd->MlmeAux.AddHtInfo.MCSSet[0] +
3332 (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3333 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3334 && (pAd->Antenna.field.TxPath == 2))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003335 pMaxHtPhy->field.STBC = STBC_USE;
3336 else
3337 pMaxHtPhy->field.STBC = STBC_NONE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003338 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003339 if (pDesireHtPhy->bHtEnable == FALSE)
3340 return;
3341
3342 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003343 StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003344 BasicMCS =
3345 pAd->CommonCfg.AddHTInfo.MCSSet[0] +
3346 (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3347 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3348 && (pAd->Antenna.field.TxPath == 2))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003349 pMaxHtPhy->field.STBC = STBC_USE;
3350 else
3351 pMaxHtPhy->field.STBC = STBC_NONE;
3352 }
3353
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003354 /* Decide MAX ht rate. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003355 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3356 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3357 else
3358 pMaxHtPhy->field.MODE = MODE_HTMIX;
3359
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003360 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth)
3361 && (pRtHtCap->ChannelWidth))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003362 pMaxHtPhy->field.BW = BW_40;
3363 else
3364 pMaxHtPhy->field.BW = BW_20;
3365
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003366 if (pMaxHtPhy->field.BW == BW_20)
3367 pMaxHtPhy->field.ShortGI =
3368 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->
3369 ShortGIfor20);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003370 else
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003371 pMaxHtPhy->field.ShortGI =
3372 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->
3373 ShortGIfor40);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003374
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003375 if (pDesireHtPhy->MCSSet[4] != 0) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003376 pMaxHtPhy->field.MCS = 32;
3377 }
3378
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003379 for (i = 23; i >= 0; i--) /* 3*3 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003380 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003381 j = i / 8;
3382 bitmask = (1 << (i - (j * 8)));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003383
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003384 if ((pActiveHtPhy->MCSSet[j] & bitmask)
3385 && (pDesireHtPhy->MCSSet[j] & bitmask)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003386 pMaxHtPhy->field.MCS = i;
3387 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003388 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003389
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003390 if (i == 0)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003391 break;
3392 }
3393
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003394 /* Copy MIN ht rate. rt2860??? */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003395 pMinHtPhy->field.BW = BW_20;
3396 pMinHtPhy->field.MCS = 0;
3397 pMinHtPhy->field.STBC = 0;
3398 pMinHtPhy->field.ShortGI = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003399 /*If STA assigns fixed rate. update to fixed here. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003400 if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) {
3401 if (pDesireHtPhy->MCSSet[4] != 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003402 pMaxHtPhy->field.MCS = 32;
3403 pMinHtPhy->field.MCS = 32;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003404 DBGPRINT(RT_DEBUG_TRACE,
3405 ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3406 pMinHtPhy->field.MCS));
3407 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003408
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003409 for (i = 23; (char)i >= 0; i--) /* 3*3 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003410 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003411 j = i / 8;
3412 bitmask = (1 << (i - (j * 8)));
3413 if ((pDesireHtPhy->MCSSet[j] & bitmask)
3414 && (pActiveHtPhy->MCSSet[j] & bitmask)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003415 pMaxHtPhy->field.MCS = i;
3416 pMinHtPhy->field.MCS = i;
3417 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003418 }
3419 if (i == 0)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003420 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003421 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003422 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003423
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003424 /* Decide ht rate */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003425 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3426 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3427 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3428 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3429 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3430
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003431 /* use default now. rt2860 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003432 if (pDesireHtPhy->MCSSet[0] != 0xff)
3433 *auto_rate_cur_p = FALSE;
3434 else
3435 *auto_rate_cur_p = TRUE;
3436
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003437 DBGPRINT(RT_DEBUG_TRACE,
3438 (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n",
3439 pAd->CommonCfg.DesiredHtPhy.AmsduSize));
3440 DBGPRINT(RT_DEBUG_TRACE,
3441 ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n",
3442 pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW,
3443 pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3444 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003445}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003446
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003447void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003448{
3449 int i;
3450
3451 Tab->numAsOriginator = 0;
3452 Tab->numAsRecipient = 0;
3453 Tab->numDoneOriginator = 0;
3454 NdisAllocateSpinLock(&pAd->BATabLock);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003455 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003456 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3457 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3458 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003459 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003460 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3461 }
3462}
3463
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003464/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003465void MlmeRadioOff(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003466{
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003467 RTMP_MLME_RADIO_OFF(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003468}
3469
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003470/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003471void MlmeRadioOn(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003472{
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003473 RTMP_MLME_RADIO_ON(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003474}
3475
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003476/* =========================================================================================== */
3477/* bss_table.c */
3478/* =========================================================================================== */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003479
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003480/*! \brief initialize BSS table
3481 * \param p_tab pointer to the table
3482 * \return none
3483 * \pre
3484 * \post
3485
3486 IRQL = PASSIVE_LEVEL
3487 IRQL = DISPATCH_LEVEL
3488
3489 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003490void BssTableInit(struct rt_bss_table *Tab)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003491{
3492 int i;
3493
3494 Tab->BssNr = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003495 Tab->BssOverlapNr = 0;
3496 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003497 NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003498 Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003499 }
3500}
3501
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003502/*! \brief search the BSS table by SSID
3503 * \param p_tab pointer to the bss table
3504 * \param ssid SSID string
3505 * \return index of the table, BSS_NOT_FOUND if not in the table
3506 * \pre
3507 * \post
3508 * \note search by sequential search
3509
3510 IRQL = DISPATCH_LEVEL
3511
3512 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003513unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003514{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003515 u8 i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003516
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003517 for (i = 0; i < Tab->BssNr; i++) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003518 /* */
3519 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3520 /* We should distinguish this case. */
3521 /* */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003522 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003523 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3524 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003525 return i;
3526 }
3527 }
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003528 return (unsigned long)BSS_NOT_FOUND;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003529}
3530
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003531unsigned long BssSsidTableSearch(struct rt_bss_table *Tab,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003532 u8 *pBssid,
3533 u8 *pSsid, u8 SsidLen, u8 Channel)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003534{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003535 u8 i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003536
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003537 for (i = 0; i < Tab->BssNr; i++) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003538 /* */
3539 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3540 /* We should distinguish this case. */
3541 /* */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003542 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003543 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3544 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3545 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3546 Tab->BssEntry[i].SsidLen)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003547 return i;
3548 }
3549 }
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003550 return (unsigned long)BSS_NOT_FOUND;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003551}
3552
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003553unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003554 u8 *Bssid,
3555 u8 *pSsid,
3556 u8 SsidLen, u8 Channel)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003557{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003558 u8 i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003559
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003560 for (i = 0; i < Tab->BssNr; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003561 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003562 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3563 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3564 (SSID_EQUAL
3565 (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3566 Tab->BssEntry[i].SsidLen)
3567 || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen))
3568 ||
3569 (NdisEqualMemory
3570 (Tab->BssEntry[i].Ssid, ZeroSsid,
3571 Tab->BssEntry[i].SsidLen)))) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003572 return i;
3573 }
3574 }
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003575 return (unsigned long)BSS_NOT_FOUND;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003576}
3577
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003578unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003579 u8 *pSsid, u8 SsidLen)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003580{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003581 u8 i;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003582
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003583 for (i = 0; i < Tab->BssNr; i++) {
3584 if (SSID_EQUAL
3585 (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3586 Tab->BssEntry[i].SsidLen)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003587 return i;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003588 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003589 }
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003590 return (unsigned long)BSS_NOT_FOUND;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003591}
3592
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003593/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003594void BssTableDeleteEntry(struct rt_bss_table *Tab,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003595 u8 *pBssid, u8 Channel)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003596{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003597 u8 i, j;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003598
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003599 for (i = 0; i < Tab->BssNr; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003600 if ((Tab->BssEntry[i].Channel == Channel) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003601 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) {
3602 for (j = i; j < Tab->BssNr - 1; j++) {
3603 NdisMoveMemory(&(Tab->BssEntry[j]),
3604 &(Tab->BssEntry[j + 1]),
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003605 sizeof(struct rt_bss_entry));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003606 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003607 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]),
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003608 sizeof(struct rt_bss_entry));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003609 Tab->BssNr -= 1;
3610 return;
3611 }
3612 }
3613}
3614
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003615/*
3616 ========================================================================
3617 Routine Description:
3618 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3619
3620 Arguments:
3621 // IRQL = DISPATCH_LEVEL
3622 ========================================================================
3623*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003624void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd,
3625 struct rt_ba_ori_entry *pBAORIEntry)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003626{
3627
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003628 if (pBAORIEntry->ORI_BA_Status != Originator_NONE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003629 NdisAcquireSpinLock(&pAd->BATabLock);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003630 if (pBAORIEntry->ORI_BA_Status == Originator_Done) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003631 pAd->BATable.numAsOriginator -= 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003632 DBGPRINT(RT_DEBUG_TRACE,
3633 ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3634 pAd->BATable.numAsRecipient));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003635 /* Erase Bitmap flag. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003636 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003637 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID))); /* If STA mode, erase flag here */
3638 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; /* If STA mode, erase flag here */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003639 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3640 pBAORIEntry->Token = 1;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003641 /* Not clear Sequence here. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003642 NdisReleaseSpinLock(&pAd->BATabLock);
3643 }
3644}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003645
3646/*! \brief
3647 * \param
3648 * \return
3649 * \pre
3650 * \post
3651
3652 IRQL = DISPATCH_LEVEL
3653
3654 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003655void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * pCfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003656 u8 HtCapabilityLen,
3657 u8 AddHtInfoLen,
3658 u8 NewExtChanOffset,
3659 u8 Channel,
3660 char Rssi,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003661 IN LARGE_INTEGER TimeStamp,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003662 u8 CkipFlag,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003663 struct rt_edca_parm *pEdcaParm,
3664 struct rt_qos_capability_parm *pQosCapability,
3665 struct rt_qbss_load_parm *pQbssLoad,
3666 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003667{
3668 COPY_MAC_ADDR(pBss->Bssid, pBssid);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003669 /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003670 pBss->Hidden = 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003671 if (SsidLen > 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003672 /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */
3673 /* Or send beacon /probe response with SSID len matching real SSID length, */
3674 /* but SSID is all zero. such as "00-00-00-00" with length 4. */
3675 /* We have to prevent this case overwrite correct table */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003676 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) {
3677 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003678 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3679 pBss->SsidLen = SsidLen;
3680 pBss->Hidden = 0;
3681 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003682 } else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003683 pBss->SsidLen = 0;
3684 pBss->BssType = BssType;
3685 pBss->BeaconPeriod = BeaconPeriod;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003686 if (BssType == BSS_INFRA) {
3687 if (pCfParm->bValid) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003688 pBss->CfpCount = pCfParm->CfpCount;
3689 pBss->CfpPeriod = pCfParm->CfpPeriod;
3690 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3691 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3692 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003693 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003694 pBss->AtimWin = AtimWin;
3695 }
3696
3697 pBss->CapabilityInfo = CapabilityInfo;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003698 /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */
3699 /* Combine with AuthMode, they will decide the connection methods. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003700 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3701 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3702 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3703 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3704 else
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003705 NdisMoveMemory(pBss->SupRate, SupRate,
3706 MAX_LEN_OF_SUPPORTED_RATES);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003707 pBss->SupRateLen = SupRateLen;
3708 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3709 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003710 pBss->NewExtChanOffset = NewExtChanOffset;
3711 pBss->ExtRateLen = ExtRateLen;
3712 pBss->Channel = Channel;
3713 pBss->CentralChannel = Channel;
3714 pBss->Rssi = Rssi;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003715 /* Update CkipFlag. if not exists, the value is 0x0 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003716 pBss->CkipFlag = CkipFlag;
3717
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003718 /* New for microsoft Fixed IEs */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003719 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3720 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3721 pBss->FixIEs.Capabilities = CapabilityInfo;
3722
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003723 /* New for microsoft Variable IEs */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003724 if (LengthVIE != 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003725 pBss->VarIELen = LengthVIE;
3726 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003727 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003728 pBss->VarIELen = 0;
3729 }
3730
3731 pBss->AddHtInfoLen = 0;
3732 pBss->HtCapabilityLen = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003733 if (HtCapabilityLen > 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003734 pBss->HtCapabilityLen = HtCapabilityLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003735 NdisMoveMemory(&pBss->HtCapability, pHtCapability,
3736 HtCapabilityLen);
3737 if (AddHtInfoLen > 0) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003738 pBss->AddHtInfoLen = AddHtInfoLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003739 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo,
3740 AddHtInfoLen);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003741
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003742 if ((pAddHtInfo->ControlChan > 2)
3743 && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
3744 EXTCHA_BELOW)
3745 && (pHtCapability->HtCapInfo.ChannelWidth ==
3746 BW_40)) {
3747 pBss->CentralChannel =
3748 pAddHtInfo->ControlChan - 2;
3749 } else
3750 if ((pAddHtInfo->AddHtInfo.ExtChanOffset ==
3751 EXTCHA_ABOVE)
3752 && (pHtCapability->HtCapInfo.ChannelWidth ==
3753 BW_40)) {
3754 pBss->CentralChannel =
3755 pAddHtInfo->ControlChan + 2;
3756 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003757 }
3758 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003759
3760 BssCipherParse(pBss);
3761
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003762 /* new for QOS */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003763 if (pEdcaParm)
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003764 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003765 else
3766 pBss->EdcaParm.bValid = FALSE;
3767 if (pQosCapability)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003768 NdisMoveMemory(&pBss->QosCapability, pQosCapability,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003769 sizeof(struct rt_qos_capability_parm));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003770 else
3771 pBss->QosCapability.bValid = FALSE;
3772 if (pQbssLoad)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003773 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003774 sizeof(struct rt_qbss_load_parm));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003775 else
3776 pBss->QbssLoad.bValid = FALSE;
3777
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003778 {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003779 struct rt_eid * pEid;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003780 u16 Length = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003781
3782 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3783 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003784 pEid = (struct rt_eid *) pVIE;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003785 while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003786 switch (pEid->Eid) {
3787 case IE_WPA:
3788 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) {
3789 if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3790 pBss->WpaIE.IELen = 0;
3791 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003792 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003793 pBss->WpaIE.IELen = pEid->Len + 2;
3794 NdisMoveMemory(pBss->WpaIE.IE, pEid,
3795 pBss->WpaIE.IELen);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003796 }
3797 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003798 case IE_RSN:
3799 if (NdisEqualMemory
3800 (pEid->Octet + 2, RSN_OUI, 3)) {
3801 if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3802 pBss->RsnIE.IELen = 0;
3803 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003804 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003805 pBss->RsnIE.IELen = pEid->Len + 2;
3806 NdisMoveMemory(pBss->RsnIE.IE, pEid,
3807 pBss->RsnIE.IELen);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02003808 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003809 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003810 }
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003811 Length = Length + 2 + (u16)pEid->Len; /* Eid[1] + Len[1]+ content[Len] */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003812 pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003813 }
3814 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003815}
3816
3817/*!
3818 * \brief insert an entry into the bss table
3819 * \param p_tab The BSS table
3820 * \param Bssid BSSID
3821 * \param ssid SSID
3822 * \param ssid_len Length of SSID
3823 * \param bss_type
3824 * \param beacon_period
3825 * \param timestamp
3826 * \param p_cf
3827 * \param atim_win
3828 * \param cap
3829 * \param rates
3830 * \param rates_len
3831 * \param channel_idx
3832 * \return none
3833 * \pre
3834 * \post
3835 * \note If SSID is identical, the old entry will be replaced by the new one
3836
3837 IRQL = DISPATCH_LEVEL
3838
3839 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003840unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *Tab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003841 u8 HtCapabilityLen,
3842 u8 AddHtInfoLen,
3843 u8 NewExtChanOffset,
3844 u8 ChannelNo,
3845 char Rssi,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003846 IN LARGE_INTEGER TimeStamp,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003847 u8 CkipFlag,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003848 struct rt_edca_parm *pEdcaParm,
3849 struct rt_qos_capability_parm *pQosCapability,
3850 struct rt_qbss_load_parm *pQbssLoad,
3851 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003852{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003853 unsigned long Idx;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003854
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003855 Idx =
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003856 BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003857 ChannelNo);
3858 if (Idx == BSS_NOT_FOUND) {
3859 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003860 /* */
3861 /* It may happen when BSS Table was full. */
3862 /* The desired AP will not be added into BSS Table */
3863 /* In this case, if we found the desired AP then overwrite BSS Table. */
3864 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003865 if (!OPSTATUS_TEST_FLAG
3866 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
3867 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid)
3868 || SSID_EQUAL(pAd->MlmeAux.Ssid,
3869 pAd->MlmeAux.SsidLen, Ssid,
3870 SsidLen)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003871 Idx = Tab->BssOverlapNr;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003872 BssEntrySet(pAd, &Tab->BssEntry[Idx],
3873 pBssid, Ssid, SsidLen,
3874 BssType, BeaconPeriod,
3875 CfParm, AtimWin,
3876 CapabilityInfo, SupRate,
3877 SupRateLen, ExtRate,
3878 ExtRateLen, pHtCapability,
3879 pAddHtInfo, HtCapabilityLen,
3880 AddHtInfoLen,
3881 NewExtChanOffset, ChannelNo,
3882 Rssi, TimeStamp, CkipFlag,
3883 pEdcaParm, pQosCapability,
3884 pQbssLoad, LengthVIE, pVIE);
3885 Tab->BssOverlapNr =
3886 (Tab->BssOverlapNr++) %
3887 MAX_LEN_OF_BSS_TABLE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003888 }
3889 return Idx;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003890 } else {
3891 return BSS_NOT_FOUND;
3892 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003893 }
3894 Idx = Tab->BssNr;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003895 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen,
3896 BssType, BeaconPeriod, CfParm, AtimWin,
3897 CapabilityInfo, SupRate, SupRateLen, ExtRate,
3898 ExtRateLen, pHtCapability, pAddHtInfo,
3899 HtCapabilityLen, AddHtInfoLen, NewExtChanOffset,
3900 ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm,
3901 pQosCapability, pQbssLoad, LengthVIE, pVIE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003902 Tab->BssNr++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003903 } else {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003904 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003905 if ((SSID_EQUAL
3906 (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid,
3907 Tab->BssEntry[Idx].SsidLen))
3908 ||
3909 (NdisEqualMemory
3910 (Tab->BssEntry[Idx].Ssid, ZeroSsid,
3911 Tab->BssEntry[Idx].SsidLen))) {
3912 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid,
3913 SsidLen, BssType, BeaconPeriod, CfParm,
3914 AtimWin, CapabilityInfo, SupRate,
3915 SupRateLen, ExtRate, ExtRateLen,
3916 pHtCapability, pAddHtInfo, HtCapabilityLen,
3917 AddHtInfoLen, NewExtChanOffset, ChannelNo,
3918 Rssi, TimeStamp, CkipFlag, pEdcaParm,
3919 pQosCapability, pQbssLoad, LengthVIE, pVIE);
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02003920 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003921 }
3922
3923 return Idx;
3924}
3925
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003926/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003927void BssTableSsidSort(struct rt_rtmp_adapter *pAd,
3928 struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003929{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08003930 int i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003931 BssTableInit(OutTab);
3932
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003933 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003934 struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003935 BOOLEAN bIsHiddenApIncluded = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003936
3937 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003938 (pAd->MlmeAux.Channel > 14) &&
3939 RadarChannelCheck(pAd, pInBss->Channel))
3940 ) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003941 if (pInBss->Hidden)
3942 bIsHiddenApIncluded = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003943 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003944
3945 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003946 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen)
3947 || bIsHiddenApIncluded)) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08003948 struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
Bartlomiej Zolnierkiewicz16232672009-04-26 16:06:00 +02003949
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003950 /* 2.4G/5G N only mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003951 if ((pInBss->HtCapabilityLen == 0) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003952 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
3953 || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
3954 DBGPRINT(RT_DEBUG_TRACE,
3955 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003956 continue;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003957 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003958 /* New for WPA2 */
3959 /* Check the Authmode first */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003960 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003961 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003962 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
3963 && (pAd->StaCfg.AuthMode !=
3964 pInBss->AuthModeAux))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003965 /* None matched */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003966 continue;
3967
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003968 /* Check cipher suite, AP must have more secured cipher than station setting */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003969 if ((pAd->StaCfg.AuthMode ==
3970 Ndis802_11AuthModeWPA)
3971 || (pAd->StaCfg.AuthMode ==
3972 Ndis802_11AuthModeWPAPSK)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003973 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003974 if (pInBss->WPA.bMixMode == FALSE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003975 if (pAd->StaCfg.WepStatus !=
3976 pInBss->WPA.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003977 continue;
3978
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003979 /* check group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003980 if ((pAd->StaCfg.WepStatus <
3981 pInBss->WPA.GroupCipher)
3982 && (pInBss->WPA.GroupCipher !=
3983 Ndis802_11GroupWEP40Enabled)
3984 && (pInBss->WPA.GroupCipher !=
3985 Ndis802_11GroupWEP104Enabled))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003986 continue;
3987
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08003988 /* check pairwise cipher, skip if none matched */
3989 /* If profile set to AES, let it pass without question. */
3990 /* If profile set to TKIP, we must find one mateched */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003991 if ((pAd->StaCfg.WepStatus ==
3992 Ndis802_11Encryption2Enabled)
3993 && (pAd->StaCfg.WepStatus !=
3994 pInBss->WPA.PairCipher)
3995 && (pAd->StaCfg.WepStatus !=
3996 pInBss->WPA.PairCipherAux))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07003997 continue;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08003998 } else
3999 if ((pAd->StaCfg.AuthMode ==
4000 Ndis802_11AuthModeWPA2)
4001 || (pAd->StaCfg.AuthMode ==
4002 Ndis802_11AuthModeWPA2PSK)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004003 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004004 if (pInBss->WPA2.bMixMode == FALSE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004005 if (pAd->StaCfg.WepStatus !=
4006 pInBss->WPA2.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004007 continue;
4008
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004009 /* check group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004010 if ((pAd->StaCfg.WepStatus <
4011 pInBss->WPA.GroupCipher)
4012 && (pInBss->WPA2.GroupCipher !=
4013 Ndis802_11GroupWEP40Enabled)
4014 && (pInBss->WPA2.GroupCipher !=
4015 Ndis802_11GroupWEP104Enabled))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004016 continue;
4017
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004018 /* check pairwise cipher, skip if none matched */
4019 /* If profile set to AES, let it pass without question. */
4020 /* If profile set to TKIP, we must find one mateched */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004021 if ((pAd->StaCfg.WepStatus ==
4022 Ndis802_11Encryption2Enabled)
4023 && (pAd->StaCfg.WepStatus !=
4024 pInBss->WPA2.PairCipher)
4025 && (pAd->StaCfg.WepStatus !=
4026 pInBss->WPA2.PairCipherAux))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004027 continue;
4028 }
4029 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004030 /* Bss Type matched, SSID matched. */
4031 /* We will check wepstatus for qualification Bss */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004032 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) {
4033 DBGPRINT(RT_DEBUG_TRACE,
4034 ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4035 pAd->StaCfg.WepStatus,
4036 pInBss->WepStatus));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004037 /* */
4038 /* For the SESv2 case, we will not qualify WepStatus. */
4039 /* */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004040 if (!pInBss->bSES)
4041 continue;
4042 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004043 /* Since the AP is using hidden SSID, and we are trying to connect to ANY */
4044 /* It definitely will fail. So, skip it. */
4045 /* CCX also require not even try to connect it!! */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004046 if (SsidLen == 0)
4047 continue;
4048
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004049 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4050 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004051 if ((pInBss->CentralChannel != pInBss->Channel) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004052 (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4053 BW_40)) {
4054 if (RTMPCheckChannel
4055 (pAd, pInBss->CentralChannel,
4056 pInBss->Channel) == FALSE) {
4057 pAd->CommonCfg.RegTransmitSetting.field.
4058 BW = BW_20;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004059 SetCommonHT(pAd);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004060 pAd->CommonCfg.RegTransmitSetting.field.
4061 BW = BW_40;
4062 } else {
4063 if (pAd->CommonCfg.DesiredHtPhy.
4064 ChannelWidth == BAND_WIDTH_20) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004065 SetCommonHT(pAd);
4066 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004067 }
4068 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004069 /* copy matching BSS from InTab to OutTab */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004070 NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004071
4072 OutTab->BssNr++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004073 } else if ((pInBss->BssType == pAd->StaCfg.BssType)
4074 && (SsidLen == 0)) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004075 struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004076
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004077 /* 2.4G/5G N only mode */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004078 if ((pInBss->HtCapabilityLen == 0) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004079 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
4080 || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
4081 DBGPRINT(RT_DEBUG_TRACE,
4082 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004083 continue;
4084 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004085 /* New for WPA2 */
4086 /* Check the Authmode first */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004087 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004088 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004089 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
4090 && (pAd->StaCfg.AuthMode !=
4091 pInBss->AuthModeAux))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004092 /* None matched */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004093 continue;
4094
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004095 /* Check cipher suite, AP must have more secured cipher than station setting */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004096 if ((pAd->StaCfg.AuthMode ==
4097 Ndis802_11AuthModeWPA)
4098 || (pAd->StaCfg.AuthMode ==
4099 Ndis802_11AuthModeWPAPSK)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004100 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004101 if (pInBss->WPA.bMixMode == FALSE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004102 if (pAd->StaCfg.WepStatus !=
4103 pInBss->WPA.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004104 continue;
4105
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004106 /* check group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004107 if (pAd->StaCfg.WepStatus <
4108 pInBss->WPA.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004109 continue;
4110
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004111 /* check pairwise cipher, skip if none matched */
4112 /* If profile set to AES, let it pass without question. */
4113 /* If profile set to TKIP, we must find one mateched */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004114 if ((pAd->StaCfg.WepStatus ==
4115 Ndis802_11Encryption2Enabled)
4116 && (pAd->StaCfg.WepStatus !=
4117 pInBss->WPA.PairCipher)
4118 && (pAd->StaCfg.WepStatus !=
4119 pInBss->WPA.PairCipherAux))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004120 continue;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004121 } else
4122 if ((pAd->StaCfg.AuthMode ==
4123 Ndis802_11AuthModeWPA2)
4124 || (pAd->StaCfg.AuthMode ==
4125 Ndis802_11AuthModeWPA2PSK)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004126 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004127 if (pInBss->WPA2.bMixMode == FALSE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004128 if (pAd->StaCfg.WepStatus !=
4129 pInBss->WPA2.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004130 continue;
4131
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004132 /* check group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004133 if (pAd->StaCfg.WepStatus <
4134 pInBss->WPA2.GroupCipher)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004135 continue;
4136
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004137 /* check pairwise cipher, skip if none matched */
4138 /* If profile set to AES, let it pass without question. */
4139 /* If profile set to TKIP, we must find one mateched */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004140 if ((pAd->StaCfg.WepStatus ==
4141 Ndis802_11Encryption2Enabled)
4142 && (pAd->StaCfg.WepStatus !=
4143 pInBss->WPA2.PairCipher)
4144 && (pAd->StaCfg.WepStatus !=
4145 pInBss->WPA2.PairCipherAux))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004146 continue;
4147 }
4148 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004149 /* Bss Type matched, SSID matched. */
4150 /* We will check wepstatus for qualification Bss */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004151 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004152 continue;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004153
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004154 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4155 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004156 if ((pInBss->CentralChannel != pInBss->Channel) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004157 (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4158 BW_40)) {
4159 if (RTMPCheckChannel
4160 (pAd, pInBss->CentralChannel,
4161 pInBss->Channel) == FALSE) {
4162 pAd->CommonCfg.RegTransmitSetting.field.
4163 BW = BW_20;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004164 SetCommonHT(pAd);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004165 pAd->CommonCfg.RegTransmitSetting.field.
4166 BW = BW_40;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004167 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004168 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004169 /* copy matching BSS from InTab to OutTab */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004170 NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004171
4172 OutTab->BssNr++;
4173 }
4174
4175 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004176 break;
4177 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004178
4179 BssTableSortByRssi(OutTab);
4180}
4181
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004182/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004183void BssTableSortByRssi(struct rt_bss_table *OutTab)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004184{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004185 int i, j;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004186 struct rt_bss_entry TmpBss;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004187
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004188 for (i = 0; i < OutTab->BssNr - 1; i++) {
4189 for (j = i + 1; j < OutTab->BssNr; j++) {
4190 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) {
4191 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j],
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004192 sizeof(struct rt_bss_entry));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004193 NdisMoveMemory(&OutTab->BssEntry[j],
4194 &OutTab->BssEntry[i],
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004195 sizeof(struct rt_bss_entry));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004196 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004197 sizeof(struct rt_bss_entry));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004198 }
4199 }
4200 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004201}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004202
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004203void BssCipherParse(struct rt_bss_entry *pBss)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004204{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004205 struct rt_eid * pEid;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004206 u8 *pTmp;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004207 struct rt_rsn_ie_header * pRsnHeader;
4208 struct rt_cipher_suite_struct * pCipher;
4209 struct rt_akm_suite * pAKM;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004210 u16 Count;
4211 int Length;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004212 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004213
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004214 /* */
4215 /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */
4216 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004217 if (pBss->Privacy) {
4218 pBss->WepStatus = Ndis802_11WEPEnabled;
4219 } else {
4220 pBss->WepStatus = Ndis802_11WEPDisabled;
4221 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004222 /* Set default to disable & open authentication before parsing variable IE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004223 pBss->AuthMode = Ndis802_11AuthModeOpen;
4224 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004225
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004226 /* Init WPA setting */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004227 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004228 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004229 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004230 pBss->WPA.RsnCapability = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004231 pBss->WPA.bMixMode = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004232
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004233 /* Init WPA2 setting */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004234 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004235 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004236 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004237 pBss->WPA2.RsnCapability = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004238 pBss->WPA2.bMixMode = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004239
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004240 Length = (int)pBss->VarIELen;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004241
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004242 while (Length > 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004243 /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004244 pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004245 pEid = (struct rt_eid *) pTmp;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004246 switch (pEid->Eid) {
4247 case IE_WPA:
4248 if (NdisEqualMemory(pEid->Octet, SES_OUI, 3)
4249 && (pEid->Len == 7)) {
4250 pBss->bSES = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004251 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004252 } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) !=
4253 1) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004254 /* if unsupported vendor specific IE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004255 break;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004256 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004257 /* Skip OUI, version, and multicast suite */
4258 /* This part should be improved in the future when AP supported multiple cipher suite. */
4259 /* For now, it's OK since almost all APs have fixed cipher suite supported. */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004260 /* pTmp = (u8 *)pEid->Octet; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004261 pTmp += 11;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004262
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004263 /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
4264 /* Value Meaning */
4265 /* 0 None */
4266 /* 1 WEP-40 */
4267 /* 2 Tkip */
4268 /* 3 WRAP */
4269 /* 4 AES */
4270 /* 5 WEP-104 */
4271 /* Parse group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004272 switch (*pTmp) {
4273 case 1:
4274 pBss->WPA.GroupCipher =
4275 Ndis802_11GroupWEP40Enabled;
4276 break;
4277 case 5:
4278 pBss->WPA.GroupCipher =
4279 Ndis802_11GroupWEP104Enabled;
4280 break;
4281 case 2:
4282 pBss->WPA.GroupCipher =
4283 Ndis802_11Encryption2Enabled;
4284 break;
4285 case 4:
4286 pBss->WPA.GroupCipher =
4287 Ndis802_11Encryption3Enabled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004288 break;
4289 default:
4290 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004291 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004292 /* number of unicast suite */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004293 pTmp += 1;
4294
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004295 /* skip all unicast cipher suites */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004296 /*Count = *(u16 *)pTmp; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004297 Count = (pTmp[1] << 8) + pTmp[0];
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004298 pTmp += sizeof(u16);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004299
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004300 /* Parsing all unicast cipher suite */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004301 while (Count > 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004302 /* Skip OUI */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004303 pTmp += 3;
4304 TmpCipher = Ndis802_11WEPDisabled;
4305 switch (*pTmp) {
4306 case 1:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004307 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004308 TmpCipher =
4309 Ndis802_11Encryption1Enabled;
4310 break;
4311 case 2:
4312 TmpCipher =
4313 Ndis802_11Encryption2Enabled;
4314 break;
4315 case 4:
4316 TmpCipher =
4317 Ndis802_11Encryption3Enabled;
4318 break;
4319 default:
4320 break;
4321 }
4322 if (TmpCipher > pBss->WPA.PairCipher) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004323 /* Move the lower cipher suite to PairCipherAux */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004324 pBss->WPA.PairCipherAux =
4325 pBss->WPA.PairCipher;
4326 pBss->WPA.PairCipher = TmpCipher;
4327 } else {
4328 pBss->WPA.PairCipherAux = TmpCipher;
4329 }
4330 pTmp++;
4331 Count--;
4332 }
4333
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004334 /* 4. get AKM suite counts */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004335 /*Count = *(u16 *)pTmp; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004336 Count = (pTmp[1] << 8) + pTmp[0];
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004337 pTmp += sizeof(u16);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004338 pTmp += 3;
4339
4340 switch (*pTmp) {
4341 case 1:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004342 /* Set AP support WPA-enterprise mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004343 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4344 pBss->AuthMode = Ndis802_11AuthModeWPA;
4345 else
4346 pBss->AuthModeAux =
4347 Ndis802_11AuthModeWPA;
4348 break;
4349 case 2:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004350 /* Set AP support WPA-PSK mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004351 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4352 pBss->AuthMode =
4353 Ndis802_11AuthModeWPAPSK;
4354 else
4355 pBss->AuthModeAux =
4356 Ndis802_11AuthModeWPAPSK;
4357 break;
4358 default:
4359 break;
4360 }
4361 pTmp += 1;
4362
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004363 /* Fixed for WPA-None */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004364 if (pBss->BssType == BSS_ADHOC) {
4365 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4366 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4367 pBss->WepStatus = pBss->WPA.GroupCipher;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004368 /* Patched bugs for old driver */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004369 if (pBss->WPA.PairCipherAux ==
4370 Ndis802_11WEPDisabled)
4371 pBss->WPA.PairCipherAux =
4372 pBss->WPA.GroupCipher;
4373 } else
4374 pBss->WepStatus = pBss->WPA.PairCipher;
4375
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004376 /* Check the Pair & Group, if different, turn on mixed mode flag */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004377 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4378 pBss->WPA.bMixMode = TRUE;
4379
4380 break;
4381
4382 case IE_RSN:
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004383 pRsnHeader = (struct rt_rsn_ie_header *) pTmp;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004384
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004385 /* 0. Version must be 1 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004386 if (le2cpu16(pRsnHeader->Version) != 1)
4387 break;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004388 pTmp += sizeof(struct rt_rsn_ie_header);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004389
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004390 /* 1. Check group cipher */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004391 pCipher = (struct rt_cipher_suite_struct *) pTmp;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004392 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4393 break;
4394
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004395 /* Parse group cipher */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004396 switch (pCipher->Type) {
4397 case 1:
4398 pBss->WPA2.GroupCipher =
4399 Ndis802_11GroupWEP40Enabled;
4400 break;
4401 case 5:
4402 pBss->WPA2.GroupCipher =
4403 Ndis802_11GroupWEP104Enabled;
4404 break;
4405 case 2:
4406 pBss->WPA2.GroupCipher =
4407 Ndis802_11Encryption2Enabled;
4408 break;
4409 case 4:
4410 pBss->WPA2.GroupCipher =
4411 Ndis802_11Encryption3Enabled;
4412 break;
4413 default:
4414 break;
4415 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004416 /* set to correct offset for next parsing */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004417 pTmp += sizeof(struct rt_cipher_suite_struct);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004418
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004419 /* 2. Get pairwise cipher counts */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004420 /*Count = *(u16 *)pTmp; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004421 Count = (pTmp[1] << 8) + pTmp[0];
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004422 pTmp += sizeof(u16);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004423
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004424 /* 3. Get pairwise cipher */
4425 /* Parsing all unicast cipher suite */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004426 while (Count > 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004427 /* Skip OUI */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004428 pCipher = (struct rt_cipher_suite_struct *) pTmp;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004429 TmpCipher = Ndis802_11WEPDisabled;
4430 switch (pCipher->Type) {
4431 case 1:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004432 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004433 TmpCipher =
4434 Ndis802_11Encryption1Enabled;
4435 break;
4436 case 2:
4437 TmpCipher =
4438 Ndis802_11Encryption2Enabled;
4439 break;
4440 case 4:
4441 TmpCipher =
4442 Ndis802_11Encryption3Enabled;
4443 break;
4444 default:
4445 break;
4446 }
4447 if (TmpCipher > pBss->WPA2.PairCipher) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004448 /* Move the lower cipher suite to PairCipherAux */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004449 pBss->WPA2.PairCipherAux =
4450 pBss->WPA2.PairCipher;
4451 pBss->WPA2.PairCipher = TmpCipher;
4452 } else {
4453 pBss->WPA2.PairCipherAux = TmpCipher;
4454 }
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004455 pTmp += sizeof(struct rt_cipher_suite_struct);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004456 Count--;
4457 }
4458
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004459 /* 4. get AKM suite counts */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004460 /*Count = *(u16 *)pTmp; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004461 Count = (pTmp[1] << 8) + pTmp[0];
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004462 pTmp += sizeof(u16);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004463
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004464 /* 5. Get AKM ciphers */
4465 /* Parsing all AKM ciphers */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004466 while (Count > 0) {
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004467 pAKM = (struct rt_akm_suite *) pTmp;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004468 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4469 break;
4470
4471 switch (pAKM->Type) {
4472 case 1:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004473 /* Set AP support WPA-enterprise mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004474 if (pBss->AuthMode ==
4475 Ndis802_11AuthModeOpen)
4476 pBss->AuthMode =
4477 Ndis802_11AuthModeWPA2;
4478 else
4479 pBss->AuthModeAux =
4480 Ndis802_11AuthModeWPA2;
4481 break;
4482 case 2:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004483 /* Set AP support WPA-PSK mode */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004484 if (pBss->AuthMode ==
4485 Ndis802_11AuthModeOpen)
4486 pBss->AuthMode =
4487 Ndis802_11AuthModeWPA2PSK;
4488 else
4489 pBss->AuthModeAux =
4490 Ndis802_11AuthModeWPA2PSK;
4491 break;
4492 default:
4493 if (pBss->AuthMode ==
4494 Ndis802_11AuthModeOpen)
4495 pBss->AuthMode =
4496 Ndis802_11AuthModeMax;
4497 else
4498 pBss->AuthModeAux =
4499 Ndis802_11AuthModeMax;
4500 break;
4501 }
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004502 pTmp += (Count * sizeof(struct rt_akm_suite));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004503 Count--;
4504 }
4505
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004506 /* Fixed for WPA-None */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004507 if (pBss->BssType == BSS_ADHOC) {
4508 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4509 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4510 pBss->WPA.PairCipherAux =
4511 pBss->WPA2.PairCipherAux;
4512 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4513 pBss->WepStatus = pBss->WPA.GroupCipher;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004514 /* Patched bugs for old driver */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004515 if (pBss->WPA.PairCipherAux ==
4516 Ndis802_11WEPDisabled)
4517 pBss->WPA.PairCipherAux =
4518 pBss->WPA.GroupCipher;
4519 }
4520 pBss->WepStatus = pBss->WPA2.PairCipher;
4521
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004522 /* 6. Get RSN capability */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004523 /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004524 pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0];
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004525 pTmp += sizeof(u16);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004526
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004527 /* Check the Pair & Group, if different, turn on mixed mode flag */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004528 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4529 pBss->WPA2.bMixMode = TRUE;
4530
4531 break;
4532 default:
4533 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004534 }
4535 Length -= (pEid->Len + 2);
4536 }
4537}
4538
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004539/* =========================================================================================== */
4540/* mac_table.c */
4541/* =========================================================================================== */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004542
4543/*! \brief generates a random mac address value for IBSS BSSID
4544 * \param Addr the bssid location
4545 * \return none
4546 * \pre
4547 * \post
4548 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004549void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004550{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004551 int i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004552
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004553 for (i = 0; i < MAC_ADDR_LEN; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004554 pAddr[i] = RandomByte(pAd);
4555 }
4556
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004557 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004558}
4559
4560/*! \brief init the management mac frame header
4561 * \param p_hdr mac header
4562 * \param subtype subtype of the frame
4563 * \param p_ds destination address, don't care if it is a broadcast address
4564 * \return none
4565 * \pre the station has the following information in the pAd->StaCfg
4566 * - bssid
4567 * - station address
4568 * \post
4569 * \note this function initializes the following field
4570
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004571 IRQL = PASSIVE_LEVEL
4572 IRQL = DISPATCH_LEVEL
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004573
4574 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004575void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd,
4576 struct rt_header_802_11 * pHdr80211,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004577 u8 SubType,
4578 u8 ToDs, u8 *pDA, u8 *pBssid)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004579{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004580 NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004581
4582 pHdr80211->FC.Type = BTYPE_MGMT;
4583 pHdr80211->FC.SubType = SubType;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004584/* if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type */
4585/* pHdr80211->FC.Type = BTYPE_CNTL; */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004586 pHdr80211->FC.ToDs = ToDs;
4587 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004588 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004589 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4590}
4591
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004592/* =========================================================================================== */
4593/* mem_mgmt.c */
4594/* =========================================================================================== */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004595
4596/*!***************************************************************************
4597 * This routine build an outgoing frame, and fill all information specified
4598 * in argument list to the frame body. The actual frame size is the summation
4599 * of all arguments.
4600 * input params:
4601 * Buffer - pointer to a pre-allocated memory segment
4602 * args - a list of <int arg_size, arg> pairs.
4603 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4604 * function will FAIL!!!
4605 * return:
4606 * Size of the buffer
4607 * usage:
4608 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4609
4610 IRQL = PASSIVE_LEVEL
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004611 IRQL = DISPATCH_LEVEL
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004612
4613 ****************************************************************************/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004614unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004615{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004616 u8 *p;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004617 int leng;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004618 unsigned long TotLeng;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004619 va_list Args;
4620
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004621 /* calculates the total length */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004622 TotLeng = 0;
4623 va_start(Args, FrameLen);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004624 do {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004625 leng = va_arg(Args, int);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004626 if (leng == END_OF_ARGS) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004627 break;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004628 }
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004629 p = va_arg(Args, void *);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004630 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4631 TotLeng = TotLeng + leng;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004632 } while (TRUE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004633
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004634 va_end(Args); /* clean up */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004635 *FrameLen = TotLeng;
4636 return TotLeng;
4637}
4638
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004639/* =========================================================================================== */
4640/* mlme_queue.c */
4641/* =========================================================================================== */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004642
4643/*! \brief Initialize The MLME Queue, used by MLME Functions
4644 * \param *Queue The MLME Queue
4645 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4646 * \pre
4647 * \post
4648 * \note Because this is done only once (at the init stage), no need to be locked
4649
4650 IRQL = PASSIVE_LEVEL
4651
4652 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004653int MlmeQueueInit(struct rt_mlme_queue *Queue)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004654{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004655 int i;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004656
4657 NdisAllocateSpinLock(&Queue->Lock);
4658
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004659 Queue->Num = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004660 Queue->Head = 0;
4661 Queue->Tail = 0;
4662
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004663 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004664 Queue->Entry[i].Occupied = FALSE;
4665 Queue->Entry[i].MsgLen = 0;
4666 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4667 }
4668
4669 return NDIS_STATUS_SUCCESS;
4670}
4671
4672/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4673 * \param *Queue The MLME Queue
4674 * \param Machine The State Machine Id
4675 * \param MsgType The Message Type
4676 * \param MsgLen The Message length
4677 * \param *Msg The message pointer
4678 * \return TRUE if enqueue is successful, FALSE if the queue is full
4679 * \pre
4680 * \post
4681 * \note The message has to be initialized
4682
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004683 IRQL = PASSIVE_LEVEL
4684 IRQL = DISPATCH_LEVEL
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004685
4686 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004687BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004688 unsigned long Machine,
4689 unsigned long MsgType, unsigned long MsgLen, void * Msg)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004690{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004691 int Tail;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004692 struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004693
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004694 /* Do nothing if the driver is starting halt state. */
4695 /* This might happen when timer already been fired before cancel timer with mlmehalt */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004696 if (RTMP_TEST_FLAG
4697 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004698 return FALSE;
4699
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004700 /* First check the size, it MUST not exceed the mlme queue size */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004701 if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4702 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n",
4703 MsgLen));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004704 return FALSE;
4705 }
4706
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004707 if (MlmeQueueFull(Queue)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004708 return FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004709 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004710
4711 NdisAcquireSpinLock(&(Queue->Lock));
4712 Tail = Queue->Tail;
4713 Queue->Tail++;
4714 Queue->Num++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004715 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004716 Queue->Tail = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004717 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004718
4719 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4720 Queue->Entry[Tail].Occupied = TRUE;
4721 Queue->Entry[Tail].Machine = Machine;
4722 Queue->Entry[Tail].MsgType = MsgType;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004723 Queue->Entry[Tail].MsgLen = MsgLen;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004724
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004725 if (Msg != NULL) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004726 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004727 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004728
4729 NdisReleaseSpinLock(&(Queue->Lock));
4730 return TRUE;
4731}
4732
4733/*! \brief This function is used when Recv gets a MLME message
4734 * \param *Queue The MLME Queue
4735 * \param TimeStampHigh The upper 32 bit of timestamp
4736 * \param TimeStampLow The lower 32 bit of timestamp
4737 * \param Rssi The receiving RSSI strength
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004738 * \param MsgLen The length of the message
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004739 * \param *Msg The message pointer
4740 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4741 * \pre
4742 * \post
4743
4744 IRQL = DISPATCH_LEVEL
4745
4746 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004747BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004748 unsigned long Wcid,
4749 unsigned long TimeStampHigh,
4750 unsigned long TimeStampLow,
4751 u8 Rssi0,
4752 u8 Rssi1,
4753 u8 Rssi2,
4754 unsigned long MsgLen, void * Msg, u8 Signal)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004755{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004756 int Tail, Machine;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004757 struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004758 int MsgType;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004759 struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004760
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004761 /* Do nothing if the driver is starting halt state. */
4762 /* This might happen when timer already been fired before cancel timer with mlmehalt */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004763 if (RTMP_TEST_FLAG
4764 (pAd,
4765 fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004766 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4767 return FALSE;
4768 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004769 /* First check the size, it MUST not exceed the mlme queue size */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004770 if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004771 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4772 return FALSE;
4773 }
4774
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004775 if (MlmeQueueFull(Queue)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004776 return FALSE;
4777 }
4778
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004779 {
4780 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) {
4781 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004782 return FALSE;
4783 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004784 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004785
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004786 /* OK, we got all the informations, it is time to put things into queue */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004787 NdisAcquireSpinLock(&(Queue->Lock));
4788 Tail = Queue->Tail;
4789 Queue->Tail++;
4790 Queue->Num++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004791 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004792 Queue->Tail = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004793 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004794 Queue->Entry[Tail].Occupied = TRUE;
4795 Queue->Entry[Tail].Machine = Machine;
4796 Queue->Entry[Tail].MsgType = MsgType;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004797 Queue->Entry[Tail].MsgLen = MsgLen;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004798 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4799 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4800 Queue->Entry[Tail].Rssi0 = Rssi0;
4801 Queue->Entry[Tail].Rssi1 = Rssi1;
4802 Queue->Entry[Tail].Rssi2 = Rssi2;
4803 Queue->Entry[Tail].Signal = Signal;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004804 Queue->Entry[Tail].Wcid = (u8)Wcid;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004805
4806 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4807
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004808 if (Msg != NULL) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004809 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4810 }
4811
4812 NdisReleaseSpinLock(&(Queue->Lock));
4813
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004814 RTMP_MLME_HANDLER(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004815
4816 return TRUE;
4817}
4818
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004819/*! \brief Dequeue a message from the MLME Queue
4820 * \param *Queue The MLME Queue
4821 * \param *Elem The message dequeued from MLME Queue
4822 * \return TRUE if the Elem contains something, FALSE otherwise
4823 * \pre
4824 * \post
4825
4826 IRQL = DISPATCH_LEVEL
4827
4828 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004829BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004830{
4831 NdisAcquireSpinLock(&(Queue->Lock));
4832 *Elem = &(Queue->Entry[Queue->Head]);
4833 Queue->Num--;
4834 Queue->Head++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004835 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004836 Queue->Head = 0;
4837 }
4838 NdisReleaseSpinLock(&(Queue->Lock));
4839 return TRUE;
4840}
4841
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004842/* IRQL = DISPATCH_LEVEL */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004843void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004844{
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004845#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004846 struct rt_mlme_queue_elem *Elem = NULL;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004847#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004848 BOOLEAN Cancelled;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004849
4850 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4851
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004852#ifdef RTMP_MAC_PCI
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004853 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004854 if (pAd->Mlme.bRunning) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004855 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4856 return;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004857 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004858 pAd->Mlme.bRunning = TRUE;
4859 }
4860 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4861
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004862 /* Remove all Mlme queues elements */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004863 while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004864 /*From message type, determine which state machine I should drive */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004865 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004866 /* free MLME element */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004867 Elem->Occupied = FALSE;
4868 Elem->MsgLen = 0;
4869
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004870 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004871 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004872 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004873 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004874#endif /* RTMP_MAC_PCI // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004875
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004876 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004877 /* Cancel all timer events */
4878 /* Be careful to cancel new added timer */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004879 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4880 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4881 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4882 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4883 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4884 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004885
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004886 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004887
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004888 /* Change back to original channel in case of doing scan */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004889 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4890 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4891
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004892 /* Resume MSDU which is turned off durning scan */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004893 RTMPResumeMsduTransmission(pAd);
4894
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004895 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004896 /* Set all state machines back IDLE */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004897 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4898 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4899 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004900 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004901 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4902 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004903 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004904
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004905#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004906 /* Remove running state */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004907 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4908 pAd->Mlme.bRunning = FALSE;
4909 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004910#endif /* RTMP_MAC_PCI // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004911}
4912
4913/*! \brief test if the MLME Queue is empty
4914 * \param *Queue The MLME Queue
4915 * \return TRUE if the Queue is empty, FALSE otherwise
4916 * \pre
4917 * \post
4918
4919 IRQL = DISPATCH_LEVEL
4920
4921 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004922BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004923{
4924 BOOLEAN Ans;
4925
4926 NdisAcquireSpinLock(&(Queue->Lock));
4927 Ans = (Queue->Num == 0);
4928 NdisReleaseSpinLock(&(Queue->Lock));
4929
4930 return Ans;
4931}
4932
4933/*! \brief test if the MLME Queue is full
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02004934 * \param *Queue The MLME Queue
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004935 * \return TRUE if the Queue is empty, FALSE otherwise
4936 * \pre
4937 * \post
4938
4939 IRQL = PASSIVE_LEVEL
4940 IRQL = DISPATCH_LEVEL
4941
4942 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004943BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004944{
4945 BOOLEAN Ans;
4946
4947 NdisAcquireSpinLock(&(Queue->Lock));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004948 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE
4949 || Queue->Entry[Queue->Tail].Occupied);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004950 NdisReleaseSpinLock(&(Queue->Lock));
4951
4952 return Ans;
4953}
4954
4955/*! \brief The destructor of MLME Queue
4956 * \param
4957 * \return
4958 * \pre
4959 * \post
4960 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4961
4962 IRQL = PASSIVE_LEVEL
4963
4964 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004965void MlmeQueueDestroy(struct rt_mlme_queue *pQueue)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004966{
4967 NdisAcquireSpinLock(&(pQueue->Lock));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004968 pQueue->Num = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004969 pQueue->Head = 0;
4970 pQueue->Tail = 0;
4971 NdisReleaseSpinLock(&(pQueue->Lock));
4972 NdisFreeSpinLock(&(pQueue->Lock));
4973}
4974
4975/*! \brief To substitute the message type if the message is coming from external
4976 * \param pFrame The frame received
4977 * \param *Machine The state machine
4978 * \param *MsgType the message type for the state machine
4979 * \return TRUE if the substitution is successful, FALSE otherwise
4980 * \pre
4981 * \post
4982
4983 IRQL = DISPATCH_LEVEL
4984
4985 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08004986BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd,
4987 struct rt_frame_802_11 * pFrame,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004988 int * Machine, int * MsgType)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004989{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004990 u16 Seq, Alg;
4991 u8 EAPType;
4992 u8 *pData;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004993
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004994 /* Pointer to start of data frames including SNAP header */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08004995 pData = (u8 *)pFrame + LENGTH_802_11;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004996
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08004997 /* The only data type will pass to this function is EAPOL frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08004998 if (pFrame->Hdr.FC.Type == BTYPE_DATA) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07004999 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005000 *Machine = WPA_STATE_MACHINE;
5001 EAPType =
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005002 *((u8 *) pFrame + LENGTH_802_11 +
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005003 LENGTH_802_1_H + 1);
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005004 return (WpaMsgTypeSubst(EAPType, (int *) MsgType));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005005 }
5006 }
5007
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005008 switch (pFrame->Hdr.FC.SubType) {
5009 case SUBTYPE_ASSOC_REQ:
5010 *Machine = ASSOC_STATE_MACHINE;
5011 *MsgType = MT2_PEER_ASSOC_REQ;
5012 break;
5013 case SUBTYPE_ASSOC_RSP:
5014 *Machine = ASSOC_STATE_MACHINE;
5015 *MsgType = MT2_PEER_ASSOC_RSP;
5016 break;
5017 case SUBTYPE_REASSOC_REQ:
5018 *Machine = ASSOC_STATE_MACHINE;
5019 *MsgType = MT2_PEER_REASSOC_REQ;
5020 break;
5021 case SUBTYPE_REASSOC_RSP:
5022 *Machine = ASSOC_STATE_MACHINE;
5023 *MsgType = MT2_PEER_REASSOC_RSP;
5024 break;
5025 case SUBTYPE_PROBE_REQ:
5026 *Machine = SYNC_STATE_MACHINE;
5027 *MsgType = MT2_PEER_PROBE_REQ;
5028 break;
5029 case SUBTYPE_PROBE_RSP:
5030 *Machine = SYNC_STATE_MACHINE;
5031 *MsgType = MT2_PEER_PROBE_RSP;
5032 break;
5033 case SUBTYPE_BEACON:
5034 *Machine = SYNC_STATE_MACHINE;
5035 *MsgType = MT2_PEER_BEACON;
5036 break;
5037 case SUBTYPE_ATIM:
5038 *Machine = SYNC_STATE_MACHINE;
5039 *MsgType = MT2_PEER_ATIM;
5040 break;
5041 case SUBTYPE_DISASSOC:
5042 *Machine = ASSOC_STATE_MACHINE;
5043 *MsgType = MT2_PEER_DISASSOC_REQ;
5044 break;
5045 case SUBTYPE_AUTH:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005046 /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005047 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16));
5048 NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16));
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005049 if (Seq == 1 || Seq == 3) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005050 *Machine = AUTH_RSP_STATE_MACHINE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005051 *MsgType = MT2_PEER_AUTH_ODD;
5052 } else if (Seq == 2 || Seq == 4) {
5053 if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) {
5054 *Machine = AUTH_STATE_MACHINE;
5055 *MsgType = MT2_PEER_AUTH_EVEN;
5056 }
5057 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005058 return FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005059 }
5060 break;
5061 case SUBTYPE_DEAUTH:
5062 *Machine = AUTH_RSP_STATE_MACHINE;
5063 *MsgType = MT2_PEER_DEAUTH;
5064 break;
5065 case SUBTYPE_ACTION:
5066 *Machine = ACTION_STATE_MACHINE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005067 /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005068 if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) {
5069 *MsgType = MT2_ACT_INVALID;
5070 } else {
5071 *MsgType = (pFrame->Octet[0] & 0x7F);
5072 }
5073 break;
5074 default:
5075 return FALSE;
5076 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005077 }
5078
5079 return TRUE;
5080}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005081
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005082/* =========================================================================================== */
5083/* state_machine.c */
5084/* =========================================================================================== */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005085
5086/*! \brief Initialize the state machine.
5087 * \param *S pointer to the state machine
5088 * \param Trans State machine transition function
5089 * \param StNr number of states
5090 * \param MsgNr number of messages
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005091 * \param DefFunc default function, when there is invalid state/message combination
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005092 * \param InitState initial state of the state machine
5093 * \param Base StateMachine base, internal use only
5094 * \pre p_sm should be a legal pointer
5095 * \post
5096
5097 IRQL = PASSIVE_LEVEL
5098
5099 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005100void StateMachineInit(struct rt_state_machine *S,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005101 IN STATE_MACHINE_FUNC Trans[],
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005102 unsigned long StNr,
5103 unsigned long MsgNr,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005104 IN STATE_MACHINE_FUNC DefFunc,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005105 unsigned long InitState, unsigned long Base)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005106{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005107 unsigned long i, j;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005108
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005109 /* set number of states and messages */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005110 S->NrState = StNr;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005111 S->NrMsg = MsgNr;
5112 S->Base = Base;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005113
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005114 S->TransFunc = Trans;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005115
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005116 /* init all state transition to default function */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005117 for (i = 0; i < StNr; i++) {
5118 for (j = 0; j < MsgNr; j++) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005119 S->TransFunc[i * MsgNr + j] = DefFunc;
5120 }
5121 }
5122
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005123 /* set the starting state */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005124 S->CurrState = InitState;
5125}
5126
5127/*! \brief This function fills in the function pointer into the cell in the state machine
5128 * \param *S pointer to the state machine
5129 * \param St state
5130 * \param Msg incoming message
5131 * \param f the function to be executed when (state, message) combination occurs at the state machine
5132 * \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
5133 * \post
5134
5135 IRQL = PASSIVE_LEVEL
5136
5137 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005138void StateMachineSetAction(struct rt_state_machine *S,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005139 unsigned long St,
5140 unsigned long Msg, IN STATE_MACHINE_FUNC Func)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005141{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005142 unsigned long MsgIdx;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005143
5144 MsgIdx = Msg - S->Base;
5145
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005146 if (St < S->NrState && MsgIdx < S->NrMsg) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005147 /* boundary checking before setting the action */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005148 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5149 }
5150}
5151
5152/*! \brief This function does the state transition
5153 * \param *Adapter the NIC adapter pointer
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005154 * \param *S the state machine
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005155 * \param *Elem the message to be executed
5156 * \return None
5157
5158 IRQL = DISPATCH_LEVEL
5159
5160 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005161void StateMachinePerformAction(struct rt_rtmp_adapter *pAd,
5162 struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005163{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005164 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))
5165 (pAd, Elem);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005166}
5167
5168/*
5169 ==========================================================================
5170 Description:
5171 The drop function, when machine executes this, the message is simply
5172 ignored. This function does nothing, the message is freed in
5173 StateMachinePerformAction()
5174 ==========================================================================
5175 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005176void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005177{
5178}
5179
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005180/* =========================================================================================== */
5181/* lfsr.c */
5182/* =========================================================================================== */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005183
5184/*
5185 ==========================================================================
5186 Description:
5187
5188 IRQL = PASSIVE_LEVEL
5189
5190 ==========================================================================
5191 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005192void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005193{
5194 if (Seed == 0)
5195 pAd->Mlme.ShiftReg = 1;
5196 else
5197 pAd->Mlme.ShiftReg = Seed;
5198}
5199
5200/*
5201 ==========================================================================
5202 Description:
5203 ==========================================================================
5204 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005205u8 RandomByte(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005206{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005207 unsigned long i;
5208 u8 R, Result;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005209
5210 R = 0;
5211
5212 if (pAd->Mlme.ShiftReg == 0)
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005213 NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005214
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005215 for (i = 0; i < 8; i++) {
5216 if (pAd->Mlme.ShiftReg & 0x00000001) {
5217 pAd->Mlme.ShiftReg =
5218 ((pAd->Mlme.
5219 ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005220 Result = 1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005221 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005222 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5223 Result = 0;
5224 }
5225 R = (R << 1) | Result;
5226 }
5227
5228 return R;
5229}
5230
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005231/*
5232 ========================================================================
5233
5234 Routine Description:
5235 Verify the support rate for different PHY type
5236
5237 Arguments:
5238 pAd Pointer to our adapter
5239
5240 Return Value:
5241 None
5242
5243 IRQL = PASSIVE_LEVEL
5244
5245 ========================================================================
5246*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005247void RTMPCheckRates(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005248 IN u8 SupRate[], IN u8 * SupRateLen)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005249{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005250 u8 RateIdx, i, j;
5251 u8 NewRate[12], NewRateLen;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005252
5253 NewRateLen = 0;
5254
5255 if (pAd->CommonCfg.PhyMode == PHY_11B)
5256 RateIdx = 4;
5257 else
5258 RateIdx = 12;
5259
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005260 /* Check for support rates exclude basic rate bit */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005261 for (i = 0; i < *SupRateLen; i++)
5262 for (j = 0; j < RateIdx; j++)
5263 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5264 NewRate[NewRateLen++] = SupRate[i];
5265
5266 *SupRateLen = NewRateLen;
5267 NdisMoveMemory(SupRate, NewRate, NewRateLen);
5268}
5269
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005270BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005271 u8 CentralChannel, u8 Channel)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005272{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005273 u8 k;
5274 u8 UpperChannel = 0, LowerChannel = 0;
5275 u8 NoEffectChannelinList = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005276
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005277 /* Find upper and lower channel according to 40MHz current operation. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005278 if (CentralChannel < Channel) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005279 UpperChannel = Channel;
5280 if (CentralChannel > 2)
5281 LowerChannel = CentralChannel - 2;
5282 else
5283 return FALSE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005284 } else if (CentralChannel > Channel) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005285 UpperChannel = CentralChannel + 2;
5286 LowerChannel = Channel;
5287 }
5288
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005289 for (k = 0; k < pAd->ChannelListNum; k++) {
5290 if (pAd->ChannelList[k].Channel == UpperChannel) {
5291 NoEffectChannelinList++;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005292 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005293 if (pAd->ChannelList[k].Channel == LowerChannel) {
5294 NoEffectChannelinList++;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005295 }
5296 }
5297
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005298 DBGPRINT(RT_DEBUG_TRACE,
5299 ("Total Channel in Channel List = [%d]\n",
5300 NoEffectChannelinList));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005301 if (NoEffectChannelinList == 2)
5302 return TRUE;
5303 else
5304 return FALSE;
5305}
5306
5307/*
5308 ========================================================================
5309
5310 Routine Description:
5311 Verify the support rate for HT phy type
5312
5313 Arguments:
5314 pAd Pointer to our adapter
5315
5316 Return Value:
5317 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
5318
5319 IRQL = PASSIVE_LEVEL
5320
5321 ========================================================================
5322*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005323BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005324 u8 Wcid,
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005325 struct rt_ht_capability_ie * pHtCapability,
5326 struct rt_add_ht_info_ie * pAddHtInfo)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005327{
5328 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5329 return FALSE;
5330
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005331 /* If use AMSDU, set flag. */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005332 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005333 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5334 fCLIENT_STATUS_AMSDU_INUSED);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005335 /* Save Peer Capability */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005336 if (pHtCapability->HtCapInfo.ShortGIfor20)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005337 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5338 fCLIENT_STATUS_SGI20_CAPABLE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005339 if (pHtCapability->HtCapInfo.ShortGIfor40)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005340 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5341 fCLIENT_STATUS_SGI40_CAPABLE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005342 if (pHtCapability->HtCapInfo.TxSTBC)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005343 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5344 fCLIENT_STATUS_TxSTBC_CAPABLE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005345 if (pHtCapability->HtCapInfo.RxSTBC)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005346 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5347 fCLIENT_STATUS_RxSTBC_CAPABLE);
5348 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) {
5349 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5350 fCLIENT_STATUS_RDG_CAPABLE);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005351 }
5352
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005353 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
5354 pAd->MacTab.Content[Wcid].MpduDensity =
5355 pHtCapability->HtCapParm.MpduDensity;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005356 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005357 /* Will check ChannelWidth for MCSSet[4] below */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005358 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005359 switch (pAd->CommonCfg.RxStream) {
5360 case 1:
5361 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5362 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5363 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5364 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5365 break;
5366 case 2:
5367 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5368 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5369 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5370 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5371 break;
5372 case 3:
5373 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5374 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5375 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5376 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5377 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005378 }
5379
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005380 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth =
5381 pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.
5382 ChannelWidth;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005383
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005384 DBGPRINT(RT_DEBUG_TRACE,
5385 ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5386 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth,
5387 pAddHtInfo->AddHtInfo.RecomWidth,
5388 pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5389 pAd->NicConfig2.field.BW40MAvailForA,
5390 pAd->NicConfig2.field.BW40MAvailForG,
5391 pAd->CommonCfg.PhyMode));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005392
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005393 pAd->MlmeAux.HtCapability.HtCapInfo.GF =
5394 pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005395
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005396 /* Send Assoc Req with my HT capability. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005397 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =
5398 pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5399 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =
5400 pAd->CommonCfg.DesiredHtPhy.MimoPs;
5401 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =
5402 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->
5403 HtCapInfo.
5404 ShortGIfor20);
5405 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =
5406 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->
5407 HtCapInfo.
5408 ShortGIfor40);
5409 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =
5410 (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo.
5411 RxSTBC);
5412 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =
5413 (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo.
5414 TxSTBC);
5415 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor =
5416 pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5417 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity =
5418 pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5419 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC =
5420 pHtCapability->ExtHtCapInfo.PlusHTC;
5421 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC =
5422 pHtCapability->ExtHtCapInfo.PlusHTC;
5423 if (pAd->CommonCfg.bRdg) {
5424 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport =
5425 pHtCapability->ExtHtCapInfo.RDGSupport;
5426 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005427 }
5428
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005429 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005430 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; /* BW20 can't transmit MCS32 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005431
5432 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5433 return TRUE;
5434}
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005435
5436/*
5437 ========================================================================
5438
5439 Routine Description:
5440 Verify the support rate for different PHY type
5441
5442 Arguments:
5443 pAd Pointer to our adapter
5444
5445 Return Value:
5446 None
5447
5448 IRQL = PASSIVE_LEVEL
5449
5450 ========================================================================
5451*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005452void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005453{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005454 u8 MinimumRate;
5455 u8 ProperMlmeRate; /*= RATE_54; */
5456 u8 i, j, RateIdx = 12; /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005457 BOOLEAN bMatch = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005458
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005459 switch (pAd->CommonCfg.PhyMode) {
5460 case PHY_11B:
5461 ProperMlmeRate = RATE_11;
5462 MinimumRate = RATE_1;
5463 break;
5464 case PHY_11BG_MIXED:
5465 case PHY_11ABGN_MIXED:
5466 case PHY_11BGN_MIXED:
5467 if ((pAd->MlmeAux.SupRateLen == 4) &&
5468 (pAd->MlmeAux.ExtRateLen == 0))
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005469 /* B only AP */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005470 ProperMlmeRate = RATE_11;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005471 else
5472 ProperMlmeRate = RATE_24;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005473
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005474 if (pAd->MlmeAux.Channel <= 14)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005475 MinimumRate = RATE_1;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005476 else
5477 MinimumRate = RATE_6;
5478 break;
5479 case PHY_11A:
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005480 case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005481 case PHY_11GN_MIXED:
5482 case PHY_11AGN_MIXED:
5483 case PHY_11AN_MIXED:
5484 case PHY_11N_5G:
5485 ProperMlmeRate = RATE_24;
5486 MinimumRate = RATE_6;
5487 break;
5488 case PHY_11ABG_MIXED:
5489 ProperMlmeRate = RATE_24;
5490 if (pAd->MlmeAux.Channel <= 14)
5491 MinimumRate = RATE_1;
5492 else
5493 MinimumRate = RATE_6;
5494 break;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005495 default: /* error */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005496 ProperMlmeRate = RATE_1;
5497 MinimumRate = RATE_1;
5498 break;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005499 }
5500
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005501 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) {
5502 for (j = 0; j < RateIdx; j++) {
5503 if ((pAd->MlmeAux.SupRate[i] & 0x7f) ==
5504 RateIdTo500Kbps[j]) {
5505 if (j == ProperMlmeRate) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005506 bMatch = TRUE;
5507 break;
5508 }
5509 }
5510 }
5511
5512 if (bMatch)
5513 break;
5514 }
5515
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005516 if (bMatch == FALSE) {
5517 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) {
5518 for (j = 0; j < RateIdx; j++) {
5519 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) ==
5520 RateIdTo500Kbps[j]) {
5521 if (j == ProperMlmeRate) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005522 bMatch = TRUE;
5523 break;
5524 }
5525 }
5526 }
5527
5528 if (bMatch)
5529 break;
5530 }
5531 }
5532
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005533 if (bMatch == FALSE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005534 ProperMlmeRate = MinimumRate;
5535 }
5536
5537 pAd->CommonCfg.MlmeRate = MinimumRate;
5538 pAd->CommonCfg.RtsRate = ProperMlmeRate;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005539 if (pAd->CommonCfg.MlmeRate >= RATE_6) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005540 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005541 pAd->CommonCfg.MlmeTransmit.field.MCS =
5542 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5543 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5544 MODE_OFDM;
5545 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5546 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5547 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005548 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5549 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005550 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5551 MODE_CCK;
5552 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5553 pAd->CommonCfg.MlmeRate;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005554 }
5555
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005556 DBGPRINT(RT_DEBUG_TRACE,
5557 ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n",
5558 pAd->CommonCfg.MlmeTransmit.word));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005559}
5560
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005561char RTMPMaxRssi(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005562 char Rssi0, char Rssi1, char Rssi2)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005563{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005564 char larger = -127;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005565
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005566 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005567 larger = Rssi0;
5568 }
5569
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005570 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005571 larger = max(Rssi0, Rssi1);
5572 }
5573
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005574 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005575 larger = max(larger, Rssi2);
5576 }
5577
5578 if (larger == -127)
5579 larger = 0;
5580
5581 return larger;
5582}
5583
5584/*
5585 ========================================================================
5586 Routine Description:
5587 Periodic evaluate antenna link status
5588
5589 Arguments:
5590 pAd - Adapter pointer
5591
5592 Return Value:
5593 None
5594
5595 ========================================================================
5596*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005597void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005598{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005599 u8 BBPR3 = 0;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005600
Bartlomiej Zolnierkiewicze932e722009-08-16 21:31:17 +02005601 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005602 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5603 fRTMP_ADAPTER_RADIO_OFF |
5604 fRTMP_ADAPTER_NIC_NOT_EXIST |
5605 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5606 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005607#ifdef RT30xx
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005608 || (pAd->EepromAccess)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005609#endif /* RT30xx // */
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +02005610#ifdef RT3090
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005611 || (pAd->bPCIclkOff == TRUE)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005612#endif /* RT3090 // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005613 )
5614 return;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005615
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005616 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005617 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5618 /* return; */
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005619
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005620 {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005621
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005622 if (pAd->StaCfg.Psm == PWR_SAVE)
5623 return;
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005624
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005625 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5626 BBPR3 &= (~0x18);
5627 if (pAd->Antenna.field.RxPath == 3) {
5628 BBPR3 |= (0x10);
5629 } else if (pAd->Antenna.field.RxPath == 2) {
5630 BBPR3 |= (0x8);
5631 } else if (pAd->Antenna.field.RxPath == 1) {
5632 BBPR3 |= (0x0);
5633 }
5634 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005635#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005636 pAd->StaCfg.BBPR3 = BBPR3;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005637#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005638 if (OPSTATUS_TEST_FLAG
5639 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5640 ) {
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005641 unsigned long TxTotalCnt =
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005642 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5643 pAd->RalinkCounters.OneSecTxRetryOkCount +
5644 pAd->RalinkCounters.OneSecTxFailCount;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005645
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005646 /* dynamic adjust antenna evaluation period according to the traffic */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005647 if (TxTotalCnt > 50) {
5648 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5649 20);
5650 pAd->Mlme.bLowThroughput = FALSE;
5651 } else {
5652 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5653 300);
5654 pAd->Mlme.bLowThroughput = TRUE;
5655 }
5656 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005657 }
5658
5659 }
5660
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005661}
5662
5663/*
5664 ========================================================================
5665 Routine Description:
5666 After evaluation, check antenna link status
5667
5668 Arguments:
5669 pAd - Adapter pointer
5670
5671 Return Value:
5672 None
5673
5674 ========================================================================
5675*/
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005676void AsicRxAntEvalTimeout(void *SystemSpecific1,
5677 void *FunctionContext,
5678 void *SystemSpecific2, void *SystemSpecific3)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005679{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005680 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005681 u8 BBPR3 = 0;
5682 char larger = -127, rssi0, rssi1, rssi2;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005683
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005684 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5685 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5686 fRTMP_ADAPTER_RADIO_OFF |
5687 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5688 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005689#ifdef RT30xx
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005690 || (pAd->EepromAccess)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005691#endif /* RT30xx // */
Bartlomiej Zolnierkiewicze44fd1c2009-09-22 20:44:24 +02005692#ifdef RT3090
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005693 || (pAd->bPCIclkOff == TRUE)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005694#endif /* RT3090 // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005695 )
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005696 return;
5697
5698 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005699 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5700 /* return; */
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005701 {
5702 if (pAd->StaCfg.Psm == PWR_SAVE)
5703 return;
5704
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005705 /* if the traffic is low, use average rssi as the criteria */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005706 if (pAd->Mlme.bLowThroughput == TRUE) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005707 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5708 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5709 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005710 } else {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005711 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5712 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5713 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5714 }
5715
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005716 if (pAd->Antenna.field.RxPath == 3) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005717 larger = max(rssi0, rssi1);
5718
5719 if (larger > (rssi2 + 20))
5720 pAd->Mlme.RealRxPath = 2;
5721 else
5722 pAd->Mlme.RealRxPath = 3;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005723 } else if (pAd->Antenna.field.RxPath == 2) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005724 if (rssi0 > (rssi1 + 20))
5725 pAd->Mlme.RealRxPath = 1;
5726 else
5727 pAd->Mlme.RealRxPath = 2;
5728 }
5729
5730 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5731 BBPR3 &= (~0x18);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005732 if (pAd->Mlme.RealRxPath == 3) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005733 BBPR3 |= (0x10);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005734 } else if (pAd->Mlme.RealRxPath == 2) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005735 BBPR3 |= (0x8);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005736 } else if (pAd->Mlme.RealRxPath == 1) {
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005737 BBPR3 |= (0x0);
5738 }
5739 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005740#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz331e0c12009-08-23 15:28:52 +02005741 pAd->StaCfg.BBPR3 = BBPR3;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005742#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005743 }
5744 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005745
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005746}
5747
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005748void APSDPeriodicExec(void *SystemSpecific1,
5749 void *FunctionContext,
5750 void *SystemSpecific2, void *SystemSpecific3)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005751{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005752 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005753
5754 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5755 return;
5756
5757 pAd->CommonCfg.TriggerTimerCount++;
5758
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005759/* Driver should not send trigger frame, it should be send by application layer */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005760/*
5761 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5762 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5763 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5764 {
5765 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5766 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5767 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5768 pAd->CommonCfg.TriggerTimerCount = 0;
5769 pAd->CommonCfg.bInServicePeriod = TRUE;
5770 }*/
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005771}
5772
5773/*
5774 ========================================================================
5775 Routine Description:
5776 Set/reset MAC registers according to bPiggyBack parameter
5777
5778 Arguments:
5779 pAd - Adapter pointer
5780 bPiggyBack - Enable / Disable Piggy-Back
5781
5782 Return Value:
5783 None
5784
5785 ========================================================================
5786*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005787void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005788{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005789 TX_LINK_CFG_STRUC TxLinkCfg;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005790
5791 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5792
5793 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5794 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5795}
5796
5797/*
5798 ========================================================================
5799 Routine Description:
5800 check if this entry need to switch rate automatically
5801
5802 Arguments:
5803 pAd
5804 pEntry
5805
5806 Return Value:
5807 TURE
5808 FALSE
5809
5810 ========================================================================
5811*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005812BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd,
5813 struct rt_mac_table_entry *pEntry)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005814{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005815 BOOLEAN result = TRUE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005816
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005817 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005818 /* only associated STA counts */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005819 if (pEntry && (pEntry->ValidAsCLI)
5820 && (pEntry->Sst == SST_ASSOC)) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005821 result = pAd->StaCfg.bAutoTxRateSwitch;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005822 } else
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005823 result = FALSE;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005824 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005825
5826 return result;
5827}
5828
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005829BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005830{
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005831 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005832 if (pAd->StaCfg.bAutoTxRateSwitch)
5833 return TRUE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005834 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005835 return FALSE;
5836}
5837
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005838/*
5839 ========================================================================
5840 Routine Description:
5841 check if this entry need to fix tx legacy rate
5842
5843 Arguments:
5844 pAd
5845 pEntry
5846
5847 Return Value:
5848 TURE
5849 FALSE
5850
5851 ========================================================================
5852*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005853u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005854{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005855 u8 tx_mode = FIXED_TXMODE_HT;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005856
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005857 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005858 tx_mode =
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005859 (u8)pAd->StaCfg.DesiredTransmitSetting.field.
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005860 FixedTxMode;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005861 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005862
5863 return tx_mode;
5864}
5865
5866/*
5867 ========================================================================
5868 Routine Description:
5869 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5870
5871 Arguments:
5872 pAd
5873 pEntry
5874
5875 Return Value:
5876 TURE
5877 FALSE
5878
5879 ========================================================================
5880*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005881void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005882{
5883 HTTRANSMIT_SETTING TransmitSetting;
5884
5885 if (fixed_tx_mode == FIXED_TXMODE_HT)
5886 return;
5887
5888 TransmitSetting.word = 0;
5889
5890 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5891 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5892
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005893 if (fixed_tx_mode == FIXED_TXMODE_CCK) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005894 TransmitSetting.field.MODE = MODE_CCK;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005895 /* CCK mode allow MCS 0~3 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005896 if (TransmitSetting.field.MCS > MCS_3)
5897 TransmitSetting.field.MCS = MCS_3;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005898 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005899 TransmitSetting.field.MODE = MODE_OFDM;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005900 /* OFDM mode allow MCS 0~7 */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005901 if (TransmitSetting.field.MCS > MCS_7)
5902 TransmitSetting.field.MCS = MCS_7;
5903 }
5904
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005905 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005906 pEntry->HTPhyMode.word = TransmitSetting.word;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005907 DBGPRINT(RT_DEBUG_TRACE,
5908 ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5909 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE),
5910 pEntry->HTPhyMode.field.MCS));
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005911 }
5912}
5913
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005914/*
5915 ==========================================================================
5916 Description:
5917 dynamic tune BBP R66 to find a balance between sensibility and
5918 noise isolation
5919
5920 IRQL = DISPATCH_LEVEL
5921
5922 ==========================================================================
5923 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08005924void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005925{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08005926 u8 OrigR66Value = 0, R66; /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */
5927 char Rssi;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005928
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005929 /* 2860C did not support Fase CCA, therefore can't tune */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005930 if (pAd->MACVersion == 0x28600100)
5931 return;
5932
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005933 /* */
5934 /* work as a STA */
5935 /* */
5936 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) /* no R66 tuning when SCANNING */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005937 return;
5938
5939 if ((pAd->OpMode == OPMODE_STA)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005940 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5941 )
5942 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005943#ifdef RTMP_MAC_PCI
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005944 && (pAd->bPCIclkOff == FALSE)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005945#endif /* RTMP_MAC_PCI // */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005946 ) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005947 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5948 R66 = OrigR66Value;
5949
5950 if (pAd->Antenna.field.RxPath > 1)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005951 Rssi =
5952 (pAd->StaCfg.RssiSample.AvgRssi0 +
5953 pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005954 else
5955 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5956
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005957 if (pAd->LatchRfRegs.Channel <= 14) { /*BG band */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005958#ifdef RT30xx
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005959 /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */
5960 /* Otherwise, it will have some throughput side effect when low RSSI */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02005961
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005962 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
5963 || IS_RT3390(pAd)) {
5964 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5965 R66 =
5966 0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20;
5967 if (OrigR66Value != R66) {
5968 RTMP_BBP_IO_WRITE8_BY_REG_ID
5969 (pAd, BBP_R66, R66);
5970 }
5971 } else {
5972 R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
5973 if (OrigR66Value != R66) {
5974 RTMP_BBP_IO_WRITE8_BY_REG_ID
5975 (pAd, BBP_R66, R66);
5976 }
Bartlomiej Zolnierkiewicz59fe2d82009-04-26 16:06:28 +02005977 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005978 } else
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005979#endif /* RT30xx // */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005980 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005981 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005982 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005983 if (OrigR66Value != R66) {
5984 RTMP_BBP_IO_WRITE8_BY_REG_ID
5985 (pAd, BBP_R66, R66);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005986 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005987 } else {
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07005988 R66 = 0x2E + GET_LNA_GAIN(pAd);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005989 if (OrigR66Value != R66) {
5990 RTMP_BBP_IO_WRITE8_BY_REG_ID
5991 (pAd, BBP_R66, R66);
5992 }
5993 }
5994 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08005995 } else { /*A band */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08005996 if (pAd->CommonCfg.BBPCurrentBW == BW_20) {
5997 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5998 R66 =
5999 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 +
6000 0x10;
6001 if (OrigR66Value != R66) {
6002 RTMP_BBP_IO_WRITE8_BY_REG_ID
6003 (pAd, BBP_R66, R66);
6004 }
6005 } else {
6006 R66 =
6007 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3;
6008 if (OrigR66Value != R66) {
6009 RTMP_BBP_IO_WRITE8_BY_REG_ID
6010 (pAd, BBP_R66, R66);
6011 }
6012 }
6013 } else {
6014 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6015 R66 =
6016 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 +
6017 0x10;
6018 if (OrigR66Value != R66) {
6019 RTMP_BBP_IO_WRITE8_BY_REG_ID
6020 (pAd, BBP_R66, R66);
6021 }
6022 } else {
6023 R66 =
6024 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3;
6025 if (OrigR66Value != R66) {
6026 RTMP_BBP_IO_WRITE8_BY_REG_ID
6027 (pAd, BBP_R66, R66);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006028 }
6029 }
6030 }
6031 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006032
6033 }
6034}
Adam McDanieled291e82009-02-23 08:01:07 -07006035
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08006036void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth)
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006037{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08006038 u8 R66 = 0x30;
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006039
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08006040 if (pAd->LatchRfRegs.Channel <= 14) { /* BG band */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02006041#ifdef RT30xx
6042 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6043
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08006044 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
6045 || IS_RT3390(pAd)) {
6046 R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02006047 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08006048 } else
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08006049#endif /* RT30xx // */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02006050 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08006051 R66 = 0x2E + GET_LNA_GAIN(pAd);
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006052 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6053 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08006054 } else { /*A band */
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006055 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08006056 if (BandWidth == BW_20) {
6057 R66 =
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08006058 (u8)(0x32 +
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08006059 (GET_LNA_GAIN(pAd) * 5) / 3);
6060 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6061 } else {
6062 R66 =
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08006063 (u8)(0x3A +
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08006064 (GET_LNA_GAIN(pAd) * 5) / 3);
6065 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6066 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006067 }
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006068 }
Bartlomiej Zolnierkiewicz37843392009-08-16 21:30:57 +02006069
Greg Kroah-Hartman91980992008-10-28 14:48:09 -07006070}