]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/rt2860/common/mlme.c
Fix common misspellings
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / rt2860 / common / mlme.c
CommitLineData
91980990
GKH
1/*
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>
97eea3af 41#include <linux/kernel.h>
91980990 42
51126deb
BZ
43u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 };
44
45u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
46u8 RSN_OUI[] = { 0x00, 0x0f, 0xac };
47u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
48u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
49u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 };
50u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 };
51u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c };
52u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
53u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c };
54
55u8 RateSwitchTable[] = {
ec278fa2
BZ
56/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
57 0x11, 0x00, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
58 0x00, 0x00, 0, 40, 101,
59 0x01, 0x00, 1, 40, 50,
60 0x02, 0x00, 2, 35, 45,
61 0x03, 0x00, 3, 20, 45,
62 0x04, 0x21, 0, 30, 50,
63 0x05, 0x21, 1, 20, 50,
64 0x06, 0x21, 2, 20, 50,
65 0x07, 0x21, 3, 15, 50,
66 0x08, 0x21, 4, 15, 30,
67 0x09, 0x21, 5, 10, 25,
68 0x0a, 0x21, 6, 8, 25,
69 0x0b, 0x21, 7, 8, 25,
70 0x0c, 0x20, 12, 15, 30,
71 0x0d, 0x20, 13, 8, 20,
72 0x0e, 0x20, 14, 8, 20,
73 0x0f, 0x20, 15, 8, 25,
74 0x10, 0x22, 15, 8, 25,
75 0x11, 0x00, 0, 0, 0,
76 0x12, 0x00, 0, 0, 0,
77 0x13, 0x00, 0, 0, 0,
78 0x14, 0x00, 0, 0, 0,
79 0x15, 0x00, 0, 0, 0,
80 0x16, 0x00, 0, 0, 0,
81 0x17, 0x00, 0, 0, 0,
82 0x18, 0x00, 0, 0, 0,
83 0x19, 0x00, 0, 0, 0,
84 0x1a, 0x00, 0, 0, 0,
85 0x1b, 0x00, 0, 0, 0,
86 0x1c, 0x00, 0, 0, 0,
87 0x1d, 0x00, 0, 0, 0,
88 0x1e, 0x00, 0, 0, 0,
89 0x1f, 0x00, 0, 0, 0,
91980990
GKH
90};
91
51126deb 92u8 RateSwitchTable11B[] = {
ec278fa2
BZ
93/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
94 0x04, 0x03, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
95 0x00, 0x00, 0, 40, 101,
96 0x01, 0x00, 1, 40, 50,
97 0x02, 0x00, 2, 35, 45,
98 0x03, 0x00, 3, 20, 45,
91980990
GKH
99};
100
51126deb 101u8 RateSwitchTable11BG[] = {
ec278fa2
BZ
102/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
103 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
104 0x00, 0x00, 0, 40, 101,
105 0x01, 0x00, 1, 40, 50,
106 0x02, 0x00, 2, 35, 45,
107 0x03, 0x00, 3, 20, 45,
108 0x04, 0x10, 2, 20, 35,
109 0x05, 0x10, 3, 16, 35,
110 0x06, 0x10, 4, 10, 25,
111 0x07, 0x10, 5, 16, 25,
112 0x08, 0x10, 6, 10, 25,
113 0x09, 0x10, 7, 10, 13,
91980990
GKH
114};
115
51126deb 116u8 RateSwitchTable11G[] = {
ec278fa2
BZ
117/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
118 0x08, 0x00, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
119 0x00, 0x10, 0, 20, 101,
120 0x01, 0x10, 1, 20, 35,
121 0x02, 0x10, 2, 20, 35,
122 0x03, 0x10, 3, 16, 35,
123 0x04, 0x10, 4, 10, 25,
124 0x05, 0x10, 5, 16, 25,
125 0x06, 0x10, 6, 10, 25,
126 0x07, 0x10, 7, 10, 13,
91980990
GKH
127};
128
51126deb 129u8 RateSwitchTable11N1S[] = {
ec278fa2
BZ
130/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
131 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
132 0x00, 0x00, 0, 40, 101,
133 0x01, 0x00, 1, 40, 50,
134 0x02, 0x00, 2, 25, 45,
135 0x03, 0x21, 0, 20, 35,
136 0x04, 0x21, 1, 20, 35,
137 0x05, 0x21, 2, 20, 35,
138 0x06, 0x21, 3, 15, 35,
139 0x07, 0x21, 4, 15, 30,
140 0x08, 0x21, 5, 10, 25,
141 0x09, 0x21, 6, 8, 14,
142 0x0a, 0x21, 7, 8, 14,
143 0x0b, 0x23, 7, 8, 14,
91980990
GKH
144};
145
51126deb 146u8 RateSwitchTable11N2S[] = {
ec278fa2
BZ
147/* 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) */
148 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
149 0x00, 0x00, 0, 40, 101,
150 0x01, 0x00, 1, 40, 50,
151 0x02, 0x00, 2, 25, 45,
152 0x03, 0x21, 0, 20, 35,
153 0x04, 0x21, 1, 20, 35,
154 0x05, 0x21, 2, 20, 35,
155 0x06, 0x21, 3, 15, 35,
156 0x07, 0x21, 4, 15, 30,
157 0x08, 0x20, 11, 15, 30,
158 0x09, 0x20, 12, 15, 30,
159 0x0a, 0x20, 13, 8, 20,
160 0x0b, 0x20, 14, 8, 20,
161 0x0c, 0x20, 15, 8, 25,
162 0x0d, 0x22, 15, 8, 15,
91980990
GKH
163};
164
51126deb 165u8 RateSwitchTable11N3S[] = {
ec278fa2
BZ
166/* 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) */
167 0x0b, 0x00, 0, 0, 0, /* 0x0a, 0x00, 0, 0, 0, // Initial used item after association */
96b3c83d
BZ
168 0x00, 0x21, 0, 30, 101,
169 0x01, 0x21, 1, 20, 50,
170 0x02, 0x21, 2, 20, 50,
171 0x03, 0x21, 3, 15, 50,
172 0x04, 0x21, 4, 15, 30,
ec278fa2
BZ
173 0x05, 0x20, 11, 15, 30, /* Required by System-Alan @ 20080812 */
174 0x06, 0x20, 12, 15, 30, /* 0x05, 0x20, 12, 15, 30, */
175 0x07, 0x20, 13, 8, 20, /* 0x06, 0x20, 13, 8, 20, */
176 0x08, 0x20, 14, 8, 20, /* 0x07, 0x20, 14, 8, 20, */
177 0x09, 0x20, 15, 8, 25, /* 0x08, 0x20, 15, 8, 25, */
178 0x0a, 0x22, 15, 8, 25, /* 0x09, 0x22, 15, 8, 25, */
91980990
GKH
179};
180
51126deb 181u8 RateSwitchTable11N2SForABand[] = {
ec278fa2
BZ
182/* 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) */
183 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
184 0x00, 0x21, 0, 30, 101,
185 0x01, 0x21, 1, 20, 50,
186 0x02, 0x21, 2, 20, 50,
187 0x03, 0x21, 3, 15, 50,
188 0x04, 0x21, 4, 15, 30,
189 0x05, 0x21, 5, 15, 30,
190 0x06, 0x20, 12, 15, 30,
191 0x07, 0x20, 13, 8, 20,
192 0x08, 0x20, 14, 8, 20,
193 0x09, 0x20, 15, 8, 25,
194 0x0a, 0x22, 15, 8, 25,
91980990
GKH
195};
196
51126deb 197u8 RateSwitchTable11N3SForABand[] = { /* 3*3 */
ec278fa2
BZ
198/* 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) */
199 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
200 0x00, 0x21, 0, 30, 101,
201 0x01, 0x21, 1, 20, 50,
202 0x02, 0x21, 2, 20, 50,
203 0x03, 0x21, 3, 15, 50,
204 0x04, 0x21, 4, 15, 30,
205 0x05, 0x21, 5, 15, 30,
206 0x06, 0x20, 12, 15, 30,
207 0x07, 0x20, 13, 8, 20,
208 0x08, 0x20, 14, 8, 20,
209 0x09, 0x20, 15, 8, 25,
210 0x0a, 0x22, 15, 8, 25,
91980990
GKH
211};
212
51126deb 213u8 RateSwitchTable11BGN1S[] = {
ec278fa2
BZ
214/* 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) */
215 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
216 0x00, 0x00, 0, 40, 101,
217 0x01, 0x00, 1, 40, 50,
218 0x02, 0x00, 2, 25, 45,
219 0x03, 0x21, 0, 20, 35,
220 0x04, 0x21, 1, 20, 35,
221 0x05, 0x21, 2, 20, 35,
222 0x06, 0x21, 3, 15, 35,
223 0x07, 0x21, 4, 15, 30,
224 0x08, 0x21, 5, 10, 25,
225 0x09, 0x21, 6, 8, 14,
226 0x0a, 0x21, 7, 8, 14,
227 0x0b, 0x23, 7, 8, 14,
91980990
GKH
228};
229
51126deb 230u8 RateSwitchTable11BGN2S[] = {
ec278fa2
BZ
231/* 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) */
232 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
233 0x00, 0x00, 0, 40, 101,
234 0x01, 0x00, 1, 40, 50,
235 0x02, 0x00, 2, 25, 45,
236 0x03, 0x21, 0, 20, 35,
237 0x04, 0x21, 1, 20, 35,
238 0x05, 0x21, 2, 20, 35,
239 0x06, 0x21, 3, 15, 35,
240 0x07, 0x21, 4, 15, 30,
241 0x08, 0x20, 11, 15, 30,
242 0x09, 0x20, 12, 15, 30,
243 0x0a, 0x20, 13, 8, 20,
244 0x0b, 0x20, 14, 8, 20,
245 0x0c, 0x20, 15, 8, 25,
246 0x0d, 0x22, 15, 8, 15,
91980990
GKH
247};
248
51126deb 249u8 RateSwitchTable11BGN3S[] = { /* 3*3 */
ec278fa2
BZ
250/* 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) */
251 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */
252 0x00, 0x21, 0, 30, 101, /*50 */
96b3c83d
BZ
253 0x01, 0x21, 1, 20, 50,
254 0x02, 0x21, 2, 20, 50,
255 0x03, 0x21, 3, 20, 50,
256 0x04, 0x21, 4, 15, 50,
257 0x05, 0x20, 20, 15, 30,
258 0x06, 0x20, 21, 8, 20,
259 0x07, 0x20, 22, 8, 20,
260 0x08, 0x20, 23, 8, 25,
261 0x09, 0x22, 23, 8, 25,
91980990
GKH
262};
263
51126deb 264u8 RateSwitchTable11BGN2SForABand[] = {
ec278fa2
BZ
265/* 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) */
266 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
267 0x00, 0x21, 0, 30, 101, /*50 */
96b3c83d
BZ
268 0x01, 0x21, 1, 20, 50,
269 0x02, 0x21, 2, 20, 50,
270 0x03, 0x21, 3, 15, 50,
271 0x04, 0x21, 4, 15, 30,
272 0x05, 0x21, 5, 15, 30,
273 0x06, 0x20, 12, 15, 30,
274 0x07, 0x20, 13, 8, 20,
275 0x08, 0x20, 14, 8, 20,
276 0x09, 0x20, 15, 8, 25,
277 0x0a, 0x22, 15, 8, 25,
91980990
GKH
278};
279
51126deb 280u8 RateSwitchTable11BGN3SForABand[] = { /* 3*3 */
ec278fa2
BZ
281/* 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) */
282 0x0c, 0x09, 0, 0, 0, /* Initial used item after association */
283 0x00, 0x21, 0, 30, 101, /*50 */
96b3c83d
BZ
284 0x01, 0x21, 1, 20, 50,
285 0x02, 0x21, 2, 20, 50,
286 0x03, 0x21, 3, 15, 50,
287 0x04, 0x21, 4, 15, 30,
288 0x05, 0x21, 5, 15, 30,
289 0x06, 0x21, 12, 15, 30,
290 0x07, 0x20, 20, 15, 30,
291 0x08, 0x20, 21, 8, 20,
292 0x09, 0x20, 22, 8, 20,
293 0x0a, 0x20, 23, 8, 25,
294 0x0b, 0x22, 23, 8, 25,
91980990 295};
91980990 296
51126deb 297extern u8 OfdmRateToRxwiMCS[];
ec278fa2
BZ
298/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */
299/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */
51126deb 300unsigned long BasicRateMask[12] =
96b3c83d
BZ
301 { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ ,
3020xfffff00f /* 11 */ ,
303 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ ,
304 0xfffff0ff /* 18 */ ,
305 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ ,
306 0xffffffff /* 54 */
307};
91980990 308
51126deb
BZ
309u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
310u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
91980990 311
ec278fa2
BZ
312/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */
313/* this value, then it's quaranteed capable of operating in 36 mbps TX rate in */
314/* clean environment. */
315/* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 */
51126deb 316char RssiSafeLevelForTxRate[] =
96b3c83d
BZ
317 { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
318
51126deb
BZ
319u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
320u16 RateIdTo500Kbps[] =
96b3c83d
BZ
321 { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
322
51126deb
BZ
323u8 SsidIe = IE_SSID;
324u8 SupRateIe = IE_SUPP_RATES;
325u8 ExtRateIe = IE_EXT_SUPP_RATES;
326u8 HtCapIe = IE_HT_CAP;
327u8 AddHtInfoIe = IE_ADD_HT;
328u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET;
329u8 ErpIe = IE_ERP;
330u8 DsIe = IE_DS_PARM;
331u8 TimIe = IE_TIM;
332u8 WpaIe = IE_WPA;
333u8 Wpa2Ie = IE_WPA2;
334u8 IbssIe = IE_IBSS_PARM;
96b3c83d 335
51126deb 336extern u8 WPA_OUI[];
96b3c83d 337
51126deb 338u8 SES_OUI[] = { 0x00, 0x90, 0x4c };
96b3c83d 339
51126deb 340u8 ZeroSsid[32] =
96b3c83d
BZ
341 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3420x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00
345};
91980990
GKH
346
347/*
348 ==========================================================================
349 Description:
350 initialize the MLME task and its data structure (queue, spinlock,
351 timer, state machines).
352
353 IRQL = PASSIVE_LEVEL
354
355 Return:
356 always return NDIS_STATUS_SUCCESS
357
358 ==========================================================================
359*/
62eb734b 360int MlmeInit(struct rt_rtmp_adapter *pAd)
91980990 361{
51126deb 362 int Status = NDIS_STATUS_SUCCESS;
91980990
GKH
363
364 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
365
96b3c83d 366 do {
91980990 367 Status = MlmeQueueInit(&pAd->Mlme.Queue);
96b3c83d 368 if (Status != NDIS_STATUS_SUCCESS)
91980990
GKH
369 break;
370
371 pAd->Mlme.bRunning = FALSE;
372 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
373
91980990
GKH
374 {
375 BssTableInit(&pAd->ScanTab);
376
ec278fa2 377 /* init STA state machines */
96b3c83d
BZ
378 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine,
379 pAd->Mlme.AssocFunc);
380 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine,
381 pAd->Mlme.AuthFunc);
382 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine,
383 pAd->Mlme.AuthRspFunc);
384 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine,
385 pAd->Mlme.SyncFunc);
91980990 386
ec278fa2
BZ
387 /* Since we are using switch/case to implement it, the init is different from the above */
388 /* state machine init */
91980990
GKH
389 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
390 }
91980990 391
96b3c83d
BZ
392 WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine,
393 pAd->Mlme.WpaFunc);
ca97b838 394
96b3c83d
BZ
395 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine,
396 pAd->Mlme.ActFunc);
91980990 397
ec278fa2 398 /* Init mlme periodic timer */
96b3c83d
BZ
399 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer,
400 GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
91980990 401
ec278fa2 402 /* Set mlme periodic timer */
91980990
GKH
403 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
404
ec278fa2 405 /* software-based RX Antenna diversity */
96b3c83d
BZ
406 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer,
407 GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd,
408 FALSE);
91980990 409
91980990 410 {
ca97b838 411#ifdef RTMP_PCI_SUPPORT
96b3c83d 412 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
ec278fa2 413 /* only PCIe cards need these two timers */
96b3c83d
BZ
414 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer,
415 GET_TIMER_FUNCTION
416 (PsPollWakeExec), pAd, FALSE);
417 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer,
418 GET_TIMER_FUNCTION(RadioOnExec),
419 pAd, FALSE);
420 }
ec278fa2 421#endif /* RTMP_PCI_SUPPORT // */
ca97b838 422
96b3c83d
BZ
423 RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer,
424 GET_TIMER_FUNCTION(LinkDownExec), pAd,
425 FALSE);
ca97b838
BZ
426
427#ifdef RTMP_MAC_USB
96b3c83d
BZ
428 RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer,
429 GET_TIMER_FUNCTION
430 (RtmpUsbStaAsicForceWakeupTimeout), pAd,
431 FALSE);
ca97b838 432 pAd->Mlme.AutoWakeupTimerRunning = FALSE;
ec278fa2 433#endif /* RTMP_MAC_USB // */
91980990 434 }
ca97b838 435
91980990
GKH
436 } while (FALSE);
437
438 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
439
440 return Status;
441}
442
443/*
444 ==========================================================================
445 Description:
446 main loop of the MLME
447 Pre:
448 Mlme has to be initialized, and there are something inside the queue
449 Note:
450 This function is invoked from MPSetInformation and MPReceive;
451 This task guarantee only one MlmeHandler will run.
452
453 IRQL = DISPATCH_LEVEL
454
455 ==========================================================================
456 */
62eb734b 457void MlmeHandler(struct rt_rtmp_adapter *pAd)
91980990 458{
62eb734b 459 struct rt_mlme_queue_elem *Elem = NULL;
91980990 460
ec278fa2
BZ
461 /* Only accept MLME and Frame from peer side, no other (control/data) frame should */
462 /* get into this state machine */
91980990
GKH
463
464 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
96b3c83d 465 if (pAd->Mlme.bRunning) {
91980990
GKH
466 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
467 return;
96b3c83d 468 } else {
91980990
GKH
469 pAd->Mlme.bRunning = TRUE;
470 }
471 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
472
96b3c83d 473 while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
91980990 474 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
96b3c83d
BZ
475 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
476 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
477 DBGPRINT(RT_DEBUG_TRACE,
478 ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n",
479 pAd->Mlme.Queue.Num));
91980990
GKH
480 break;
481 }
ec278fa2 482 /*From message type, determine which state machine I should drive */
96b3c83d 483 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
ca97b838 484#ifdef RTMP_MAC_USB
96b3c83d
BZ
485 if (Elem->MsgType == MT2_RESET_CONF) {
486 DBGPRINT_RAW(RT_DEBUG_TRACE,
06aea994 487 ("reset MLME state machine!\n"));
59fe2d89
BZ
488 MlmeRestartStateMachine(pAd);
489 Elem->Occupied = FALSE;
490 Elem->MsgLen = 0;
491 continue;
492 }
ec278fa2 493#endif /* RTMP_MAC_USB // */
91980990 494
ec278fa2 495 /* if dequeue success */
96b3c83d 496 switch (Elem->Machine) {
ec278fa2 497 /* STA state machines */
96b3c83d
BZ
498 case ASSOC_STATE_MACHINE:
499 StateMachinePerformAction(pAd,
500 &pAd->Mlme.
501 AssocMachine, Elem);
502 break;
503 case AUTH_STATE_MACHINE:
504 StateMachinePerformAction(pAd,
505 &pAd->Mlme.
506 AuthMachine, Elem);
507 break;
508 case AUTH_RSP_STATE_MACHINE:
509 StateMachinePerformAction(pAd,
510 &pAd->Mlme.
511 AuthRspMachine, Elem);
512 break;
513 case SYNC_STATE_MACHINE:
514 StateMachinePerformAction(pAd,
515 &pAd->Mlme.
516 SyncMachine, Elem);
517 break;
518 case MLME_CNTL_STATE_MACHINE:
519 MlmeCntlMachinePerformAction(pAd,
520 &pAd->Mlme.
521 CntlMachine, Elem);
522 break;
523 case WPA_PSK_STATE_MACHINE:
524 StateMachinePerformAction(pAd,
525 &pAd->Mlme.
526 WpaPskMachine, Elem);
527 break;
91980990 528
96b3c83d
BZ
529 case ACTION_STATE_MACHINE:
530 StateMachinePerformAction(pAd,
531 &pAd->Mlme.ActMachine,
532 Elem);
533 break;
91980990 534
96b3c83d
BZ
535 case WPA_STATE_MACHINE:
536 StateMachinePerformAction(pAd,
537 &pAd->Mlme.WpaMachine,
538 Elem);
539 break;
91980990 540
96b3c83d
BZ
541 default:
542 DBGPRINT(RT_DEBUG_TRACE,
543 ("ERROR: Illegal machine %ld in MlmeHandler()\n",
544 Elem->Machine));
545 break;
ec278fa2 546 } /* end of switch */
91980990 547
ec278fa2 548 /* free MLME element */
91980990
GKH
549 Elem->Occupied = FALSE;
550 Elem->MsgLen = 0;
551
96b3c83d 552 } else {
8c3d9092 553 DBGPRINT_ERR("MlmeHandler: MlmeQueue empty\n");
91980990
GKH
554 }
555 }
556
557 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
558 pAd->Mlme.bRunning = FALSE;
559 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
560}
561
562/*
563 ==========================================================================
564 Description:
565 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
566 Parameters:
567 Adapter - NIC Adapter pointer
568 Post:
569 The MLME task will no longer work properly
570
571 IRQL = PASSIVE_LEVEL
572
573 ==========================================================================
574 */
62eb734b 575void MlmeHalt(struct rt_rtmp_adapter *pAd)
91980990 576{
96b3c83d 577 BOOLEAN Cancelled;
91980990
GKH
578
579 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
580
96b3c83d 581 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
ec278fa2 582 /* disable BEACON generation and other BEACON related hardware timers */
91980990
GKH
583 AsicDisableSync(pAd);
584 }
585
91980990 586 {
ec278fa2 587 /* Cancel pending timers */
96b3c83d
BZ
588 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
589 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
590 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
591 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
592 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
593 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
ca97b838
BZ
594
595#ifdef RTMP_MAC_PCI
96b3c83d
BZ
596 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
597 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) {
598 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
599 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
91980990 600 }
ec278fa2 601#endif /* RTMP_MAC_PCI // */
ca97b838 602
96b3c83d 603 RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
ca97b838
BZ
604
605#ifdef RTMP_MAC_USB
606 RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
ec278fa2 607#endif /* RTMP_MAC_USB // */
91980990 608 }
91980990 609
96b3c83d
BZ
610 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
611 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
91980990 612
96b3c83d 613 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
62eb734b 614 struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps;
ca97b838 615
ec278fa2 616 /* Set LED */
91980990 617 RTMPSetLED(pAd, LED_HALT);
ec278fa2 618 RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it. */
ca97b838 619#ifdef RTMP_MAC_USB
96b3c83d
BZ
620 {
621 LED_CFG_STRUC LedCfg;
622 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
623 LedCfg.field.LedPolar = 0;
624 LedCfg.field.RLedMode = 0;
625 LedCfg.field.GLedMode = 0;
626 LedCfg.field.YLedMode = 0;
627 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
628 }
ec278fa2 629#endif /* RTMP_MAC_USB // */
ca97b838
BZ
630
631 if (pChipOps->AsicHaltAction)
632 pChipOps->AsicHaltAction(pAd);
91980990
GKH
633 }
634
25985edc 635 RTMPusecDelay(5000); /* 5 msec to guarantee Ant Diversity timer canceled */
91980990
GKH
636
637 MlmeQueueDestroy(&pAd->Mlme.Queue);
638 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
639
640 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
641}
642
62eb734b 643void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd)
91980990 644{
96b3c83d
BZ
645 pAd->RalinkCounters.LastOneSecRxOkDataCnt =
646 pAd->RalinkCounters.OneSecRxOkDataCnt;
ec278fa2 647 /* clear all OneSecxxx counters. */
91980990
GKH
648 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
649 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
650 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
651 pAd->RalinkCounters.OneSecRxOkCnt = 0;
652 pAd->RalinkCounters.OneSecTxFailCount = 0;
653 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
654 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
655 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
ca97b838
BZ
656 pAd->RalinkCounters.OneSecReceivedByteCount = 0;
657 pAd->RalinkCounters.OneSecTransmittedByteCount = 0;
91980990 658
ec278fa2 659 /* TODO: for debug only. to be removed */
91980990
GKH
660 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
661 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
662 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
663 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
664 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
665 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
666 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
667 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
668 pAd->RalinkCounters.OneSecTxDoneCount = 0;
669 pAd->RalinkCounters.OneSecRxCount = 0;
670 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
671 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
672
673 return;
674}
675
91980990
GKH
676/*
677 ==========================================================================
678 Description:
679 This routine is executed periodically to -
680 1. Decide if it's a right time to turn on PwrMgmt bit of all
681 outgoiing frames
682 2. Calculate ChannelQuality based on statistics of the last
683 period, so that TX rate won't toggling very frequently between a
684 successful TX and a failed TX.
685 3. If the calculated ChannelQuality indicated current connection not
686 healthy, then a ROAMing attempt is tried here.
687
688 IRQL = DISPATCH_LEVEL
689
690 ==========================================================================
691 */
ec278fa2 692#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec */
51126deb
BZ
693void MlmePeriodicExec(void *SystemSpecific1,
694 void *FunctionContext,
695 void *SystemSpecific2, void *SystemSpecific3)
91980990 696{
51126deb 697 unsigned long TxTotalCnt;
62eb734b 698 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
91980990 699
ca97b838 700#ifdef RTMP_MAC_PCI
91980990 701 {
ec278fa2
BZ
702 /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */
703 /* Move code to here, because following code will return when radio is off */
96b3c83d
BZ
704 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) ==
705 0) && (pAd->StaCfg.bHardwareRadio == TRUE)
706 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
707 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
708 /*&&(pAd->bPCIclkOff == FALSE) */
709 ) {
51126deb 710 u32 data = 0;
91980990 711
ec278fa2 712 /* Read GPIO pin2 as Hardware controlled radio state */
e44fd1cf 713#ifndef RT3090
ca97b838 714 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
ec278fa2
BZ
715#endif /* RT3090 // */
716/*KH(PCIE PS):Added based on Jane<-- */
e44fd1cf 717#ifdef RT3090
ec278fa2
BZ
718/* Read GPIO pin2 as Hardware controlled radio state */
719/* We need to Read GPIO if HW said so no mater what advance power saving */
96b3c83d
BZ
720 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
721 &&
722 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
723 && (pAd->StaCfg.PSControl.field.EnablePSinIdle ==
724 TRUE)) {
ec278fa2 725 /* Want to make sure device goes to L0 state before reading register. */
96b3c83d
BZ
726 RTMPPCIeLinkCtrlValueRestore(pAd, 0);
727 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
728 RTMPPCIeLinkCtrlSetting(pAd, 3);
729 } else
730 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
ec278fa2
BZ
731#endif /* RT3090 // */
732/*KH(PCIE PS):Added based on Jane--> */
e44fd1cf 733
96b3c83d 734 if (data & 0x04) {
91980990 735 pAd->StaCfg.bHwRadio = TRUE;
96b3c83d 736 } else {
91980990
GKH
737 pAd->StaCfg.bHwRadio = FALSE;
738 }
96b3c83d
BZ
739 if (pAd->StaCfg.bRadio !=
740 (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) {
741 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio
742 && pAd->StaCfg.bSwRadio);
743 if (pAd->StaCfg.bRadio == TRUE) {
91980990 744 MlmeRadioOn(pAd);
ec278fa2 745 /* Update extra information */
91980990 746 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
96b3c83d 747 } else {
91980990 748 MlmeRadioOff(pAd);
ec278fa2 749 /* Update extra information */
91980990
GKH
750 pAd->ExtraInfo = HW_RADIO_OFF;
751 }
752 }
753 }
754 }
ec278fa2 755#endif /* RTMP_MAC_PCI // */
91980990 756
ec278fa2
BZ
757 /* Do nothing if the driver is starting halt state. */
758 /* This might happen when timer already been fired before cancel timer with mlmehalt */
91980990 759 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
96b3c83d
BZ
760 fRTMP_ADAPTER_RADIO_OFF |
761 fRTMP_ADAPTER_RADIO_MEASUREMENT |
762 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
91980990
GKH
763 return;
764
ca97b838 765 RTMP_MLME_PRE_SANITY_CHECK(pAd);
91980990 766
91980990 767 {
ec278fa2 768 /* Do nothing if monitor mode is on */
91980990
GKH
769 if (MONITOR_ON(pAd))
770 return;
771
96b3c83d 772 if (pAd->Mlme.PeriodicRound & 0x1) {
ec278fa2 773 /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D */
91980990 774 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
96b3c83d
BZ
775 (STA_TGN_WIFI_ON(pAd)) &&
776 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
777 {
778 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
779 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
780 } else if ((STA_TGN_WIFI_ON(pAd)) &&
781 ((pAd->MACVersion & 0xffff) == 0x0101)) {
782 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
783 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
784 }
91980990
GKH
785 }
786 }
91980990
GKH
787
788 pAd->bUpdateBcnCntDone = FALSE;
789
ec278fa2 790/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */
96b3c83d 791 pAd->Mlme.PeriodicRound++;
91980990 792
ca97b838 793#ifdef RTMP_MAC_USB
ec278fa2 794 /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */
59fe2d89 795 NICUpdateFifoStaCounters(pAd);
ec278fa2 796#endif /* RTMP_MAC_USB // */
ca97b838 797
ec278fa2 798 /* execute every 500ms */
96b3c83d
BZ
799 if ((pAd->Mlme.PeriodicRound % 5 == 0)
800 && RTMPAutoRateSwitchCheck(pAd)
801 /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ )
91980990 802 {
ec278fa2 803 /* perform dynamic tx rate switching based on past TX history */
91980990 804 {
96b3c83d
BZ
805 if ((OPSTATUS_TEST_FLAG
806 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
807 )
808 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
91980990
GKH
809 MlmeDynamicTxRateSwitching(pAd);
810 }
91980990 811 }
ec278fa2 812 /* Normal 1 second Mlme PeriodicExec. */
96b3c83d
BZ
813 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) {
814 pAd->Mlme.OneSecPeriodicRound++;
ca97b838 815
ec278fa2 816 /*ORIBATimerTimeout(pAd); */
91980990 817
ec278fa2 818 /* Media status changed, report to NDIS */
96b3c83d 819 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) {
91980990 820 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
96b3c83d
BZ
821 if (OPSTATUS_TEST_FLAG
822 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
823 pAd->IndicateMediaState =
824 NdisMediaStateConnected;
91980990
GKH
825 RTMP_IndicateMediaState(pAd);
826
96b3c83d
BZ
827 } else {
828 pAd->IndicateMediaState =
829 NdisMediaStateDisconnected;
91980990
GKH
830 RTMP_IndicateMediaState(pAd);
831 }
832 }
833
834 NdisGetSystemUpTime(&pAd->Mlme.Now32);
835
ec278fa2
BZ
836 /* add the most up-to-date h/w raw counters into software variable, so that */
837 /* the dynamic tuning mechanism below are based on most up-to-date information */
91980990
GKH
838 NICUpdateRawCounters(pAd);
839
ca97b838
BZ
840#ifdef RTMP_MAC_USB
841 RTUSBWatchDog(pAd);
ec278fa2 842#endif /* RTMP_MAC_USB // */
59fe2d89 843
ec278fa2 844 /* Need statistics after read counter. So put after NICUpdateRawCounters */
91980990 845 ORIBATimerTimeout(pAd);
91980990 846
ec278fa2
BZ
847 /* if MGMT RING is full more than twice within 1 second, we consider there's */
848 /* a hardware problem stucking the TX path. In this case, try a hardware reset */
849 /* to recover the system */
850 /* if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */
851 /* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */
852 /* else */
853 /* pAd->RalinkCounters.MgmtRingFullCount = 0; */
ca97b838 854
ec278fa2 855 /* The time period for checking antenna is according to traffic */
ca97b838 856 {
96b3c83d
BZ
857 if (pAd->Mlme.bEnableAutoAntennaCheck) {
858 TxTotalCnt =
859 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
860 pAd->RalinkCounters.OneSecTxRetryOkCount +
861 pAd->RalinkCounters.OneSecTxFailCount;
862
ec278fa2 863 /* dynamic adjust antenna evaluation period according to the traffic */
96b3c83d
BZ
864 if (TxTotalCnt > 50) {
865 if (pAd->Mlme.OneSecPeriodicRound %
866 10 == 0) {
867 AsicEvaluateRxAnt(pAd);
868 }
869 } else {
870 if (pAd->Mlme.OneSecPeriodicRound % 3 ==
871 0) {
872 AsicEvaluateRxAnt(pAd);
873 }
91980990
GKH
874 }
875 }
876 }
877
5a911fd6 878 STAMlmePeriodicExec(pAd);
91980990
GKH
879
880 MlmeResetRalinkCounters(pAd);
881
91980990 882 {
ca97b838 883#ifdef RTMP_MAC_PCI
96b3c83d
BZ
884 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
885 && (pAd->bPCIclkOff == FALSE))
ec278fa2 886#endif /* RTMP_MAC_PCI // */
91980990 887 {
ec278fa2
BZ
888 /* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */
889 /* and sending CTS-to-self over and over. */
890 /* Software Patch Solution: */
891 /* 1. Polling debug state register 0x10F4 every one second. */
892 /* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */
893 /* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */
91980990 894
51126deb 895 u32 MacReg = 0;
91980990
GKH
896
897 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
96b3c83d
BZ
898 if (((MacReg & 0x20000000) && (MacReg & 0x80))
899 || ((MacReg & 0x20000000)
900 && (MacReg & 0x20))) {
91980990
GKH
901 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
902 RTMPusecDelay(1);
903 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
904
96b3c83d
BZ
905 DBGPRINT(RT_DEBUG_WARN,
906 ("Warning, MAC specific condition occurs \n"));
91980990
GKH
907 }
908 }
909 }
91980990 910
ca97b838 911 RTMP_MLME_HANDLER(pAd);
91980990
GKH
912 }
913
91980990
GKH
914 pAd->bUpdateBcnCntDone = FALSE;
915}
916
ca97b838
BZ
917/*
918 ==========================================================================
919 Validate SSID for connection try and rescan purpose
920 Valid SSID will have visible chars only.
921 The valid length is from 0 to 32.
922 IRQL = DISPATCH_LEVEL
923 ==========================================================================
924 */
51126deb 925BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen)
91980990 926{
96b3c83d 927 int index;
91980990 928
ca97b838
BZ
929 if (SsidLen > MAX_LEN_OF_SSID)
930 return (FALSE);
931
ec278fa2 932 /* Check each character value */
96b3c83d 933 for (index = 0; index < SsidLen; index++) {
ca97b838
BZ
934 if (pSsid[index] < 0x20)
935 return (FALSE);
96b3c83d 936 }
91980990 937
ec278fa2 938 /* All checked */
ca97b838
BZ
939 return (TRUE);
940}
941
62eb734b
BZ
942void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd,
943 struct rt_mac_table_entry *pEntry,
51126deb
BZ
944 u8 ** ppTable,
945 u8 *pTableSize, u8 *pInitTxRateIdx)
ca97b838 946{
96b3c83d 947 do {
ec278fa2 948 /* decide the rate table for tuning */
96b3c83d 949 if (pAd->CommonCfg.TxRateTableSize > 0) {
ca97b838
BZ
950 *ppTable = RateSwitchTable;
951 *pTableSize = RateSwitchTable[0];
952 *pInitTxRateIdx = RateSwitchTable[1];
953
954 break;
96b3c83d 955 }
ed291e80 956
96b3c83d 957 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) {
ec278fa2 958 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 */
ca97b838
BZ
959 *ppTable = RateSwitchTable11N1S;
960 *pTableSize = RateSwitchTable11N1S[0];
961 *pInitTxRateIdx = RateSwitchTable11N1S[1];
962
ec278fa2 963 } 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 */
96b3c83d 964 if (pAd->LatchRfRegs.Channel <= 14) {
ca97b838
BZ
965 *ppTable = RateSwitchTable11N2S;
966 *pTableSize = RateSwitchTable11N2S[0];
96b3c83d
BZ
967 *pInitTxRateIdx =
968 RateSwitchTable11N2S[1];
969 } else {
ca97b838 970 *ppTable = RateSwitchTable11N2SForABand;
96b3c83d
BZ
971 *pTableSize =
972 RateSwitchTable11N2SForABand[0];
973 *pInitTxRateIdx =
974 RateSwitchTable11N2SForABand[1];
975 }
91980990 976
96b3c83d
BZ
977 } else if ((pEntry->RateLen == 4)
978 && (pEntry->HTCapability.MCSSet[0] == 0)
979 && (pEntry->HTCapability.MCSSet[1] == 0)
980 ) {
ca97b838
BZ
981 *ppTable = RateSwitchTable11B;
982 *pTableSize = RateSwitchTable11B[0];
983 *pInitTxRateIdx = RateSwitchTable11B[1];
91980990 984
96b3c83d 985 } else if (pAd->LatchRfRegs.Channel <= 14) {
ca97b838
BZ
986 *ppTable = RateSwitchTable11BG;
987 *pTableSize = RateSwitchTable11BG[0];
988 *pInitTxRateIdx = RateSwitchTable11BG[1];
91980990 989
96b3c83d 990 } else {
ca97b838
BZ
991 *ppTable = RateSwitchTable11G;
992 *pTableSize = RateSwitchTable11G[0];
993 *pInitTxRateIdx = RateSwitchTable11G[1];
91980990 994
ca97b838
BZ
995 }
996 break;
997 }
ec278fa2
BZ
998 /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
999 /* ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1000 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 */
ca97b838
BZ
1001 *ppTable = RateSwitchTable11BGN1S;
1002 *pTableSize = RateSwitchTable11BGN1S[0];
1003 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
91980990 1004
ca97b838 1005 break;
96b3c83d 1006 }
ec278fa2
BZ
1007 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
1008 /* (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1009 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 */
96b3c83d 1010 if (pAd->LatchRfRegs.Channel <= 14) {
ca97b838
BZ
1011 *ppTable = RateSwitchTable11BGN2S;
1012 *pTableSize = RateSwitchTable11BGN2S[0];
1013 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
91980990 1014
96b3c83d 1015 } else {
ca97b838
BZ
1016 *ppTable = RateSwitchTable11BGN2SForABand;
1017 *pTableSize = RateSwitchTable11BGN2SForABand[0];
96b3c83d
BZ
1018 *pInitTxRateIdx =
1019 RateSwitchTable11BGN2SForABand[1];
91980990 1020
ca97b838
BZ
1021 }
1022 break;
91980990 1023 }
ec278fa2
BZ
1024 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1025 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11N 1S AP */
ca97b838
BZ
1026 *ppTable = RateSwitchTable11N1S;
1027 *pTableSize = RateSwitchTable11N1S[0];
1028 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1029
1030 break;
1031 }
ec278fa2
BZ
1032 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1033 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11N 2S AP */
96b3c83d
BZ
1034 if (pAd->LatchRfRegs.Channel <= 14) {
1035 *ppTable = RateSwitchTable11N2S;
1036 *pTableSize = RateSwitchTable11N2S[0];
1037 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1038 } else {
ca97b838
BZ
1039 *ppTable = RateSwitchTable11N2SForABand;
1040 *pTableSize = RateSwitchTable11N2SForABand[0];
96b3c83d
BZ
1041 *pInitTxRateIdx =
1042 RateSwitchTable11N2SForABand[1];
ca97b838
BZ
1043 }
1044
1045 break;
1046 }
ec278fa2 1047 /*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
96b3c83d 1048 if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode == PHY_11B)
ec278fa2 1049 /*Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode */
96b3c83d 1050 /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */
ec278fa2 1051 ) { /* B only AP */
ca97b838
BZ
1052 *ppTable = RateSwitchTable11B;
1053 *pTableSize = RateSwitchTable11B[0];
1054 *pInitTxRateIdx = RateSwitchTable11B[1];
1055
1056 break;
1057 }
ec278fa2 1058 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
ca97b838 1059 if ((pEntry->RateLen > 8)
96b3c83d
BZ
1060 && (pEntry->HTCapability.MCSSet[0] == 0)
1061 && (pEntry->HTCapability.MCSSet[1] == 0)
ec278fa2 1062 ) { /* B/G mixed AP */
ca97b838
BZ
1063 *ppTable = RateSwitchTable11BG;
1064 *pTableSize = RateSwitchTable11BG[0];
1065 *pInitTxRateIdx = RateSwitchTable11BG[1];
1066
1067 break;
1068 }
ec278fa2 1069 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
ca97b838 1070 if ((pEntry->RateLen == 8)
96b3c83d
BZ
1071 && (pEntry->HTCapability.MCSSet[0] == 0)
1072 && (pEntry->HTCapability.MCSSet[1] == 0)
ec278fa2 1073 ) { /* G only AP */
ca97b838
BZ
1074 *ppTable = RateSwitchTable11G;
1075 *pTableSize = RateSwitchTable11G[0];
1076 *pInitTxRateIdx = RateSwitchTable11G[1];
1077
1078 break;
1079 }
1080
1081 {
ec278fa2
BZ
1082 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1083 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) { /* Legacy mode */
96b3c83d 1084 if (pAd->CommonCfg.MaxTxRate <= RATE_11) {
ca97b838
BZ
1085 *ppTable = RateSwitchTable11B;
1086 *pTableSize = RateSwitchTable11B[0];
1087 *pInitTxRateIdx = RateSwitchTable11B[1];
96b3c83d
BZ
1088 } else if ((pAd->CommonCfg.MaxTxRate > RATE_11)
1089 && (pAd->CommonCfg.MinTxRate >
1090 RATE_11)) {
ca97b838
BZ
1091 *ppTable = RateSwitchTable11G;
1092 *pTableSize = RateSwitchTable11G[0];
1093 *pInitTxRateIdx = RateSwitchTable11G[1];
1094
96b3c83d 1095 } else {
ca97b838
BZ
1096 *ppTable = RateSwitchTable11BG;
1097 *pTableSize = RateSwitchTable11BG[0];
96b3c83d
BZ
1098 *pInitTxRateIdx =
1099 RateSwitchTable11BG[1];
ca97b838
BZ
1100 }
1101 break;
1102 }
96b3c83d
BZ
1103 if (pAd->LatchRfRegs.Channel <= 14) {
1104 if (pAd->CommonCfg.TxStream == 1) {
ca97b838
BZ
1105 *ppTable = RateSwitchTable11N1S;
1106 *pTableSize = RateSwitchTable11N1S[0];
96b3c83d
BZ
1107 *pInitTxRateIdx =
1108 RateSwitchTable11N1S[1];
1109 DBGPRINT_RAW(RT_DEBUG_ERROR,
25985edc 1110 ("DRS: unknown mode,default use 11N 1S AP \n"));
96b3c83d 1111 } else {
ca97b838
BZ
1112 *ppTable = RateSwitchTable11N2S;
1113 *pTableSize = RateSwitchTable11N2S[0];
96b3c83d
BZ
1114 *pInitTxRateIdx =
1115 RateSwitchTable11N2S[1];
1116 DBGPRINT_RAW(RT_DEBUG_ERROR,
25985edc 1117 ("DRS: unknown mode,default use 11N 2S AP \n"));
ca97b838 1118 }
96b3c83d
BZ
1119 } else {
1120 if (pAd->CommonCfg.TxStream == 1) {
ca97b838
BZ
1121 *ppTable = RateSwitchTable11N1S;
1122 *pTableSize = RateSwitchTable11N1S[0];
96b3c83d
BZ
1123 *pInitTxRateIdx =
1124 RateSwitchTable11N1S[1];
1125 DBGPRINT_RAW(RT_DEBUG_ERROR,
25985edc 1126 ("DRS: unknown mode,default use 11N 1S AP \n"));
96b3c83d 1127 } else {
ca97b838 1128 *ppTable = RateSwitchTable11N2SForABand;
96b3c83d
BZ
1129 *pTableSize =
1130 RateSwitchTable11N2SForABand[0];
1131 *pInitTxRateIdx =
1132 RateSwitchTable11N2SForABand[1];
1133 DBGPRINT_RAW(RT_DEBUG_ERROR,
25985edc 1134 ("DRS: unknown mode,default use 11N 2S AP \n"));
ca97b838
BZ
1135 }
1136 }
96b3c83d 1137 DBGPRINT_RAW(RT_DEBUG_ERROR,
25985edc 1138 ("DRS: unknown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
96b3c83d
BZ
1139 pAd->StaActive.SupRateLen,
1140 pAd->StaActive.ExtRateLen,
1141 pAd->StaActive.SupportedPhyInfo.MCSSet[0],
1142 pAd->StaActive.SupportedPhyInfo.
1143 MCSSet[1]));
ca97b838 1144 }
96b3c83d 1145 } while (FALSE);
ca97b838
BZ
1146}
1147
62eb734b 1148void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd)
ca97b838 1149{
51126deb 1150 unsigned long TxTotalCnt;
96b3c83d 1151 int i;
ca97b838
BZ
1152
1153 /*
96b3c83d
BZ
1154 We return here in ATE mode, because the statistics
1155 that ATE need are not collected via this routine.
1156 */
ca97b838 1157#if defined(RT305x)||defined(RT3070)
ec278fa2 1158 /* 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 */
96b3c83d 1159 if (!pAd->CommonCfg.HighPowerPatchDisabled) {
ca97b838 1160#ifdef RT3070
96b3c83d 1161 if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201)))
ec278fa2 1162#endif /* RT3070 // */
96b3c83d
BZ
1163 {
1164 if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0)
1165 && (pAd->StaCfg.RssiSample.AvgRssi0 >
1166 (pAd->BbpRssiToDbmDelta - 35))) {
1167 RT30xxWriteRFRegister(pAd, RF_R27, 0x20);
1168 } else {
1169 RT30xxWriteRFRegister(pAd, RF_R27, 0x23);
1170 }
1171 }
ca97b838
BZ
1172 }
1173#endif
e44fd1cf 1174#ifdef PCIE_PS_SUPPORT
ec278fa2
BZ
1175/* don't perform idle-power-save mechanism within 3 min after driver initialization. */
1176/* This can make rebooter test more robust */
96b3c83d
BZ
1177 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
1178 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
1179 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1180 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1181 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) {
1182 if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) {
1183 if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1184 TRUE) {
1185 DBGPRINT(RT_DEBUG_TRACE,
1186 ("%s\n", __func__));
1187 RT28xxPciAsicRadioOff(pAd,
1188 GUI_IDLE_POWER_SAVE,
1189 0);
1190 } else {
1191 AsicSendCommandToMcu(pAd, 0x30,
1192 PowerSafeCID, 0xff,
1193 0x2);
ec278fa2 1194 /* Wait command success */
96b3c83d
BZ
1195 AsicCheckCommanOk(pAd, PowerSafeCID);
1196 RTMP_SET_FLAG(pAd,
1197 fRTMP_ADAPTER_IDLE_RADIO_OFF);
1198 DBGPRINT(RT_DEBUG_TRACE,
1199 ("PSM - rt30xx Issue Sleep command)\n"));
e44fd1cf 1200 }
96b3c83d
BZ
1201 } else if (pAd->Mlme.OneSecPeriodicRound > 180) {
1202 if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1203 TRUE) {
1204 DBGPRINT(RT_DEBUG_TRACE,
1205 ("%s\n", __func__));
1206 RT28xxPciAsicRadioOff(pAd,
1207 GUI_IDLE_POWER_SAVE,
1208 0);
1209 } else {
1210 AsicSendCommandToMcu(pAd, 0x30,
1211 PowerSafeCID, 0xff,
1212 0x02);
ec278fa2 1213 /* Wait command success */
96b3c83d
BZ
1214 AsicCheckCommanOk(pAd, PowerSafeCID);
1215 RTMP_SET_FLAG(pAd,
1216 fRTMP_ADAPTER_IDLE_RADIO_OFF);
1217 DBGPRINT(RT_DEBUG_TRACE,
1218 ("PSM - rt28xx Issue Sleep command)\n"));
e44fd1cf
BZ
1219 }
1220 }
96b3c83d
BZ
1221 } else {
1222 DBGPRINT(RT_DEBUG_TRACE,
1223 ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1224 pAd->CommonCfg.SsidLen,
1225 pAd->CommonCfg.Ssid[0],
1226 pAd->CommonCfg.Ssid[1],
1227 pAd->CommonCfg.Ssid[2],
1228 pAd->CommonCfg.Ssid[3], pAd->MlmeAux.SsidLen,
1229 pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1],
1230 pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
e44fd1cf
BZ
1231 }
1232 }
ec278fa2 1233#endif /* PCIE_PS_SUPPORT // */
ca97b838 1234
96b3c83d 1235 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) {
ec278fa2 1236 /* WPA MIC error should block association attempt for 60 seconds */
ca97b838 1237 if (pAd->StaCfg.bBlockAssoc &&
96b3c83d
BZ
1238 RTMP_TIME_AFTER(pAd->Mlme.Now32,
1239 pAd->StaCfg.LastMicErrorTime +
1240 (60 * OS_HZ)))
1241 pAd->StaCfg.bBlockAssoc = FALSE;
1242 }
1243
1244 if ((pAd->PreMediaState != pAd->IndicateMediaState)
1245 && (pAd->CommonCfg.bWirelessEvent)) {
1246 if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1247 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1248 pAd->MacTab.Content[BSSID_WCID].
1249 Addr, BSS0, 0);
ca97b838
BZ
1250 }
1251 pAd->PreMediaState = pAd->IndicateMediaState;
1252 }
1253
96b3c83d
BZ
1254 if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) {
1255 } else {
1256 AsicStaBbpTuning(pAd);
ca97b838
BZ
1257 }
1258
1259 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
96b3c83d
BZ
1260 pAd->RalinkCounters.OneSecTxRetryOkCount +
1261 pAd->RalinkCounters.OneSecTxFailCount;
ca97b838 1262
96b3c83d 1263 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
ec278fa2 1264 /* update channel quality for Roaming and UI LinkQuality display */
ca97b838
BZ
1265 MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32);
1266 }
ec278fa2
BZ
1267 /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */
1268 /* Radio is currently in noisy environment */
ca97b838 1269 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
96b3c83d 1270 AsicAdjustTxPower(pAd);
ca97b838 1271
96b3c83d 1272 if (INFRA_ON(pAd)) {
ca97b838 1273
ec278fa2
BZ
1274 /* Is PSM bit consistent with user power management policy? */
1275 /* This is the only place that will set PSM bit ON. */
ca97b838 1276 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
96b3c83d 1277 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
ca97b838
BZ
1278
1279 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1280
96b3c83d
BZ
1281 if ((RTMP_TIME_AFTER
1282 (pAd->Mlme.Now32,
1283 pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ)))
1284 &&
1285 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1286 &&
1287 (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) <
1288 600))) {
ca97b838 1289 RTMPSetAGCInitValue(pAd, BW_20);
96b3c83d
BZ
1290 DBGPRINT(RT_DEBUG_TRACE,
1291 ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n",
1292 (0x2E + GET_LNA_GAIN(pAd))));
1293 }
ec278fa2
BZ
1294 /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */
1295 /* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */
96b3c83d
BZ
1296 {
1297 if (pAd->CommonCfg.bAPSDCapable
1298 && pAd->CommonCfg.APEdcaParm.bAPSDCapable) {
ec278fa2 1299 /* When APSD is enabled, the period changes as 20 sec */
96b3c83d
BZ
1300 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1301 RTMPSendNullFrame(pAd,
1302 pAd->CommonCfg.TxRate,
1303 TRUE);
1304 } else {
ec278fa2 1305 /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */
96b3c83d
BZ
1306 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) {
1307 if (pAd->CommonCfg.bWmmCapable)
1308 RTMPSendNullFrame(pAd,
1309 pAd->
1310 CommonCfg.
1311 TxRate, TRUE);
1312 else
1313 RTMPSendNullFrame(pAd,
1314 pAd->
1315 CommonCfg.
1316 TxRate,
1317 FALSE);
1318 }
1319 }
ca97b838
BZ
1320 }
1321
96b3c83d
BZ
1322 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) {
1323 DBGPRINT(RT_DEBUG_TRACE,
1324 ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n",
1325 pAd->RalinkCounters.BadCQIAutoRecoveryCount));
ca97b838 1326
ec278fa2 1327 /* Lost AP, send disconnect & link down event */
91980990
GKH
1328 LinkDown(pAd, FALSE);
1329
96b3c83d
BZ
1330 RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL,
1331 0);
ca97b838 1332
ec278fa2 1333 /* RTMPPatchMacBbpBug(pAd); */
91980990 1334 MlmeAutoReconnectLastSSID(pAd);
96b3c83d
BZ
1335 } else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) {
1336 pAd->RalinkCounters.BadCQIAutoRecoveryCount++;
1337 DBGPRINT(RT_DEBUG_TRACE,
1338 ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n",
1339 pAd->RalinkCounters.BadCQIAutoRecoveryCount));
91980990
GKH
1340 MlmeAutoReconnectLastSSID(pAd);
1341 }
1342
96b3c83d
BZ
1343 if (pAd->StaCfg.bAutoRoaming) {
1344 BOOLEAN rv = FALSE;
51126deb
BZ
1345 char dBmToRoam = pAd->StaCfg.dBmToRoam;
1346 char MaxRssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1347 pAd->StaCfg.RssiSample.
1348 LastRssi0,
1349 pAd->StaCfg.RssiSample.
1350 LastRssi1,
1351 pAd->StaCfg.RssiSample.
1352 LastRssi2);
91980990 1353
ec278fa2 1354 /* Scanning, ignore Roaming */
96b3c83d
BZ
1355 if (!RTMP_TEST_FLAG
1356 (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
1357 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1358 && (MaxRssi <= dBmToRoam)) {
1359 DBGPRINT(RT_DEBUG_TRACE,
1360 ("Rssi=%d, dBmToRoam=%d\n", MaxRssi,
51126deb 1361 (char)dBmToRoam));
ca97b838 1362
ec278fa2 1363 /* Add auto seamless roaming */
ca97b838
BZ
1364 if (rv == FALSE)
1365 rv = MlmeCheckForFastRoaming(pAd);
91980990 1366
96b3c83d
BZ
1367 if (rv == FALSE) {
1368 if ((pAd->StaCfg.LastScanTime +
1369 10 * OS_HZ) < pAd->Mlme.Now32) {
1370 DBGPRINT(RT_DEBUG_TRACE,
25985edc 1371 ("MMCHK - Roaming, No eligible entry, try new scan!\n"));
ca97b838 1372 pAd->StaCfg.ScanCnt = 2;
96b3c83d
BZ
1373 pAd->StaCfg.LastScanTime =
1374 pAd->Mlme.Now32;
ca97b838 1375 MlmeAutoScan(pAd);
96b3c83d
BZ
1376 }
1377 }
91980990
GKH
1378 }
1379 }
96b3c83d 1380 } else if (ADHOC_ON(pAd)) {
ec278fa2
BZ
1381 /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */
1382 /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */
1383 /* join later. */
96b3c83d
BZ
1384 if (RTMP_TIME_AFTER
1385 (pAd->Mlme.Now32,
1386 pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)
1387 && OPSTATUS_TEST_FLAG(pAd,
1388 fOP_STATUS_MEDIA_STATE_CONNECTED)) {
62eb734b 1389 struct rt_mlme_start_req StartReq;
96b3c83d
BZ
1390
1391 DBGPRINT(RT_DEBUG_TRACE,
1392 ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
91980990
GKH
1393 LinkDown(pAd, FALSE);
1394
96b3c83d 1395 StartParmFill(pAd, &StartReq,
51126deb 1396 (char *) pAd->MlmeAux.Ssid,
96b3c83d
BZ
1397 pAd->MlmeAux.SsidLen);
1398 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ,
62eb734b 1399 sizeof(struct rt_mlme_start_req), &StartReq);
91980990
GKH
1400 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1401 }
59fe2d89 1402
96b3c83d 1403 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
62eb734b 1404 struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i];
59fe2d89
BZ
1405
1406 if (pEntry->ValidAsCLI == FALSE)
1407 continue;
1408
96b3c83d
BZ
1409 if (RTMP_TIME_AFTER
1410 (pAd->Mlme.Now32,
1411 pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1412 MacTableDeleteEntry(pAd, pEntry->Aid,
1413 pEntry->Addr);
59fe2d89 1414 }
ec278fa2 1415 } else /* no INFRA nor ADHOC connection */
91980990
GKH
1416 {
1417
1418 if (pAd->StaCfg.bScanReqIsFromWebUI &&
96b3c83d
BZ
1419 RTMP_TIME_BEFORE(pAd->Mlme.Now32,
1420 pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
91980990 1421 goto SKIP_AUTO_SCAN_CONN;
96b3c83d
BZ
1422 else
1423 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
91980990
GKH
1424
1425 if ((pAd->StaCfg.bAutoReconnect == TRUE)
96b3c83d
BZ
1426 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1427 &&
1428 (MlmeValidateSSID
1429 (pAd->MlmeAux.AutoReconnectSsid,
1430 pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1431 if ((pAd->ScanTab.BssNr == 0)
1432 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) {
62eb734b 1433 struct rt_mlme_scan_req ScanReq;
96b3c83d
BZ
1434
1435 if (RTMP_TIME_AFTER
1436 (pAd->Mlme.Now32,
1437 pAd->StaCfg.LastScanTime + (10 * OS_HZ))) {
1438 DBGPRINT(RT_DEBUG_TRACE,
1439 ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n",
1440 pAd->MlmeAux.
1441 AutoReconnectSsid));
1442 ScanParmFill(pAd, &ScanReq,
51126deb 1443 (char *)pAd->MlmeAux.
96b3c83d
BZ
1444 AutoReconnectSsid,
1445 pAd->MlmeAux.
1446 AutoReconnectSsidLen,
1447 BSS_ANY, SCAN_ACTIVE);
1448 MlmeEnqueue(pAd, SYNC_STATE_MACHINE,
1449 MT2_MLME_SCAN_REQ,
1450 sizeof
62eb734b 1451 (struct rt_mlme_scan_req),
96b3c83d
BZ
1452 &ScanReq);
1453 pAd->Mlme.CntlMachine.CurrState =
1454 CNTL_WAIT_OID_LIST_SCAN;
ec278fa2 1455 /* Reset Missed scan number */
96b3c83d
BZ
1456 pAd->StaCfg.LastScanTime =
1457 pAd->Mlme.Now32;
ec278fa2 1458 } else if (pAd->StaCfg.BssType == BSS_ADHOC) /* Quit the forever scan when in a very clean room */
91980990 1459 MlmeAutoReconnectLastSSID(pAd);
96b3c83d
BZ
1460 } else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1461 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) {
91980990 1462 MlmeAutoScan(pAd);
96b3c83d
BZ
1463 pAd->StaCfg.LastScanTime =
1464 pAd->Mlme.Now32;
1465 } else {
1466 MlmeAutoReconnectLastSSID(pAd);
91980990
GKH
1467 }
1468 }
1469 }
1470 }
1471
1472SKIP_AUTO_SCAN_CONN:
1473
96b3c83d
BZ
1474 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap != 0)
1475 && (pAd->MacTab.fAnyBASession == FALSE)) {
91980990 1476 pAd->MacTab.fAnyBASession = TRUE;
96b3c83d
BZ
1477 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE,
1478 FALSE);
1479 } else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap == 0)
1480 && (pAd->MacTab.fAnyBASession == TRUE)) {
91980990 1481 pAd->MacTab.fAnyBASession = FALSE;
96b3c83d
BZ
1482 AsicUpdateProtect(pAd,
1483 pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1484 OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
91980990 1485 }
91980990 1486
91980990
GKH
1487 return;
1488}
1489
ec278fa2 1490/* Link down report */
51126deb
BZ
1491void LinkDownExec(void *SystemSpecific1,
1492 void *FunctionContext,
1493 void *SystemSpecific2, void *SystemSpecific3)
91980990 1494{
62eb734b 1495 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
91980990 1496
96b3c83d 1497 if (pAd != NULL) {
62eb734b 1498 struct rt_mlme_disassoc_req DisassocReq;
ca97b838
BZ
1499
1500 if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
96b3c83d
BZ
1501 (INFRA_ON(pAd))) {
1502 DBGPRINT(RT_DEBUG_TRACE,
1503 ("LinkDownExec(): disassociate with current AP...\n"));
1504 DisassocParmFill(pAd, &DisassocReq,
1505 pAd->CommonCfg.Bssid,
1506 REASON_DISASSOC_STA_LEAVING);
1507 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
1508 MT2_MLME_DISASSOC_REQ,
62eb734b 1509 sizeof(struct rt_mlme_disassoc_req),
96b3c83d 1510 &DisassocReq);
ca97b838
BZ
1511 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1512
96b3c83d
BZ
1513 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1514 RTMP_IndicateMediaState(pAd);
1515 pAd->ExtraInfo = GENERAL_LINK_DOWN;
ca97b838
BZ
1516 }
1517 }
91980990
GKH
1518}
1519
ec278fa2 1520/* IRQL = DISPATCH_LEVEL */
62eb734b 1521void MlmeAutoScan(struct rt_rtmp_adapter *pAd)
91980990 1522{
ec278fa2 1523 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
96b3c83d 1524 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
91980990
GKH
1525 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1526 MlmeEnqueue(pAd,
96b3c83d
BZ
1527 MLME_CNTL_STATE_MACHINE,
1528 OID_802_11_BSSID_LIST_SCAN,
1529 pAd->MlmeAux.AutoReconnectSsidLen,
1530 pAd->MlmeAux.AutoReconnectSsid);
ca97b838 1531 RTMP_MLME_HANDLER(pAd);
91980990
GKH
1532 }
1533}
1534
ec278fa2 1535/* IRQL = DISPATCH_LEVEL */
62eb734b 1536void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd)
91980990 1537{
96b3c83d
BZ
1538 if (pAd->StaCfg.bAutoConnectByBssid) {
1539 DBGPRINT(RT_DEBUG_TRACE,
aa4d282c 1540 ("Driver auto reconnect to last OID_802_11_BSSID "
1c919d90 1541 "setting - %pM\n", pAd->MlmeAux.Bssid));
ca97b838
BZ
1542
1543 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1544 MlmeEnqueue(pAd,
96b3c83d
BZ
1545 MLME_CNTL_STATE_MACHINE,
1546 OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid);
91980990 1547
ca97b838 1548 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
91980990 1549
ca97b838
BZ
1550 RTMP_MLME_HANDLER(pAd);
1551 }
ec278fa2 1552 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
ca97b838 1553 else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
96b3c83d
BZ
1554 (MlmeValidateSSID
1555 (pAd->MlmeAux.AutoReconnectSsid,
1556 pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
62eb734b 1557 struct rt_ndis_802_11_ssid OidSsid;
91980990 1558 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
96b3c83d
BZ
1559 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid,
1560 pAd->MlmeAux.AutoReconnectSsidLen);
1561
1562 DBGPRINT(RT_DEBUG_TRACE,
1563 ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
1564 pAd->MlmeAux.AutoReconnectSsid,
1565 pAd->MlmeAux.AutoReconnectSsidLen));
1566 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID,
62eb734b 1567 sizeof(struct rt_ndis_802_11_ssid), &OidSsid);
ca97b838 1568 RTMP_MLME_HANDLER(pAd);
91980990
GKH
1569 }
1570}
91980990
GKH
1571
1572/*
1573 ==========================================================================
ca97b838
BZ
1574 Description:
1575 This routine checks if there're other APs out there capable for
1576 roaming. Caller should call this routine only when Link up in INFRA mode
1577 and channel quality is below CQI_GOOD_THRESHOLD.
1578
91980990 1579 IRQL = DISPATCH_LEVEL
ca97b838
BZ
1580
1581 Output:
91980990
GKH
1582 ==========================================================================
1583 */
62eb734b 1584void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32)
91980990 1585{
51126deb 1586 u16 i;
62eb734b
BZ
1587 struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1588 struct rt_bss_entry *pBss;
91980990 1589
ca97b838 1590 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
ec278fa2 1591 /* put all roaming candidates into RoamTab, and sort in RSSI order */
ca97b838 1592 BssTableInit(pRoamTab);
96b3c83d 1593 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
ca97b838
BZ
1594 pBss = &pAd->ScanTab.BssEntry[i];
1595
96b3c83d
BZ
1596 if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) <
1597 Now32)
ec278fa2 1598 continue; /* AP disappear */
ca97b838 1599 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
ec278fa2 1600 continue; /* RSSI too weak. forget it. */
ca97b838 1601 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
ec278fa2 1602 continue; /* skip current AP */
96b3c83d
BZ
1603 if (pBss->Rssi <
1604 (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
ec278fa2 1605 continue; /* only AP with stronger RSSI is eligible for roaming */
ca97b838 1606
ec278fa2 1607 /* AP passing all above rules is put into roaming candidate table */
96b3c83d 1608 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
62eb734b 1609 sizeof(struct rt_bss_entry));
ca97b838 1610 pRoamTab->BssNr += 1;
91980990
GKH
1611 }
1612
96b3c83d 1613 if (pRoamTab->BssNr > 0) {
ec278fa2 1614 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
96b3c83d
BZ
1615 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1616 pAd->RalinkCounters.PoorCQIRoamingCount++;
1617 DBGPRINT(RT_DEBUG_TRACE,
1618 ("MMCHK - Roaming attempt #%ld\n",
1619 pAd->RalinkCounters.PoorCQIRoamingCount));
1620 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1621 MT2_MLME_ROAMING_REQ, 0, NULL);
ca97b838
BZ
1622 RTMP_MLME_HANDLER(pAd);
1623 }
1624 }
96b3c83d
BZ
1625 DBGPRINT(RT_DEBUG_TRACE,
1626 ("<== MlmeCheckForRoaming(# of candidate= %d)\n",
1627 pRoamTab->BssNr));
91980990
GKH
1628}
1629
ca97b838
BZ
1630/*
1631 ==========================================================================
1632 Description:
1633 This routine checks if there're other APs out there capable for
1634 roaming. Caller should call this routine only when link up in INFRA mode
1635 and channel quality is below CQI_GOOD_THRESHOLD.
1636
1637 IRQL = DISPATCH_LEVEL
1638
1639 Output:
1640 ==========================================================================
1641 */
62eb734b 1642BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd)
91980990 1643{
51126deb 1644 u16 i;
62eb734b
BZ
1645 struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1646 struct rt_bss_entry *pBss;
ca97b838
BZ
1647
1648 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
ec278fa2 1649 /* put all roaming candidates into RoamTab, and sort in RSSI order */
ca97b838 1650 BssTableInit(pRoamTab);
96b3c83d 1651 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
ca97b838 1652 pBss = &pAd->ScanTab.BssEntry[i];
91980990 1653
96b3c83d
BZ
1654 if ((pBss->Rssi <= -50)
1655 && (pBss->Channel == pAd->CommonCfg.Channel))
ec278fa2 1656 continue; /* RSSI too weak. forget it. */
ca97b838 1657 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
ec278fa2 1658 continue; /* skip current AP */
96b3c83d
BZ
1659 if (!SSID_EQUAL
1660 (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid,
1661 pAd->CommonCfg.SsidLen))
ec278fa2 1662 continue; /* skip different SSID */
96b3c83d
BZ
1663 if (pBss->Rssi <
1664 (RTMPMaxRssi
1665 (pAd, pAd->StaCfg.RssiSample.LastRssi0,
1666 pAd->StaCfg.RssiSample.LastRssi1,
1667 pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
ec278fa2 1668 continue; /* skip AP without better RSSI */
96b3c83d
BZ
1669
1670 DBGPRINT(RT_DEBUG_TRACE,
1671 ("LastRssi0 = %d, pBss->Rssi = %d\n",
1672 RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0,
1673 pAd->StaCfg.RssiSample.LastRssi1,
1674 pAd->StaCfg.RssiSample.LastRssi2),
1675 pBss->Rssi));
ec278fa2 1676 /* AP passing all above rules is put into roaming candidate table */
96b3c83d 1677 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
62eb734b 1678 sizeof(struct rt_bss_entry));
ca97b838 1679 pRoamTab->BssNr += 1;
96b3c83d 1680 }
91980990 1681
96b3c83d
BZ
1682 DBGPRINT(RT_DEBUG_TRACE,
1683 ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1684 if (pRoamTab->BssNr > 0) {
ec278fa2 1685 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
96b3c83d
BZ
1686 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1687 pAd->RalinkCounters.PoorCQIRoamingCount++;
1688 DBGPRINT(RT_DEBUG_TRACE,
1689 ("MMCHK - Roaming attempt #%ld\n",
1690 pAd->RalinkCounters.PoorCQIRoamingCount));
1691 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1692 MT2_MLME_ROAMING_REQ, 0, NULL);
ca97b838
BZ
1693 RTMP_MLME_HANDLER(pAd);
1694 return TRUE;
96b3c83d
BZ
1695 }
1696 }
91980990 1697
ca97b838
BZ
1698 return FALSE;
1699}
91980990 1700
62eb734b
BZ
1701void MlmeSetTxRate(struct rt_rtmp_adapter *pAd,
1702 struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate)
ca97b838 1703{
51126deb 1704 u8 MaxMode = MODE_OFDM;
91980990 1705
ca97b838 1706 MaxMode = MODE_HTGREENFIELD;
91980990 1707
96b3c83d
BZ
1708 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC)
1709 && (pAd->Antenna.field.TxPath == 2))
ca97b838 1710 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
96b3c83d 1711 else
ca97b838 1712 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
91980990 1713
ca97b838
BZ
1714 if (pTxRate->CurrMCS < MCS_AUTO)
1715 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
91980990 1716
ca97b838
BZ
1717 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1718 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
91980990 1719
96b3c83d 1720 if (ADHOC_ON(pAd)) {
ec278fa2 1721 /* If peer adhoc is b-only mode, we can't send 11g rate. */
ca97b838 1722 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
96b3c83d 1723 pEntry->HTPhyMode.field.STBC = STBC_NONE;
91980990 1724
ec278fa2
BZ
1725 /* */
1726 /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */
1727 /* */
96b3c83d
BZ
1728 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1729 pEntry->HTPhyMode.field.ShortGI =
1730 pAd->StaCfg.HTPhyMode.field.ShortGI;
1731 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
ca97b838 1732
ec278fa2 1733 /* Patch speed error in status page */
ca97b838 1734 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
96b3c83d 1735 } else {
ca97b838 1736 if (pTxRate->Mode <= MaxMode)
96b3c83d 1737 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
91980990 1738
96b3c83d
BZ
1739 if (pTxRate->ShortGI
1740 && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
ca97b838
BZ
1741 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1742 else
1743 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
91980990 1744
ec278fa2 1745 /* Reexam each bandwidth's SGI support. */
96b3c83d
BZ
1746 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) {
1747 if ((pEntry->HTPhyMode.field.BW == BW_20)
1748 &&
1749 (!CLIENT_STATUS_TEST_FLAG
1750 (pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
ca97b838 1751 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
96b3c83d
BZ
1752 if ((pEntry->HTPhyMode.field.BW == BW_40)
1753 &&
1754 (!CLIENT_STATUS_TEST_FLAG
1755 (pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
ca97b838 1756 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
91980990 1757 }
ec278fa2 1758 /* Turn RTS/CTS rate to 6Mbps. */
96b3c83d
BZ
1759 if ((pEntry->HTPhyMode.field.MCS == 0)
1760 && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) {
1761 pEntry->HTPhyMode.field.MCS =
1762 pAd->StaCfg.HTPhyMode.field.MCS;
1763 if (pAd->MacTab.fAnyBASession) {
1764 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1765 ALLN_SETPROTECT, TRUE,
1766 (BOOLEAN) pAd->MlmeAux.
1767 AddHtInfo.AddHtInfo2.
1768 NonGfPresent);
1769 } else {
1770 AsicUpdateProtect(pAd,
1771 pAd->MlmeAux.AddHtInfo.
1772 AddHtInfo2.OperaionMode,
1773 ALLN_SETPROTECT, TRUE,
1774 (BOOLEAN) pAd->MlmeAux.
1775 AddHtInfo.AddHtInfo2.
1776 NonGfPresent);
91980990 1777 }
96b3c83d
BZ
1778 } else if ((pEntry->HTPhyMode.field.MCS == 8)
1779 && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) {
1780 pEntry->HTPhyMode.field.MCS =
1781 pAd->StaCfg.HTPhyMode.field.MCS;
1782 if (pAd->MacTab.fAnyBASession) {
1783 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1784 ALLN_SETPROTECT, TRUE,
1785 (BOOLEAN) pAd->MlmeAux.
1786 AddHtInfo.AddHtInfo2.
1787 NonGfPresent);
1788 } else {
1789 AsicUpdateProtect(pAd,
1790 pAd->MlmeAux.AddHtInfo.
1791 AddHtInfo2.OperaionMode,
1792 ALLN_SETPROTECT, TRUE,
1793 (BOOLEAN) pAd->MlmeAux.
1794 AddHtInfo.AddHtInfo2.
1795 NonGfPresent);
ca97b838 1796 }
96b3c83d
BZ
1797 } else if ((pEntry->HTPhyMode.field.MCS != 0)
1798 && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) {
1799 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1800 TRUE,
1801 (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1802 AddHtInfo2.NonGfPresent);
1803
1804 } else if ((pEntry->HTPhyMode.field.MCS != 8)
1805 && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) {
1806 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1807 TRUE,
1808 (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1809 AddHtInfo2.NonGfPresent);
91980990 1810 }
91980990 1811
96b3c83d
BZ
1812 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1813 pEntry->HTPhyMode.field.ShortGI =
1814 pAd->StaCfg.HTPhyMode.field.ShortGI;
1815 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1816 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1817 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD)
1818 && pAd->WIFItestbed.bGreenField)
1819 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1820 }
1821
51126deb 1822 pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word);
91980990
GKH
1823}
1824
91980990
GKH
1825/*
1826 ==========================================================================
1827 Description:
ca97b838
BZ
1828 This routine calculates the acumulated TxPER of eaxh TxRate. And
1829 according to the calculation result, change CommonCfg.TxRate which
1830 is the stable TX Rate we expect the Radio situation could sustained.
1831
1832 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1833 Output:
1834 CommonCfg.TxRate -
91980990
GKH
1835
1836 IRQL = DISPATCH_LEVEL
1837
ca97b838
BZ
1838 NOTE:
1839 call this routine every second
91980990
GKH
1840 ==========================================================================
1841 */
62eb734b 1842void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd)
91980990 1843{
51126deb
BZ
1844 u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1845 unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt;
1846 unsigned long TxErrorRatio = 0;
96b3c83d 1847 BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
62eb734b 1848 struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
51126deb
BZ
1849 u8 *pTable;
1850 u8 TableSize = 0;
1851 u8 InitTxRateIdx = 0, TrainUp, TrainDown;
1852 char Rssi, RssiOffset = 0;
96b3c83d
BZ
1853 TX_STA_CNT1_STRUC StaTx1;
1854 TX_STA_CNT0_STRUC TxStaCnt0;
51126deb 1855 unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
62eb734b
BZ
1856 struct rt_mac_table_entry *pEntry;
1857 struct rt_rssi_sample *pRssi = &pAd->StaCfg.RssiSample;
91980990 1858
ec278fa2
BZ
1859 /* */
1860 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
1861 /* */
96b3c83d 1862 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
ca97b838 1863 pEntry = &pAd->MacTab.Content[i];
91980990 1864
ec278fa2 1865 /* check if this entry need to switch rate automatically */
ca97b838
BZ
1866 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1867 continue;
91980990 1868
96b3c83d 1869 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) {
ca97b838 1870 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1871 pRssi->AvgRssi0,
1872 pRssi->AvgRssi1, pRssi->AvgRssi2);
91980990 1873
ec278fa2 1874 /* Update statistic counter */
ca97b838
BZ
1875 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1876 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1877 pAd->bUpdateBcnCntDone = TRUE;
1878 TxRetransmit = StaTx1.field.TxRetransmit;
1879 TxSuccess = StaTx1.field.TxSuccess;
1880 TxFailCount = TxStaCnt0.field.TxFailCount;
1881 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
91980990 1882
96b3c83d
BZ
1883 pAd->RalinkCounters.OneSecTxRetryOkCount +=
1884 StaTx1.field.TxRetransmit;
1885 pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
1886 StaTx1.field.TxSuccess;
1887 pAd->RalinkCounters.OneSecTxFailCount +=
1888 TxStaCnt0.field.TxFailCount;
1889 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
1890 StaTx1.field.TxSuccess;
1891 pAd->WlanCounters.RetryCount.u.LowPart +=
1892 StaTx1.field.TxRetransmit;
1893 pAd->WlanCounters.FailedCount.u.LowPart +=
1894 TxStaCnt0.field.TxFailCount;
91980990 1895
ec278fa2
BZ
1896 /* if no traffic in the past 1-sec period, don't change TX rate, */
1897 /* but clear all bad history. because the bad history may affect the next */
1898 /* Chariot throughput test */
96b3c83d
BZ
1899 AccuTxTotalCnt =
1900 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1901 pAd->RalinkCounters.OneSecTxRetryOkCount +
1902 pAd->RalinkCounters.OneSecTxFailCount;
91980990 1903
ca97b838 1904 if (TxTotalCnt)
96b3c83d
BZ
1905 TxErrorRatio =
1906 ((TxRetransmit +
1907 TxFailCount) * 100) / TxTotalCnt;
1908 } else {
ca97b838
BZ
1909 if (INFRA_ON(pAd) && (i == 1))
1910 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1911 pRssi->AvgRssi0,
1912 pRssi->AvgRssi1,
1913 pRssi->AvgRssi2);
ca97b838
BZ
1914 else
1915 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1916 pEntry->RssiSample.AvgRssi0,
1917 pEntry->RssiSample.AvgRssi1,
1918 pEntry->RssiSample.AvgRssi2);
91980990 1919
ca97b838 1920 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
96b3c83d
BZ
1921 pEntry->OneSecTxRetryOkCount +
1922 pEntry->OneSecTxFailCount;
91980990 1923
ca97b838 1924 if (TxTotalCnt)
96b3c83d
BZ
1925 TxErrorRatio =
1926 ((pEntry->OneSecTxRetryOkCount +
1927 pEntry->OneSecTxFailCount) * 100) /
1928 TxTotalCnt;
1929 }
91980990 1930
96b3c83d 1931 if (TxTotalCnt) {
ca97b838 1932 /*
96b3c83d
BZ
1933 Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1934 We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1935 */
1936 if (TxErrorRatio == 100) {
1937 TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp;
51126deb
BZ
1938 unsigned long Index;
1939 unsigned long MACValue;
ca97b838
BZ
1940
1941 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1942 TxRtyCfgtmp.word = TxRtyCfg.word;
1943 TxRtyCfg.field.LongRtyLimit = 0x0;
1944 TxRtyCfg.field.ShortRtyLimit = 0x0;
1945 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1946
1947 RTMPusecDelay(1);
1948
1949 Index = 0;
1950 MACValue = 0;
96b3c83d
BZ
1951 do {
1952 RTMP_IO_READ32(pAd, TXRXQ_PCNT,
1953 &MACValue);
ca97b838
BZ
1954 if ((MACValue & 0xffffff) == 0)
1955 break;
1956 Index++;
1957 RTMPusecDelay(1000);
96b3c83d
BZ
1958 } while ((Index < 330)
1959 &&
1960 (!RTMP_TEST_FLAG
1961 (pAd,
1962 fRTMP_ADAPTER_HALT_IN_PROGRESS)));
ca97b838
BZ
1963
1964 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
96b3c83d
BZ
1965 TxRtyCfg.field.LongRtyLimit =
1966 TxRtyCfgtmp.field.LongRtyLimit;
1967 TxRtyCfg.field.ShortRtyLimit =
1968 TxRtyCfgtmp.field.ShortRtyLimit;
ca97b838 1969 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
96b3c83d 1970 }
91980990 1971 }
91980990 1972
ca97b838 1973 CurrRateIdx = pEntry->CurrTxRateIndex;
91980990 1974
96b3c83d
BZ
1975 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
1976 &InitTxRateIdx);
91980990 1977
96b3c83d 1978 if (CurrRateIdx >= TableSize) {
ca97b838
BZ
1979 CurrRateIdx = TableSize - 1;
1980 }
ec278fa2
BZ
1981 /* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */
1982 /* So need to sync here. */
96b3c83d 1983 pCurrTxRate =
62eb734b 1984 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
ca97b838 1985 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
ec278fa2 1986 /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */
96b3c83d 1987 ) {
91980990 1988
ec278fa2
BZ
1989 /* Need to sync Real Tx rate and our record. */
1990 /* Then return for next DRS. */
96b3c83d 1991 pCurrTxRate =
62eb734b 1992 (struct rt_rtmp_tx_rate_switch *) & pTable[(InitTxRateIdx + 1)
96b3c83d 1993 * 5];
ca97b838
BZ
1994 pEntry->CurrTxRateIndex = InitTxRateIdx;
1995 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
91980990 1996
ec278fa2 1997 /* reset all OneSecTx counters */
ca97b838
BZ
1998 RESET_ONE_SEC_TX_CNT(pEntry);
1999 continue;
2000 }
ec278fa2 2001 /* decide the next upgrade rate and downgrade rate, if any */
96b3c83d 2002 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
ca97b838 2003 UpRateIdx = CurrRateIdx + 1;
96b3c83d
BZ
2004 DownRateIdx = CurrRateIdx - 1;
2005 } else if (CurrRateIdx == 0) {
ca97b838
BZ
2006 UpRateIdx = CurrRateIdx + 1;
2007 DownRateIdx = CurrRateIdx;
96b3c83d 2008 } else if (CurrRateIdx == (TableSize - 1)) {
ca97b838
BZ
2009 UpRateIdx = CurrRateIdx;
2010 DownRateIdx = CurrRateIdx - 1;
96b3c83d 2011 }
91980990 2012
96b3c83d 2013 pCurrTxRate =
62eb734b 2014 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
96b3c83d
BZ
2015
2016 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2017 TrainUp =
2018 (pCurrTxRate->TrainUp +
2019 (pCurrTxRate->TrainUp >> 1));
2020 TrainDown =
2021 (pCurrTxRate->TrainDown +
2022 (pCurrTxRate->TrainDown >> 1));
2023 } else {
2024 TrainUp = pCurrTxRate->TrainUp;
2025 TrainDown = pCurrTxRate->TrainDown;
2026 }
91980990 2027
ec278fa2 2028 /*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */
91980990 2029
ec278fa2
BZ
2030 /* */
2031 /* Keep the last time TxRateChangeAction status. */
2032 /* */
96b3c83d
BZ
2033 pEntry->LastTimeTxRateChangeAction =
2034 pEntry->LastSecTxRateChangeAction;
91980990 2035
ec278fa2
BZ
2036 /* */
2037 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2038 /* (criteria copied from RT2500 for Netopia case) */
2039 /* */
96b3c83d 2040 if (TxTotalCnt <= 15) {
51126deb
BZ
2041 char idx = 0;
2042 u8 TxRateIdx;
2043 u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 =
96b3c83d 2044 0, MCS5 = 0, MCS6 = 0, MCS7 = 0;
51126deb
BZ
2045 u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2046 u8 MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; /* 3*3 */
91980990 2047
ec278fa2 2048 /* check the existence and index of each needed MCS */
96b3c83d
BZ
2049 while (idx < pTable[0]) {
2050 pCurrTxRate =
62eb734b 2051 (struct rt_rtmp_tx_rate_switch *) & pTable[(idx + 1) *
96b3c83d 2052 5];
91980990 2053
96b3c83d 2054 if (pCurrTxRate->CurrMCS == MCS_0) {
ca97b838 2055 MCS0 = idx;
96b3c83d 2056 } else if (pCurrTxRate->CurrMCS == MCS_1) {
ca97b838 2057 MCS1 = idx;
96b3c83d 2058 } else if (pCurrTxRate->CurrMCS == MCS_2) {
ca97b838 2059 MCS2 = idx;
96b3c83d 2060 } else if (pCurrTxRate->CurrMCS == MCS_3) {
ca97b838 2061 MCS3 = idx;
96b3c83d 2062 } else if (pCurrTxRate->CurrMCS == MCS_4) {
ca97b838 2063 MCS4 = idx;
96b3c83d
BZ
2064 } else if (pCurrTxRate->CurrMCS == MCS_5) {
2065 MCS5 = idx;
2066 } else if (pCurrTxRate->CurrMCS == MCS_6) {
2067 MCS6 = idx;
2068 }
ec278fa2
BZ
2069 /*else if (pCurrTxRate->CurrMCS == MCS_7) */
2070 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) /* prevent the highest MCS using short GI when 1T and low throughput */
96b3c83d 2071 {
ca97b838 2072 MCS7 = idx;
96b3c83d 2073 } else if (pCurrTxRate->CurrMCS == MCS_12) {
ca97b838 2074 MCS12 = idx;
96b3c83d 2075 } else if (pCurrTxRate->CurrMCS == MCS_13) {
ca97b838 2076 MCS13 = idx;
96b3c83d 2077 } else if (pCurrTxRate->CurrMCS == MCS_14) {
ca97b838 2078 MCS14 = idx;
96b3c83d 2079 }
ec278fa2 2080 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 */
96b3c83d 2081 {
ca97b838 2082 MCS15 = idx;
ec278fa2 2083 } else if (pCurrTxRate->CurrMCS == MCS_20) /* 3*3 */
ca97b838
BZ
2084 {
2085 MCS20 = idx;
96b3c83d 2086 } else if (pCurrTxRate->CurrMCS == MCS_21) {
ca97b838 2087 MCS21 = idx;
96b3c83d 2088 } else if (pCurrTxRate->CurrMCS == MCS_22) {
ca97b838 2089 MCS22 = idx;
96b3c83d 2090 } else if (pCurrTxRate->CurrMCS == MCS_23) {
ca97b838
BZ
2091 MCS23 = idx;
2092 }
96b3c83d 2093 idx++;
ca97b838 2094 }
91980990 2095
96b3c83d
BZ
2096 if (pAd->LatchRfRegs.Channel <= 14) {
2097 if (pAd->NicConfig2.field.ExternalLNAForG) {
ca97b838 2098 RssiOffset = 2;
96b3c83d 2099 } else {
ca97b838
BZ
2100 RssiOffset = 5;
2101 }
96b3c83d
BZ
2102 } else {
2103 if (pAd->NicConfig2.field.ExternalLNAForA) {
ca97b838 2104 RssiOffset = 5;
96b3c83d 2105 } else {
ca97b838
BZ
2106 RssiOffset = 8;
2107 }
2108 }
91980990 2109
96b3c83d 2110 /*if (MCS15) */
ec278fa2 2111 if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) { /* N mode with 3 stream // 3*3 */
ca97b838
BZ
2112 if (MCS23 && (Rssi >= -70))
2113 TxRateIdx = MCS23;
2114 else if (MCS22 && (Rssi >= -72))
2115 TxRateIdx = MCS22;
96b3c83d 2116 else if (MCS21 && (Rssi >= -76))
ca97b838
BZ
2117 TxRateIdx = MCS21;
2118 else if (MCS20 && (Rssi >= -78))
2119 TxRateIdx = MCS20;
96b3c83d
BZ
2120 else if (MCS4 && (Rssi >= -82))
2121 TxRateIdx = MCS4;
2122 else if (MCS3 && (Rssi >= -84))
2123 TxRateIdx = MCS3;
2124 else if (MCS2 && (Rssi >= -86))
2125 TxRateIdx = MCS2;
2126 else if (MCS1 && (Rssi >= -88))
2127 TxRateIdx = MCS1;
2128 else
2129 TxRateIdx = MCS0;
2130 }
ec278fa2
BZ
2131/* else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */
2132 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand)) /* 3*3 */
2133 { /* N mode with 2 stream */
96b3c83d 2134 if (MCS15 && (Rssi >= (-70 + RssiOffset)))
ca97b838 2135 TxRateIdx = MCS15;
96b3c83d 2136 else if (MCS14 && (Rssi >= (-72 + RssiOffset)))
ca97b838 2137 TxRateIdx = MCS14;
96b3c83d 2138 else if (MCS13 && (Rssi >= (-76 + RssiOffset)))
ca97b838 2139 TxRateIdx = MCS13;
96b3c83d 2140 else if (MCS12 && (Rssi >= (-78 + RssiOffset)))
ca97b838 2141 TxRateIdx = MCS12;
96b3c83d 2142 else if (MCS4 && (Rssi >= (-82 + RssiOffset)))
ca97b838 2143 TxRateIdx = MCS4;
96b3c83d 2144 else if (MCS3 && (Rssi >= (-84 + RssiOffset)))
ca97b838 2145 TxRateIdx = MCS3;
96b3c83d 2146 else if (MCS2 && (Rssi >= (-86 + RssiOffset)))
ca97b838 2147 TxRateIdx = MCS2;
96b3c83d 2148 else if (MCS1 && (Rssi >= (-88 + RssiOffset)))
ca97b838
BZ
2149 TxRateIdx = MCS1;
2150 else
2151 TxRateIdx = MCS0;
ec278fa2 2152 } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) { /* N mode with 1 stream */
96b3c83d 2153 if (MCS7 && (Rssi > (-72 + RssiOffset)))
ca97b838 2154 TxRateIdx = MCS7;
96b3c83d 2155 else if (MCS6 && (Rssi > (-74 + RssiOffset)))
ca97b838 2156 TxRateIdx = MCS6;
96b3c83d 2157 else if (MCS5 && (Rssi > (-77 + RssiOffset)))
ca97b838 2158 TxRateIdx = MCS5;
96b3c83d 2159 else if (MCS4 && (Rssi > (-79 + RssiOffset)))
ca97b838 2160 TxRateIdx = MCS4;
96b3c83d 2161 else if (MCS3 && (Rssi > (-81 + RssiOffset)))
ca97b838 2162 TxRateIdx = MCS3;
96b3c83d 2163 else if (MCS2 && (Rssi > (-83 + RssiOffset)))
ca97b838 2164 TxRateIdx = MCS2;
96b3c83d 2165 else if (MCS1 && (Rssi > (-86 + RssiOffset)))
ca97b838
BZ
2166 TxRateIdx = MCS1;
2167 else
2168 TxRateIdx = MCS0;
ec278fa2 2169 } else { /* Legacy mode */
ca97b838
BZ
2170 if (MCS7 && (Rssi > -70))
2171 TxRateIdx = MCS7;
2172 else if (MCS6 && (Rssi > -74))
2173 TxRateIdx = MCS6;
2174 else if (MCS5 && (Rssi > -78))
2175 TxRateIdx = MCS5;
2176 else if (MCS4 && (Rssi > -82))
2177 TxRateIdx = MCS4;
ec278fa2 2178 else if (MCS4 == 0) /* for B-only mode */
ca97b838
BZ
2179 TxRateIdx = MCS3;
2180 else if (MCS3 && (Rssi > -85))
2181 TxRateIdx = MCS3;
2182 else if (MCS2 && (Rssi > -87))
2183 TxRateIdx = MCS2;
2184 else if (MCS1 && (Rssi > -90))
2185 TxRateIdx = MCS1;
2186 else
2187 TxRateIdx = MCS0;
2188 }
91980990 2189
ec278fa2 2190 /* if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */
ca97b838
BZ
2191 {
2192 pEntry->CurrTxRateIndex = TxRateIdx;
96b3c83d 2193 pNextTxRate =
62eb734b 2194 (struct rt_rtmp_tx_rate_switch *) &
96b3c83d 2195 pTable[(pEntry->CurrTxRateIndex + 1) * 5];
ca97b838
BZ
2196 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2197 }
91980990 2198
96b3c83d 2199 NdisZeroMemory(pEntry->TxQuality,
51126deb 2200 sizeof(u16)*
96b3c83d
BZ
2201 MAX_STEP_OF_TX_RATE_SWITCH);
2202 NdisZeroMemory(pEntry->PER,
51126deb 2203 sizeof(u8)*
96b3c83d 2204 MAX_STEP_OF_TX_RATE_SWITCH);
ca97b838 2205 pEntry->fLastSecAccordingRSSI = TRUE;
ec278fa2 2206 /* reset all OneSecTx counters */
ca97b838 2207 RESET_ONE_SEC_TX_CNT(pEntry);
91980990 2208
ca97b838
BZ
2209 continue;
2210 }
91980990 2211
96b3c83d 2212 if (pEntry->fLastSecAccordingRSSI == TRUE) {
ca97b838
BZ
2213 pEntry->fLastSecAccordingRSSI = FALSE;
2214 pEntry->LastSecTxRateChangeAction = 0;
ec278fa2 2215 /* reset all OneSecTx counters */
ca97b838
BZ
2216 RESET_ONE_SEC_TX_CNT(pEntry);
2217
2218 continue;
91980990
GKH
2219 }
2220
96b3c83d
BZ
2221 do {
2222 BOOLEAN bTrainUpDown = FALSE;
1623267a 2223
96b3c83d 2224 pEntry->CurrTxRateStableTime++;
91980990 2225
ec278fa2 2226 /* downgrade TX quality if PER >= Rate-Down threshold */
96b3c83d 2227 if (TxErrorRatio >= TrainDown) {
ca97b838 2228 bTrainUpDown = TRUE;
96b3c83d
BZ
2229 pEntry->TxQuality[CurrRateIdx] =
2230 DRS_TX_QUALITY_WORST_BOUND;
91980990 2231 }
ec278fa2 2232 /* upgrade TX quality if PER <= Rate-Up threshold */
96b3c83d 2233 else if (TxErrorRatio <= TrainUp) {
ca97b838
BZ
2234 bTrainUpDown = TRUE;
2235 bUpgradeQuality = TRUE;
2236 if (pEntry->TxQuality[CurrRateIdx])
ec278fa2 2237 pEntry->TxQuality[CurrRateIdx]--; /* quality very good in CurrRate */
ca97b838
BZ
2238
2239 if (pEntry->TxRateUpPenalty)
96b3c83d 2240 pEntry->TxRateUpPenalty--;
ca97b838 2241 else if (pEntry->TxQuality[UpRateIdx])
ec278fa2 2242 pEntry->TxQuality[UpRateIdx]--; /* may improve next UP rate's quality */
91980990
GKH
2243 }
2244
51126deb 2245 pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio;
91980990 2246
96b3c83d 2247 if (bTrainUpDown) {
ec278fa2 2248 /* perform DRS - consider TxRate Down first, then rate up. */
96b3c83d
BZ
2249 if ((CurrRateIdx != DownRateIdx)
2250 && (pEntry->TxQuality[CurrRateIdx] >=
2251 DRS_TX_QUALITY_WORST_BOUND)) {
ca97b838 2252 pEntry->CurrTxRateIndex = DownRateIdx;
96b3c83d
BZ
2253 } else if ((CurrRateIdx != UpRateIdx)
2254 && (pEntry->TxQuality[UpRateIdx] <=
2255 0)) {
ca97b838 2256 pEntry->CurrTxRateIndex = UpRateIdx;
91980990
GKH
2257 }
2258 }
ca97b838 2259 } while (FALSE);
91980990 2260
ec278fa2 2261 /* if rate-up happen, clear all bad history of all TX rates */
96b3c83d 2262 if (pEntry->CurrTxRateIndex > CurrRateIdx) {
ca97b838
BZ
2263 pEntry->CurrTxRateStableTime = 0;
2264 pEntry->TxRateUpPenalty = 0;
ec278fa2 2265 pEntry->LastSecTxRateChangeAction = 1; /* rate UP */
96b3c83d 2266 NdisZeroMemory(pEntry->TxQuality,
51126deb 2267 sizeof(u16)*
96b3c83d
BZ
2268 MAX_STEP_OF_TX_RATE_SWITCH);
2269 NdisZeroMemory(pEntry->PER,
51126deb 2270 sizeof(u8)*
96b3c83d 2271 MAX_STEP_OF_TX_RATE_SWITCH);
91980990 2272
ec278fa2
BZ
2273 /* */
2274 /* For TxRate fast train up */
2275 /* */
96b3c83d
BZ
2276 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2277 RTMPSetTimer(&pAd->StaCfg.
2278 StaQuickResponeForRateUpTimer,
2279 100);
91980990 2280
96b3c83d
BZ
2281 pAd->StaCfg.
2282 StaQuickResponeForRateUpTimerRunning = TRUE;
91980990 2283 }
ca97b838
BZ
2284 bTxRateChanged = TRUE;
2285 }
ec278fa2 2286 /* if rate-down happen, only clear DownRate's bad history */
96b3c83d 2287 else if (pEntry->CurrTxRateIndex < CurrRateIdx) {
ca97b838 2288 pEntry->CurrTxRateStableTime = 0;
ec278fa2
BZ
2289 pEntry->TxRateUpPenalty = 0; /* no penalty */
2290 pEntry->LastSecTxRateChangeAction = 2; /* rate DOWN */
ca97b838
BZ
2291 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2292 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
91980990 2293
ec278fa2
BZ
2294 /* */
2295 /* For TxRate fast train down */
2296 /* */
96b3c83d
BZ
2297 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2298 RTMPSetTimer(&pAd->StaCfg.
2299 StaQuickResponeForRateUpTimer,
2300 100);
91980990 2301
96b3c83d
BZ
2302 pAd->StaCfg.
2303 StaQuickResponeForRateUpTimerRunning = TRUE;
ca97b838
BZ
2304 }
2305 bTxRateChanged = TRUE;
96b3c83d 2306 } else {
ec278fa2 2307 pEntry->LastSecTxRateChangeAction = 0; /* rate no change */
ca97b838 2308 bTxRateChanged = FALSE;
91980990
GKH
2309 }
2310
ca97b838 2311 pEntry->LastTxOkCount = TxSuccess;
91980990 2312 {
51126deb 2313 u8 tmpTxRate;
ca97b838 2314
ec278fa2 2315 /* to fix tcp ack issue */
96b3c83d
BZ
2316 if (!bTxRateChanged
2317 && (pAd->RalinkCounters.OneSecReceivedByteCount >
2318 (pAd->RalinkCounters.
2319 OneSecTransmittedByteCount * 5))) {
ca97b838 2320 tmpTxRate = DownRateIdx;
96b3c83d
BZ
2321 DBGPRINT_RAW(RT_DEBUG_TRACE,
2322 ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2323 pAd->RalinkCounters.
2324 OneSecReceivedByteCount,
2325 pAd->RalinkCounters.
2326 OneSecTransmittedByteCount,
2327 pEntry->CurrTxRateIndex,
2328 tmpTxRate));
2329 } else {
ca97b838 2330 tmpTxRate = pEntry->CurrTxRateIndex;
91980990 2331 }
ca97b838 2332
96b3c83d 2333 pNextTxRate =
62eb734b 2334 (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) *
96b3c83d 2335 5];
ca97b838 2336 }
96b3c83d 2337 if (bTxRateChanged && pNextTxRate) {
ca97b838 2338 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
91980990 2339 }
ec278fa2 2340 /* reset all OneSecTx counters */
ca97b838 2341 RESET_ONE_SEC_TX_CNT(pEntry);
91980990
GKH
2342 }
2343}
91980990 2344
ca97b838
BZ
2345/*
2346 ========================================================================
2347 Routine Description:
2348 Station side, Auto TxRate faster train up timer call back function.
2349
2350 Arguments:
2351 SystemSpecific1 - Not used.
2352 FunctionContext - Pointer to our Adapter context.
2353 SystemSpecific2 - Not used.
2354 SystemSpecific3 - Not used.
2355
2356 Return Value:
2357 None
2358
2359 ========================================================================
2360*/
51126deb
BZ
2361void StaQuickResponeForRateUpExec(void *SystemSpecific1,
2362 void *FunctionContext,
2363 void *SystemSpecific2,
2364 void *SystemSpecific3)
91980990 2365{
62eb734b 2366 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
51126deb
BZ
2367 u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2368 unsigned long TxTotalCnt;
2369 unsigned long TxErrorRatio = 0;
ec278fa2 2370 BOOLEAN bTxRateChanged; /*, bUpgradeQuality = FALSE; */
62eb734b 2371 struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
51126deb
BZ
2372 u8 *pTable;
2373 u8 TableSize = 0;
2374 u8 InitTxRateIdx = 0, TrainUp, TrainDown;
96b3c83d
BZ
2375 TX_STA_CNT1_STRUC StaTx1;
2376 TX_STA_CNT0_STRUC TxStaCnt0;
51126deb
BZ
2377 char Rssi, ratio;
2378 unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
62eb734b 2379 struct rt_mac_table_entry *pEntry;
51126deb 2380 unsigned long i;
91980990 2381
ca97b838
BZ
2382 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2383
ec278fa2
BZ
2384 /* */
2385 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
2386 /* */
96b3c83d 2387 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
ca97b838 2388 pEntry = &pAd->MacTab.Content[i];
91980990 2389
ec278fa2 2390 /* check if this entry need to switch rate automatically */
ca97b838
BZ
2391 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2392 continue;
91980990 2393
ca97b838
BZ
2394 if (INFRA_ON(pAd) && (i == 1))
2395 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
2396 pAd->StaCfg.RssiSample.AvgRssi0,
2397 pAd->StaCfg.RssiSample.AvgRssi1,
2398 pAd->StaCfg.RssiSample.AvgRssi2);
ca97b838
BZ
2399 else
2400 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
2401 pEntry->RssiSample.AvgRssi0,
2402 pEntry->RssiSample.AvgRssi1,
2403 pEntry->RssiSample.AvgRssi2);
91980990 2404
ca97b838 2405 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
91980990 2406
96b3c83d
BZ
2407 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
2408 &InitTxRateIdx);
91980990 2409
ec278fa2 2410 /* decide the next upgrade rate and downgrade rate, if any */
96b3c83d 2411 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
ca97b838 2412 UpRateIdx = CurrRateIdx + 1;
96b3c83d
BZ
2413 DownRateIdx = CurrRateIdx - 1;
2414 } else if (CurrRateIdx == 0) {
ca97b838
BZ
2415 UpRateIdx = CurrRateIdx + 1;
2416 DownRateIdx = CurrRateIdx;
96b3c83d 2417 } else if (CurrRateIdx == (TableSize - 1)) {
ca97b838
BZ
2418 UpRateIdx = CurrRateIdx;
2419 DownRateIdx = CurrRateIdx - 1;
2420 }
91980990 2421
96b3c83d 2422 pCurrTxRate =
62eb734b 2423 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
96b3c83d
BZ
2424
2425 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2426 TrainUp =
2427 (pCurrTxRate->TrainUp +
2428 (pCurrTxRate->TrainUp >> 1));
2429 TrainDown =
2430 (pCurrTxRate->TrainDown +
2431 (pCurrTxRate->TrainDown >> 1));
2432 } else {
2433 TrainUp = pCurrTxRate->TrainUp;
2434 TrainDown = pCurrTxRate->TrainDown;
ca97b838
BZ
2435 }
2436
96b3c83d 2437 if (pAd->MacTab.Size == 1) {
ec278fa2 2438 /* Update statistic counter */
ca97b838
BZ
2439 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2440 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2441
2442 TxRetransmit = StaTx1.field.TxRetransmit;
2443 TxSuccess = StaTx1.field.TxSuccess;
2444 TxFailCount = TxStaCnt0.field.TxFailCount;
2445 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2446
96b3c83d
BZ
2447 pAd->RalinkCounters.OneSecTxRetryOkCount +=
2448 StaTx1.field.TxRetransmit;
2449 pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
2450 StaTx1.field.TxSuccess;
2451 pAd->RalinkCounters.OneSecTxFailCount +=
2452 TxStaCnt0.field.TxFailCount;
2453 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
2454 StaTx1.field.TxSuccess;
2455 pAd->WlanCounters.RetryCount.u.LowPart +=
2456 StaTx1.field.TxRetransmit;
2457 pAd->WlanCounters.FailedCount.u.LowPart +=
2458 TxStaCnt0.field.TxFailCount;
ca97b838
BZ
2459
2460 if (TxTotalCnt)
96b3c83d
BZ
2461 TxErrorRatio =
2462 ((TxRetransmit +
2463 TxFailCount) * 100) / TxTotalCnt;
2464 } else {
ca97b838 2465 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
96b3c83d
BZ
2466 pEntry->OneSecTxRetryOkCount +
2467 pEntry->OneSecTxFailCount;
91980990 2468
ca97b838 2469 if (TxTotalCnt)
96b3c83d
BZ
2470 TxErrorRatio =
2471 ((pEntry->OneSecTxRetryOkCount +
2472 pEntry->OneSecTxFailCount) * 100) /
2473 TxTotalCnt;
ca97b838 2474 }
91980990 2475
ec278fa2
BZ
2476 /* */
2477 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2478 /* (criteria copied from RT2500 for Netopia case) */
2479 /* */
96b3c83d
BZ
2480 if (TxTotalCnt <= 12) {
2481 NdisZeroMemory(pAd->DrsCounters.TxQuality,
51126deb 2482 sizeof(u16)*
96b3c83d
BZ
2483 MAX_STEP_OF_TX_RATE_SWITCH);
2484 NdisZeroMemory(pAd->DrsCounters.PER,
51126deb 2485 sizeof(u8)*
96b3c83d
BZ
2486 MAX_STEP_OF_TX_RATE_SWITCH);
2487
2488 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2489 && (CurrRateIdx != DownRateIdx)) {
ca97b838 2490 pAd->CommonCfg.TxRateIndex = DownRateIdx;
96b3c83d
BZ
2491 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2492 DRS_TX_QUALITY_WORST_BOUND;
2493 } else
2494 if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2495 2) && (CurrRateIdx != UpRateIdx)) {
ca97b838
BZ
2496 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2497 }
91980990 2498
96b3c83d
BZ
2499 DBGPRINT_RAW(RT_DEBUG_TRACE,
2500 ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
ca97b838
BZ
2501 return;
2502 }
91980990 2503
96b3c83d 2504 do {
51126deb 2505 unsigned long OneSecTxNoRetryOKRationCount;
91980990 2506
ca97b838
BZ
2507 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2508 ratio = 5;
2509 else
2510 ratio = 4;
91980990 2511
ec278fa2 2512 /* downgrade TX quality if PER >= Rate-Down threshold */
96b3c83d
BZ
2513 if (TxErrorRatio >= TrainDown) {
2514 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2515 DRS_TX_QUALITY_WORST_BOUND;
ca97b838 2516 }
91980990 2517
96b3c83d 2518 pAd->DrsCounters.PER[CurrRateIdx] =
51126deb 2519 (u8)TxErrorRatio;
91980990 2520
ca97b838 2521 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
91980990 2522
ec278fa2 2523 /* perform DRS - consider TxRate Down first, then rate up. */
96b3c83d
BZ
2524 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2525 && (CurrRateIdx != DownRateIdx)) {
2526 if ((pAd->DrsCounters.LastTxOkCount + 2) >=
2527 OneSecTxNoRetryOKRationCount) {
2528 pAd->CommonCfg.TxRateIndex =
2529 DownRateIdx;
2530 pAd->DrsCounters.
2531 TxQuality[CurrRateIdx] =
2532 DRS_TX_QUALITY_WORST_BOUND;
ca97b838 2533
91980990 2534 }
91980990 2535
96b3c83d
BZ
2536 } else
2537 if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2538 2) && (CurrRateIdx != UpRateIdx)) {
2539 if ((TxErrorRatio >= 50)
2540 || (TxErrorRatio >= TrainDown)) {
91980990 2541
96b3c83d
BZ
2542 } else if ((pAd->DrsCounters.LastTxOkCount + 2)
2543 >= OneSecTxNoRetryOKRationCount) {
ca97b838 2544 pAd->CommonCfg.TxRateIndex = UpRateIdx;
91980990 2545 }
ca97b838 2546 }
96b3c83d 2547 } while (FALSE);
91980990 2548
ec278fa2 2549 /* if rate-up happen, clear all bad history of all TX rates */
96b3c83d 2550 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) {
ca97b838 2551 pAd->DrsCounters.TxRateUpPenalty = 0;
96b3c83d 2552 NdisZeroMemory(pAd->DrsCounters.TxQuality,
51126deb 2553 sizeof(u16)*
96b3c83d
BZ
2554 MAX_STEP_OF_TX_RATE_SWITCH);
2555 NdisZeroMemory(pAd->DrsCounters.PER,
51126deb 2556 sizeof(u8)*
96b3c83d 2557 MAX_STEP_OF_TX_RATE_SWITCH);
ca97b838
BZ
2558 bTxRateChanged = TRUE;
2559 }
ec278fa2 2560 /* if rate-down happen, only clear DownRate's bad history */
96b3c83d
BZ
2561 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) {
2562 DBGPRINT_RAW(RT_DEBUG_TRACE,
2563 ("QuickDRS: --TX rate from %d to %d \n",
2564 CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2565
ec278fa2 2566 pAd->DrsCounters.TxRateUpPenalty = 0; /* no penalty */
96b3c83d
BZ
2567 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] =
2568 0;
ca97b838
BZ
2569 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2570 bTxRateChanged = TRUE;
96b3c83d 2571 } else {
ca97b838
BZ
2572 bTxRateChanged = FALSE;
2573 }
91980990 2574
96b3c83d 2575 pNextTxRate =
62eb734b 2576 (struct rt_rtmp_tx_rate_switch *) &
96b3c83d
BZ
2577 pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5];
2578 if (bTxRateChanged && pNextTxRate) {
ca97b838
BZ
2579 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2580 }
2581 }
2582}
2583
2584/*
2585 ==========================================================================
2586 Description:
2587 This routine is executed periodically inside MlmePeriodicExec() after
2588 association with an AP.
2589 It checks if StaCfg.Psm is consistent with user policy (recorded in
2590 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2591 there're some conditions to consider:
2592 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2593 the time when Mibss==TRUE
2594 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2595 if outgoing traffic available in TxRing or MgmtRing.
2596 Output:
2597 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
91980990 2598
ca97b838 2599 IRQL = DISPATCH_LEVEL
91980990 2600
ca97b838
BZ
2601 ==========================================================================
2602 */
62eb734b 2603void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32)
ca97b838 2604{
51126deb 2605 unsigned long PowerMode;
91980990 2606
ec278fa2
BZ
2607 /* condition - */
2608 /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */
2609 /* 2. user wants either MAX_PSP or FAST_PSP */
2610 /* 3. but current psm is not in PWR_SAVE */
2611 /* 4. CNTL state machine is not doing SCANning */
2612 /* 5. no TX SUCCESS event for the past 1-sec period */
96b3c83d 2613 PowerMode = pAd->StaCfg.WindowsPowerMode;
91980990 2614
ca97b838 2615 if (INFRA_ON(pAd) &&
96b3c83d
BZ
2616 (PowerMode != Ndis802_11PowerModeCAM) &&
2617 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
ec278fa2 2618/* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */
96b3c83d
BZ
2619 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
2620 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2621 /*&&
2622 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2623 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2624 ) {
2625 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2626 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
ca97b838 2627 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
96b3c83d
BZ
2628 if (!
2629 (pAd->CommonCfg.bAPSDCapable
2630 && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
2631 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2632 } else {
2633 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
91980990 2634 }
96b3c83d 2635 }
91980990
GKH
2636}
2637
ec278fa2
BZ
2638/* IRQL = PASSIVE_LEVEL */
2639/* IRQL = DISPATCH_LEVEL */
62eb734b 2640void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm)
ca97b838
BZ
2641{
2642 AUTO_RSP_CFG_STRUC csr4;
91980990 2643
ca97b838
BZ
2644 pAd->StaCfg.Psm = psm;
2645 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
96b3c83d 2646 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0;
ca97b838
BZ
2647 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2648
2649 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2650}
2651
2652/*
2653 ==========================================================================
2654 Description:
2655 This routine calculates TxPER, RxPER of the past N-sec period. And
2656 according to the calculation result, ChannelQuality is calculated here
2657 to decide if current AP is still doing the job.
2658
2659 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2660 Output:
2661 StaCfg.ChannelQuality - 0..100
2662
2663 IRQL = DISPATCH_LEVEL
2664
2665 NOTE: This routine decide channle quality based on RX CRC error ratio.
2666 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2667 is performed right before this routine, so that this routine can decide
2668 channel quality based on the most up-to-date information
2669 ==========================================================================
91980990 2670 */
62eb734b
BZ
2671void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd,
2672 struct rt_mac_table_entry *pMacEntry, unsigned long Now32)
91980990 2673{
51126deb
BZ
2674 unsigned long TxOkCnt, TxCnt, TxPER, TxPRR;
2675 unsigned long RxCnt, RxPER;
2676 u8 NorRssi;
2677 char MaxRssi;
62eb734b 2678 struct rt_rssi_sample *pRssiSample = NULL;
51126deb
BZ
2679 u32 OneSecTxNoRetryOkCount = 0;
2680 u32 OneSecTxRetryOkCount = 0;
2681 u32 OneSecTxFailCount = 0;
2682 u32 OneSecRxOkCnt = 0;
2683 u32 OneSecRxFcsErrCnt = 0;
2684 unsigned long ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming */
2685 unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime;
91980990 2686
96b3c83d 2687 if (pAd->OpMode == OPMODE_STA) {
ca97b838 2688 pRssiSample = &pAd->StaCfg.RssiSample;
96b3c83d
BZ
2689 OneSecTxNoRetryOkCount =
2690 pAd->RalinkCounters.OneSecTxNoRetryOkCount;
ca97b838
BZ
2691 OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2692 OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2693 OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2694 OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
91980990
GKH
2695 }
2696
ca97b838 2697 MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
96b3c83d 2698 pRssiSample->LastRssi1, pRssiSample->LastRssi2);
91980990 2699
ec278fa2
BZ
2700 /* */
2701 /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */
2702 /* */
ca97b838
BZ
2703 TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2704 TxCnt = TxOkCnt + OneSecTxFailCount;
96b3c83d 2705 if (TxCnt < 5) {
ca97b838
BZ
2706 TxPER = 0;
2707 TxPRR = 0;
96b3c83d 2708 } else {
ca97b838
BZ
2709 TxPER = (OneSecTxFailCount * 100) / TxCnt;
2710 TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2711 }
91980990 2712
ec278fa2
BZ
2713 /* */
2714 /* calculate RX PER - don't take RxPER into consideration if too few sample */
2715 /* */
ca97b838
BZ
2716 RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2717 if (RxCnt < 5)
2718 RxPER = 0;
2719 else
2720 RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
91980990 2721
ec278fa2
BZ
2722 /* */
2723 /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */
2724 /* */
2725 if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) && /* no heavy traffic */
96b3c83d
BZ
2726 ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) {
2727 DBGPRINT(RT_DEBUG_TRACE,
2728 ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2729 BeaconLostTime, TxOkCnt));
ca97b838 2730 ChannelQuality = 0;
96b3c83d 2731 } else {
ec278fa2 2732 /* Normalize Rssi */
ca97b838
BZ
2733 if (MaxRssi > -40)
2734 NorRssi = 100;
2735 else if (MaxRssi < -90)
2736 NorRssi = 0;
2737 else
2738 NorRssi = (MaxRssi + 90) * 2;
91980990 2739
ec278fa2 2740 /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */
ca97b838 2741 ChannelQuality = (RSSI_WEIGHTING * NorRssi +
96b3c83d
BZ
2742 TX_WEIGHTING * (100 - TxPRR) +
2743 RX_WEIGHTING * (100 - RxPER)) / 100;
ca97b838 2744 }
6a28a69a 2745
ca97b838 2746 if (pAd->OpMode == OPMODE_STA)
96b3c83d
BZ
2747 pAd->Mlme.ChannelQuality =
2748 (ChannelQuality > 100) ? 100 : ChannelQuality;
91980990 2749
ca97b838 2750}
91980990 2751
ec278fa2 2752/* IRQL = DISPATCH_LEVEL */
62eb734b 2753void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble)
91980990 2754{
ca97b838 2755 AUTO_RSP_CFG_STRUC csr4;
91980990 2756
ec278fa2
BZ
2757 /* */
2758 /* Always use Long preamble before verifiation short preamble functionality works well. */
2759 /* Todo: remove the following line if short preamble functionality works */
2760 /* */
2761 /*TxPreamble = Rt802_11PreambleLong; */
ca97b838
BZ
2762
2763 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
96b3c83d
BZ
2764 if (TxPreamble == Rt802_11PreambleLong) {
2765 DBGPRINT(RT_DEBUG_TRACE,
51126deb 2766 ("MlmeSetTxPreamble (= long PREAMBLE)\n"));
ca97b838
BZ
2767 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2768 csr4.field.AutoResponderPreamble = 0;
96b3c83d 2769 } else {
ec278fa2 2770 /* NOTE: 1Mbps should always use long preamble */
96b3c83d 2771 DBGPRINT(RT_DEBUG_TRACE,
51126deb 2772 ("MlmeSetTxPreamble (= short PREAMBLE)\n"));
ca97b838
BZ
2773 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2774 csr4.field.AutoResponderPreamble = 1;
2775 }
2776
2777 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2778}
2779
2780/*
2781 ==========================================================================
2782 Description:
2783 Update basic rate bitmap
2784 ==========================================================================
2785 */
2786
62eb734b 2787void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter)
ca97b838 2788{
51126deb 2789 int i, j;
96b3c83d 2790 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
51126deb
BZ
2791 u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2792 u8 *sup_p = pAdapter->CommonCfg.SupRate;
2793 u8 *ext_p = pAdapter->CommonCfg.ExtRate;
2794 unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap;
96b3c83d
BZ
2795
2796 /* if A mode, always use fix BasicRateBitMap */
ec278fa2 2797 /*if (pAdapter->CommonCfg.Channel == PHY_11A) */
ca97b838 2798 if (pAdapter->CommonCfg.Channel > 14)
96b3c83d
BZ
2799 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2800 /* End of if */
2801
2802 if (pAdapter->CommonCfg.BasicRateBitmap > 4095) {
2803 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2804 return;
2805 }
2806 /* End of if */
2807 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2808 sup_p[i] &= 0x7f;
2809 ext_p[i] &= 0x7f;
2810 } /* End of for */
2811
2812 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2813 if (bitmap & (1 << i)) {
2814 for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2815 if (sup_p[j] == rate[i])
2816 sup_p[j] |= 0x80;
2817 /* End of if */
2818 } /* End of for */
2819
2820 for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2821 if (ext_p[j] == rate[i])
2822 ext_p[j] |= 0x80;
2823 /* End of if */
2824 } /* End of for */
2825 } /* End of if */
2826 } /* End of for */
2827} /* End of UpdateBasicRateBitmap */
91980990 2828
ec278fa2
BZ
2829/* IRQL = PASSIVE_LEVEL */
2830/* IRQL = DISPATCH_LEVEL */
25985edc 2831/* bLinkUp is to identify the initial link speed. */
ec278fa2 2832/* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */
62eb734b 2833void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx)
91980990 2834{
ca97b838 2835 int i, num;
51126deb
BZ
2836 u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2837 u8 MinSupport = RATE_54;
2838 unsigned long BasicRateBitmap = 0;
2839 u8 CurrBasicRate = RATE_1;
2840 u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
96b3c83d
BZ
2841 PHTTRANSMIT_SETTING pHtPhy = NULL;
2842 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2843 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2844 BOOLEAN *auto_rate_cur_p;
51126deb 2845 u8 HtMcs = MCS_AUTO;
91980990 2846
ec278fa2 2847 /* find max desired rate */
ca97b838 2848 UpdateBasicRateBitmap(pAd);
91980990 2849
ca97b838
BZ
2850 num = 0;
2851 auto_rate_cur_p = NULL;
96b3c83d
BZ
2852 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2853 switch (pAd->CommonCfg.DesireRate[i] & 0x7f) {
2854 case 2:
2855 Rate = RATE_1;
2856 num++;
2857 break;
2858 case 4:
2859 Rate = RATE_2;
2860 num++;
2861 break;
2862 case 11:
2863 Rate = RATE_5_5;
2864 num++;
2865 break;
2866 case 22:
2867 Rate = RATE_11;
2868 num++;
2869 break;
2870 case 12:
2871 Rate = RATE_6;
2872 num++;
2873 break;
2874 case 18:
2875 Rate = RATE_9;
2876 num++;
2877 break;
2878 case 24:
2879 Rate = RATE_12;
2880 num++;
2881 break;
2882 case 36:
2883 Rate = RATE_18;
2884 num++;
2885 break;
2886 case 48:
2887 Rate = RATE_24;
2888 num++;
2889 break;
2890 case 72:
2891 Rate = RATE_36;
2892 num++;
2893 break;
2894 case 96:
2895 Rate = RATE_48;
2896 num++;
2897 break;
2898 case 108:
2899 Rate = RATE_54;
2900 num++;
2901 break;
ec278fa2 2902 /*default: Rate = RATE_1; break; */
ca97b838 2903 }
96b3c83d
BZ
2904 if (MaxDesire < Rate)
2905 MaxDesire = Rate;
91980990
GKH
2906 }
2907
ec278fa2
BZ
2908/*=========================================================================== */
2909/*=========================================================================== */
ca97b838 2910 {
96b3c83d
BZ
2911 pHtPhy = &pAd->StaCfg.HTPhyMode;
2912 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2913 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
91980990 2914
ca97b838 2915 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
96b3c83d 2916 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
91980990 2917
ca97b838 2918 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
96b3c83d
BZ
2919 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2920 (MaxDesire > RATE_11)) {
ca97b838
BZ
2921 MaxDesire = RATE_11;
2922 }
2923 }
91980990 2924
ca97b838
BZ
2925 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2926 pMinHtPhy->word = 0;
2927 pMaxHtPhy->word = 0;
2928 pHtPhy->word = 0;
91980990 2929
ec278fa2
BZ
2930 /* Auto rate switching is enabled only if more than one DESIRED RATES are */
2931 /* specified; otherwise disabled */
96b3c83d 2932 if (num <= 1) {
ec278fa2
BZ
2933 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2934 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
ca97b838 2935 *auto_rate_cur_p = FALSE;
96b3c83d 2936 } else {
ec278fa2
BZ
2937 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2938 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
ca97b838 2939 *auto_rate_cur_p = TRUE;
91980990
GKH
2940 }
2941
96b3c83d 2942 if (HtMcs != MCS_AUTO) {
ec278fa2
BZ
2943 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2944 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
ca97b838 2945 *auto_rate_cur_p = FALSE;
96b3c83d 2946 } else {
ec278fa2
BZ
2947 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2948 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
ca97b838 2949 *auto_rate_cur_p = TRUE;
91980990
GKH
2950 }
2951
96b3c83d 2952 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
ca97b838
BZ
2953 pSupRate = &pAd->StaActive.SupRate[0];
2954 pExtRate = &pAd->StaActive.ExtRate[0];
2955 SupRateLen = pAd->StaActive.SupRateLen;
2956 ExtRateLen = pAd->StaActive.ExtRateLen;
96b3c83d 2957 } else {
ca97b838
BZ
2958 pSupRate = &pAd->CommonCfg.SupRate[0];
2959 pExtRate = &pAd->CommonCfg.ExtRate[0];
2960 SupRateLen = pAd->CommonCfg.SupRateLen;
2961 ExtRateLen = pAd->CommonCfg.ExtRateLen;
91980990
GKH
2962 }
2963
ec278fa2 2964 /* find max supported rate */
96b3c83d
BZ
2965 for (i = 0; i < SupRateLen; i++) {
2966 switch (pSupRate[i] & 0x7f) {
2967 case 2:
2968 Rate = RATE_1;
2969 if (pSupRate[i] & 0x80)
2970 BasicRateBitmap |= 0x0001;
2971 break;
2972 case 4:
2973 Rate = RATE_2;
2974 if (pSupRate[i] & 0x80)
2975 BasicRateBitmap |= 0x0002;
2976 break;
2977 case 11:
2978 Rate = RATE_5_5;
2979 if (pSupRate[i] & 0x80)
2980 BasicRateBitmap |= 0x0004;
2981 break;
2982 case 22:
2983 Rate = RATE_11;
2984 if (pSupRate[i] & 0x80)
2985 BasicRateBitmap |= 0x0008;
2986 break;
2987 case 12:
2988 Rate = RATE_6; /*if (pSupRate[i] & 0x80) */
2989 BasicRateBitmap |= 0x0010;
2990 break;
2991 case 18:
2992 Rate = RATE_9;
2993 if (pSupRate[i] & 0x80)
2994 BasicRateBitmap |= 0x0020;
2995 break;
2996 case 24:
2997 Rate = RATE_12; /*if (pSupRate[i] & 0x80) */
2998 BasicRateBitmap |= 0x0040;
2999 break;
3000 case 36:
3001 Rate = RATE_18;
3002 if (pSupRate[i] & 0x80)
3003 BasicRateBitmap |= 0x0080;
3004 break;
3005 case 48:
3006 Rate = RATE_24; /*if (pSupRate[i] & 0x80) */
3007 BasicRateBitmap |= 0x0100;
3008 break;
3009 case 72:
3010 Rate = RATE_36;
3011 if (pSupRate[i] & 0x80)
3012 BasicRateBitmap |= 0x0200;
3013 break;
3014 case 96:
3015 Rate = RATE_48;
3016 if (pSupRate[i] & 0x80)
3017 BasicRateBitmap |= 0x0400;
3018 break;
3019 case 108:
3020 Rate = RATE_54;
3021 if (pSupRate[i] & 0x80)
3022 BasicRateBitmap |= 0x0800;
3023 break;
3024 default:
3025 Rate = RATE_1;
3026 break;
3027 }
3028 if (MaxSupport < Rate)
3029 MaxSupport = Rate;
3030
3031 if (MinSupport > Rate)
3032 MinSupport = Rate;
3033 }
3034
3035 for (i = 0; i < ExtRateLen; i++) {
3036 switch (pExtRate[i] & 0x7f) {
3037 case 2:
3038 Rate = RATE_1;
3039 if (pExtRate[i] & 0x80)
3040 BasicRateBitmap |= 0x0001;
3041 break;
3042 case 4:
3043 Rate = RATE_2;
3044 if (pExtRate[i] & 0x80)
3045 BasicRateBitmap |= 0x0002;
3046 break;
3047 case 11:
3048 Rate = RATE_5_5;
3049 if (pExtRate[i] & 0x80)
3050 BasicRateBitmap |= 0x0004;
3051 break;
3052 case 22:
3053 Rate = RATE_11;
3054 if (pExtRate[i] & 0x80)
3055 BasicRateBitmap |= 0x0008;
3056 break;
3057 case 12:
3058 Rate = RATE_6; /*if (pExtRate[i] & 0x80) */
3059 BasicRateBitmap |= 0x0010;
3060 break;
3061 case 18:
3062 Rate = RATE_9;
3063 if (pExtRate[i] & 0x80)
3064 BasicRateBitmap |= 0x0020;
3065 break;
3066 case 24:
3067 Rate = RATE_12; /*if (pExtRate[i] & 0x80) */
3068 BasicRateBitmap |= 0x0040;
3069 break;
3070 case 36:
3071 Rate = RATE_18;
3072 if (pExtRate[i] & 0x80)
3073 BasicRateBitmap |= 0x0080;
3074 break;
3075 case 48:
3076 Rate = RATE_24; /*if (pExtRate[i] & 0x80) */
3077 BasicRateBitmap |= 0x0100;
3078 break;
3079 case 72:
3080 Rate = RATE_36;
3081 if (pExtRate[i] & 0x80)
3082 BasicRateBitmap |= 0x0200;
3083 break;
3084 case 96:
3085 Rate = RATE_48;
3086 if (pExtRate[i] & 0x80)
3087 BasicRateBitmap |= 0x0400;
3088 break;
3089 case 108:
3090 Rate = RATE_54;
3091 if (pExtRate[i] & 0x80)
3092 BasicRateBitmap |= 0x0800;
3093 break;
3094 default:
3095 Rate = RATE_1;
3096 break;
3097 }
3098 if (MaxSupport < Rate)
3099 MaxSupport = Rate;
3100
3101 if (MinSupport > Rate)
3102 MinSupport = Rate;
3103 }
3104
3105 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
91980990 3106
ec278fa2
BZ
3107 /* bug fix */
3108 /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */
ca97b838 3109
ec278fa2
BZ
3110 /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */
3111 /* the DURATION field of outgoing uniicast DATA/MGMT frame */
96b3c83d 3112 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
ca97b838 3113 if (BasicRateBitmap & (0x01 << i))
51126deb 3114 CurrBasicRate = (u8)i;
ca97b838 3115 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
91980990
GKH
3116 }
3117
96b3c83d
BZ
3118 DBGPRINT(RT_DEBUG_TRACE,
3119 ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3120 RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
ec278fa2 3121 /* max tx rate = min {max desire rate, max supported rate} */
ca97b838
BZ
3122 if (MaxSupport < MaxDesire)
3123 pAd->CommonCfg.MaxTxRate = MaxSupport;
3124 else
3125 pAd->CommonCfg.MaxTxRate = MaxDesire;
91980990 3126
ca97b838 3127 pAd->CommonCfg.MinTxRate = MinSupport;
ec278fa2
BZ
3128 /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */
3129 /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */
3130 /* on average RSSI */
3131 /* 1. RSSI >= -70db, start at 54 Mbps (short distance) */
3132 /* 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */
3133 /* 3. -75 > RSSI, start at 11 Mbps (long distance) */
96b3c83d 3134 if (*auto_rate_cur_p) {
ca97b838 3135 short dbm = 0;
91980990 3136
ca97b838 3137 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
91980990 3138
ca97b838
BZ
3139 if (bLinkUp == TRUE)
3140 pAd->CommonCfg.TxRate = RATE_24;
3141 else
3142 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
91980990 3143
ca97b838
BZ
3144 if (dbm < -75)
3145 pAd->CommonCfg.TxRate = RATE_11;
3146 else if (dbm < -70)
3147 pAd->CommonCfg.TxRate = RATE_24;
91980990 3148
ec278fa2 3149 /* should never exceed MaxTxRate (consider 11B-only mode) */
ca97b838
BZ
3150 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3151 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
91980990 3152
ca97b838 3153 pAd->CommonCfg.TxRateIndex = 0;
96b3c83d 3154 } else {
ca97b838 3155 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
96b3c83d
BZ
3156 pHtPhy->field.MCS =
3157 (pAd->CommonCfg.MaxTxRate >
3158 3) ? (pAd->CommonCfg.MaxTxRate -
3159 4) : pAd->CommonCfg.MaxTxRate;
3160 pHtPhy->field.MODE =
3161 (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3162
3163 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC =
3164 pHtPhy->field.STBC;
3165 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI =
3166 pHtPhy->field.ShortGI;
3167 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS =
3168 pHtPhy->field.MCS;
3169 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE =
3170 pHtPhy->field.MODE;
3171 }
3172
3173 if (pAd->CommonCfg.TxRate <= RATE_11) {
ca97b838
BZ
3174 pMaxHtPhy->field.MODE = MODE_CCK;
3175 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3176 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
96b3c83d 3177 } else {
ca97b838
BZ
3178 pMaxHtPhy->field.MODE = MODE_OFDM;
3179 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
96b3c83d
BZ
3180 if (pAd->CommonCfg.MinTxRate >= RATE_6
3181 && (pAd->CommonCfg.MinTxRate <= RATE_54)) {
3182 pMinHtPhy->field.MCS =
3183 OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
3184 } else {
3185 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3186 }
91980990 3187 }
91980990 3188
ca97b838 3189 pHtPhy->word = (pMaxHtPhy->word);
96b3c83d
BZ
3190 if (bLinkUp && (pAd->OpMode == OPMODE_STA)) {
3191 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3192 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word =
3193 pMaxHtPhy->word;
3194 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word =
3195 pMinHtPhy->word;
3196 } else {
3197 switch (pAd->CommonCfg.PhyMode) {
3198 case PHY_11BG_MIXED:
3199 case PHY_11B:
3200 case PHY_11BGN_MIXED:
3201 pAd->CommonCfg.MlmeRate = RATE_1;
3202 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3203 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
91980990 3204
ec278fa2 3205/*#ifdef WIFI_TEST */
96b3c83d 3206 pAd->CommonCfg.RtsRate = RATE_11;
ec278fa2
BZ
3207/*#else */
3208/* pAd->CommonCfg.RtsRate = RATE_1; */
3209/*#endif */
96b3c83d
BZ
3210 break;
3211 case PHY_11G:
3212 case PHY_11A:
3213 case PHY_11AGN_MIXED:
3214 case PHY_11GN_MIXED:
3215 case PHY_11N_2_4G:
3216 case PHY_11AN_MIXED:
3217 case PHY_11N_5G:
3218 pAd->CommonCfg.MlmeRate = RATE_6;
3219 pAd->CommonCfg.RtsRate = RATE_6;
3220 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3221 pAd->CommonCfg.MlmeTransmit.field.MCS =
3222 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3223 break;
3224 case PHY_11ABG_MIXED:
3225 case PHY_11ABGN_MIXED:
3226 if (pAd->CommonCfg.Channel <= 14) {
3227 pAd->CommonCfg.MlmeRate = RATE_1;
3228 pAd->CommonCfg.RtsRate = RATE_1;
3229 pAd->CommonCfg.MlmeTransmit.field.MODE =
3230 MODE_CCK;
3231 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3232 } else {
ca97b838
BZ
3233 pAd->CommonCfg.MlmeRate = RATE_6;
3234 pAd->CommonCfg.RtsRate = RATE_6;
96b3c83d
BZ
3235 pAd->CommonCfg.MlmeTransmit.field.MODE =
3236 MODE_OFDM;
3237 pAd->CommonCfg.MlmeTransmit.field.MCS =
3238 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3239 }
3240 break;
ec278fa2 3241 default: /* error */
96b3c83d
BZ
3242 pAd->CommonCfg.MlmeRate = RATE_6;
3243 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3244 pAd->CommonCfg.MlmeTransmit.field.MCS =
3245 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3246 pAd->CommonCfg.RtsRate = RATE_1;
3247 break;
ca97b838 3248 }
ec278fa2
BZ
3249 /* */
3250 /* Keep Basic Mlme Rate. */
3251 /* */
96b3c83d
BZ
3252 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word =
3253 pAd->CommonCfg.MlmeTransmit.word;
ca97b838 3254 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
96b3c83d
BZ
3255 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3256 OfdmRateToRxwiMCS[RATE_24];
ca97b838 3257 else
96b3c83d
BZ
3258 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3259 RATE_1;
ca97b838 3260 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
91980990 3261 }
91980990 3262
96b3c83d
BZ
3263 DBGPRINT(RT_DEBUG_TRACE,
3264 (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3265 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
3266 RateIdToMbps[pAd->CommonCfg.MaxTxRate],
3267 RateIdToMbps[pAd->CommonCfg.MinTxRate],
3268 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3269 *auto_rate_cur_p));
3270 DBGPRINT(RT_DEBUG_TRACE,
3271 (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3272 RateIdToMbps[pAd->CommonCfg.TxRate],
3273 RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3274 DBGPRINT(RT_DEBUG_TRACE,
3275 ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3276 pAd->CommonCfg.MlmeTransmit.word,
3277 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
3278 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
3279 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word));
91980990
GKH
3280}
3281
ca97b838
BZ
3282/*
3283 ==========================================================================
3284 Description:
3285 This function update HT Rate setting.
3286 Input Wcid value is valid for 2 case :
3287 1. it's used for Station in infra mode that copy AP rate to Mactable.
3288 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
91980990
GKH
3289
3290 IRQL = DISPATCH_LEVEL
3291
ca97b838 3292 ==========================================================================
91980990 3293 */
62eb734b 3294void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx)
91980990 3295{
51126deb
BZ
3296 u8 StbcMcs; /*j, StbcMcs, bitmask; */
3297 char i; /* 3*3 */
62eb734b
BZ
3298 struct rt_ht_capability *pRtHtCap = NULL;
3299 struct rt_ht_phy_info *pActiveHtPhy = NULL;
51126deb
BZ
3300 unsigned long BasicMCS;
3301 u8 j, bitmask;
62eb734b 3302 struct rt_ht_phy_info *pDesireHtPhy = NULL;
96b3c83d
BZ
3303 PHTTRANSMIT_SETTING pHtPhy = NULL;
3304 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3305 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3306 BOOLEAN *auto_rate_cur_p;
91980990 3307
96b3c83d 3308 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n"));
91980990 3309
ca97b838 3310 auto_rate_cur_p = NULL;
91980990 3311
ca97b838 3312 {
96b3c83d
BZ
3313 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3314 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3315 pHtPhy = &pAd->StaCfg.HTPhyMode;
3316 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3317 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
91980990 3318
ca97b838
BZ
3319 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3320 }
91980990 3321
96b3c83d 3322 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
ca97b838
BZ
3323 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3324 return;
91980990 3325
ca97b838
BZ
3326 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3327 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
51126deb 3328 StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
96b3c83d
BZ
3329 BasicMCS =
3330 pAd->MlmeAux.AddHtInfo.MCSSet[0] +
3331 (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3332 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3333 && (pAd->Antenna.field.TxPath == 2))
ca97b838
BZ
3334 pMaxHtPhy->field.STBC = STBC_USE;
3335 else
3336 pMaxHtPhy->field.STBC = STBC_NONE;
96b3c83d 3337 } else {
ca97b838
BZ
3338 if (pDesireHtPhy->bHtEnable == FALSE)
3339 return;
91980990 3340
ca97b838 3341 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
51126deb 3342 StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
96b3c83d
BZ
3343 BasicMCS =
3344 pAd->CommonCfg.AddHTInfo.MCSSet[0] +
3345 (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3346 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3347 && (pAd->Antenna.field.TxPath == 2))
ca97b838
BZ
3348 pMaxHtPhy->field.STBC = STBC_USE;
3349 else
3350 pMaxHtPhy->field.STBC = STBC_NONE;
3351 }
91980990 3352
ec278fa2 3353 /* Decide MAX ht rate. */
ca97b838
BZ
3354 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3355 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3356 else
3357 pMaxHtPhy->field.MODE = MODE_HTMIX;
91980990 3358
96b3c83d
BZ
3359 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth)
3360 && (pRtHtCap->ChannelWidth))
ca97b838
BZ
3361 pMaxHtPhy->field.BW = BW_40;
3362 else
3363 pMaxHtPhy->field.BW = BW_20;
91980990 3364
96b3c83d
BZ
3365 if (pMaxHtPhy->field.BW == BW_20)
3366 pMaxHtPhy->field.ShortGI =
3367 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->
3368 ShortGIfor20);
ca97b838 3369 else
96b3c83d
BZ
3370 pMaxHtPhy->field.ShortGI =
3371 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->
3372 ShortGIfor40);
91980990 3373
96b3c83d 3374 if (pDesireHtPhy->MCSSet[4] != 0) {
ca97b838
BZ
3375 pMaxHtPhy->field.MCS = 32;
3376 }
91980990 3377
ec278fa2 3378 for (i = 23; i >= 0; i--) /* 3*3 */
ca97b838 3379 {
96b3c83d
BZ
3380 j = i / 8;
3381 bitmask = (1 << (i - (j * 8)));
91980990 3382
96b3c83d
BZ
3383 if ((pActiveHtPhy->MCSSet[j] & bitmask)
3384 && (pDesireHtPhy->MCSSet[j] & bitmask)) {
ca97b838
BZ
3385 pMaxHtPhy->field.MCS = i;
3386 break;
96b3c83d 3387 }
91980990 3388
96b3c83d 3389 if (i == 0)
ca97b838
BZ
3390 break;
3391 }
91980990 3392
ec278fa2 3393 /* Copy MIN ht rate. rt2860??? */
ca97b838
BZ
3394 pMinHtPhy->field.BW = BW_20;
3395 pMinHtPhy->field.MCS = 0;
3396 pMinHtPhy->field.STBC = 0;
3397 pMinHtPhy->field.ShortGI = 0;
ec278fa2 3398 /*If STA assigns fixed rate. update to fixed here. */
96b3c83d
BZ
3399 if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) {
3400 if (pDesireHtPhy->MCSSet[4] != 0) {
ca97b838
BZ
3401 pMaxHtPhy->field.MCS = 32;
3402 pMinHtPhy->field.MCS = 32;
96b3c83d
BZ
3403 DBGPRINT(RT_DEBUG_TRACE,
3404 ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3405 pMinHtPhy->field.MCS));
3406 }
ca97b838 3407
51126deb 3408 for (i = 23; (char)i >= 0; i--) /* 3*3 */
91980990 3409 {
96b3c83d
BZ
3410 j = i / 8;
3411 bitmask = (1 << (i - (j * 8)));
3412 if ((pDesireHtPhy->MCSSet[j] & bitmask)
3413 && (pActiveHtPhy->MCSSet[j] & bitmask)) {
ca97b838
BZ
3414 pMaxHtPhy->field.MCS = i;
3415 pMinHtPhy->field.MCS = i;
3416 break;
96b3c83d
BZ
3417 }
3418 if (i == 0)
ca97b838 3419 break;
96b3c83d 3420 }
ca97b838 3421 }
ca97b838 3422
ec278fa2 3423 /* Decide ht rate */
ca97b838
BZ
3424 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3425 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3426 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3427 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3428 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3429
ec278fa2 3430 /* use default now. rt2860 */
ca97b838
BZ
3431 if (pDesireHtPhy->MCSSet[0] != 0xff)
3432 *auto_rate_cur_p = FALSE;
3433 else
3434 *auto_rate_cur_p = TRUE;
3435
96b3c83d
BZ
3436 DBGPRINT(RT_DEBUG_TRACE,
3437 (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n",
3438 pAd->CommonCfg.DesiredHtPhy.AmsduSize));
3439 DBGPRINT(RT_DEBUG_TRACE,
3440 ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n",
3441 pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW,
3442 pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3443 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n"));
ca97b838
BZ
3444}
3445
62eb734b 3446void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab)
ca97b838
BZ
3447{
3448 int i;
3449
3450 Tab->numAsOriginator = 0;
3451 Tab->numAsRecipient = 0;
3452 Tab->numDoneOriginator = 0;
3453 NdisAllocateSpinLock(&pAd->BATabLock);
96b3c83d 3454 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
ca97b838
BZ
3455 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3456 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3457 }
96b3c83d 3458 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
ca97b838 3459 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
91980990 3460 }
ca97b838 3461}
91980990 3462
ec278fa2 3463/* IRQL = DISPATCH_LEVEL */
62eb734b 3464void MlmeRadioOff(struct rt_rtmp_adapter *pAd)
ca97b838
BZ
3465{
3466 RTMP_MLME_RADIO_OFF(pAd);
3467}
3468
ec278fa2 3469/* IRQL = DISPATCH_LEVEL */
62eb734b 3470void MlmeRadioOn(struct rt_rtmp_adapter *pAd)
ca97b838
BZ
3471{
3472 RTMP_MLME_RADIO_ON(pAd);
91980990 3473}
91980990 3474
ec278fa2
BZ
3475/* =========================================================================================== */
3476/* bss_table.c */
3477/* =========================================================================================== */
91980990 3478
ca97b838
BZ
3479/*! \brief initialize BSS table
3480 * \param p_tab pointer to the table
3481 * \return none
3482 * \pre
91980990
GKH
3483 * \post
3484
3485 IRQL = PASSIVE_LEVEL
ca97b838 3486 IRQL = DISPATCH_LEVEL
91980990
GKH
3487
3488 */
62eb734b 3489void BssTableInit(struct rt_bss_table *Tab)
91980990 3490{
ca97b838 3491 int i;
91980990 3492
ca97b838 3493 Tab->BssNr = 0;
96b3c83d
BZ
3494 Tab->BssOverlapNr = 0;
3495 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) {
62eb734b 3496 NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry));
ec278fa2 3497 Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */
ca97b838
BZ
3498 }
3499}
91980990 3500
ca97b838
BZ
3501/*! \brief search the BSS table by SSID
3502 * \param p_tab pointer to the bss table
3503 * \param ssid SSID string
3504 * \return index of the table, BSS_NOT_FOUND if not in the table
3505 * \pre
3506 * \post
3507 * \note search by sequential search
3508
3509 IRQL = DISPATCH_LEVEL
3510
3511 */
62eb734b 3512unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel)
ca97b838 3513{
51126deb 3514 u8 i;
ca97b838 3515
96b3c83d 3516 for (i = 0; i < Tab->BssNr; i++) {
ec278fa2
BZ
3517 /* */
3518 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3519 /* We should distinguish this case. */
3520 /* */
ca97b838 3521 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
96b3c83d
BZ
3522 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3523 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) {
ca97b838 3524 return i;
91980990
GKH
3525 }
3526 }
51126deb 3527 return (unsigned long)BSS_NOT_FOUND;
91980990
GKH
3528}
3529
62eb734b 3530unsigned long BssSsidTableSearch(struct rt_bss_table *Tab,
51126deb
BZ
3531 u8 *pBssid,
3532 u8 *pSsid, u8 SsidLen, u8 Channel)
ca97b838 3533{
51126deb 3534 u8 i;
91980990 3535
96b3c83d 3536 for (i = 0; i < Tab->BssNr; i++) {
ec278fa2
BZ
3537 /* */
3538 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3539 /* We should distinguish this case. */
3540 /* */
ca97b838 3541 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
96b3c83d
BZ
3542 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3543 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3544 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3545 Tab->BssEntry[i].SsidLen)) {
ca97b838
BZ
3546 return i;
3547 }
3548 }
51126deb 3549 return (unsigned long)BSS_NOT_FOUND;
ca97b838 3550}
91980990 3551
62eb734b 3552unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab,
51126deb
BZ
3553 u8 *Bssid,
3554 u8 *pSsid,
3555 u8 SsidLen, u8 Channel)
91980990 3556{
51126deb 3557 u8 i;
91980990 3558
96b3c83d 3559 for (i = 0; i < Tab->BssNr; i++) {
ca97b838 3560 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
96b3c83d
BZ
3561 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3562 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3563 (SSID_EQUAL
3564 (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3565 Tab->BssEntry[i].SsidLen)
3566 || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen))
3567 ||
3568 (NdisEqualMemory
3569 (Tab->BssEntry[i].Ssid, ZeroSsid,
3570 Tab->BssEntry[i].SsidLen)))) {
ca97b838
BZ
3571 return i;
3572 }
91980990 3573 }
51126deb 3574 return (unsigned long)BSS_NOT_FOUND;
91980990
GKH
3575}
3576
62eb734b 3577unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab,
51126deb 3578 u8 *pSsid, u8 SsidLen)
ca97b838 3579{
51126deb 3580 u8 i;
91980990 3581
96b3c83d
BZ
3582 for (i = 0; i < Tab->BssNr; i++) {
3583 if (SSID_EQUAL
3584 (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3585 Tab->BssEntry[i].SsidLen)) {
ca97b838 3586 return i;
96b3c83d 3587 }
ca97b838 3588 }
51126deb 3589 return (unsigned long)BSS_NOT_FOUND;
ca97b838
BZ
3590}
3591
ec278fa2 3592/* IRQL = DISPATCH_LEVEL */
62eb734b 3593void BssTableDeleteEntry(struct rt_bss_table *Tab,
51126deb 3594 u8 *pBssid, u8 Channel)
91980990 3595{
51126deb 3596 u8 i, j;
ca97b838 3597
96b3c83d 3598 for (i = 0; i < Tab->BssNr; i++) {
ca97b838 3599 if ((Tab->BssEntry[i].Channel == Channel) &&
96b3c83d
BZ
3600 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) {
3601 for (j = i; j < Tab->BssNr - 1; j++) {
3602 NdisMoveMemory(&(Tab->BssEntry[j]),
3603 &(Tab->BssEntry[j + 1]),
62eb734b 3604 sizeof(struct rt_bss_entry));
ca97b838 3605 }
96b3c83d 3606 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]),
62eb734b 3607 sizeof(struct rt_bss_entry));
ca97b838
BZ
3608 Tab->BssNr -= 1;
3609 return;
3610 }
3611 }
91980990
GKH
3612}
3613
3614/*
ca97b838
BZ
3615 ========================================================================
3616 Routine Description:
3617 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3618
3619 Arguments:
3620 // IRQL = DISPATCH_LEVEL
3621 ========================================================================
3622*/
62eb734b
BZ
3623void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd,
3624 struct rt_ba_ori_entry *pBAORIEntry)
91980990 3625{
91980990 3626
96b3c83d 3627 if (pBAORIEntry->ORI_BA_Status != Originator_NONE) {
ca97b838 3628 NdisAcquireSpinLock(&pAd->BATabLock);
96b3c83d 3629 if (pBAORIEntry->ORI_BA_Status == Originator_Done) {
ca97b838 3630 pAd->BATable.numAsOriginator -= 1;
96b3c83d
BZ
3631 DBGPRINT(RT_DEBUG_TRACE,
3632 ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3633 pAd->BATable.numAsRecipient));
ec278fa2 3634 /* Erase Bitmap flag. */
ca97b838 3635 }
ec278fa2
BZ
3636 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID))); /* If STA mode, erase flag here */
3637 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; /* If STA mode, erase flag here */
ca97b838
BZ
3638 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3639 pBAORIEntry->Token = 1;
ec278fa2 3640 /* Not clear Sequence here. */
ca97b838
BZ
3641 NdisReleaseSpinLock(&pAd->BATabLock);
3642 }
3643}
91980990 3644
ca97b838
BZ
3645/*! \brief
3646 * \param
3647 * \return
3648 * \pre
3649 * \post
91980990 3650
ca97b838 3651 IRQL = DISPATCH_LEVEL
91980990 3652
91980990 3653 */
62eb734b 3654void 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 */
51126deb
BZ
3655 u8 HtCapabilityLen,
3656 u8 AddHtInfoLen,
3657 u8 NewExtChanOffset,
3658 u8 Channel,
3659 char Rssi,
96b3c83d 3660 IN LARGE_INTEGER TimeStamp,
51126deb 3661 u8 CkipFlag,
62eb734b
BZ
3662 struct rt_edca_parm *pEdcaParm,
3663 struct rt_qos_capability_parm *pQosCapability,
3664 struct rt_qbss_load_parm *pQbssLoad,
3665 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
91980990 3666{
ca97b838 3667 COPY_MAC_ADDR(pBss->Bssid, pBssid);
ec278fa2 3668 /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */
ca97b838 3669 pBss->Hidden = 1;
96b3c83d 3670 if (SsidLen > 0) {
ec278fa2
BZ
3671 /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */
3672 /* Or send beacon /probe response with SSID len matching real SSID length, */
3673 /* but SSID is all zero. such as "00-00-00-00" with length 4. */
3674 /* We have to prevent this case overwrite correct table */
96b3c83d
BZ
3675 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) {
3676 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
ca97b838
BZ
3677 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3678 pBss->SsidLen = SsidLen;
3679 pBss->Hidden = 0;
3680 }
96b3c83d 3681 } else
ca97b838
BZ
3682 pBss->SsidLen = 0;
3683 pBss->BssType = BssType;
3684 pBss->BeaconPeriod = BeaconPeriod;
96b3c83d
BZ
3685 if (BssType == BSS_INFRA) {
3686 if (pCfParm->bValid) {
ca97b838
BZ
3687 pBss->CfpCount = pCfParm->CfpCount;
3688 pBss->CfpPeriod = pCfParm->CfpPeriod;
3689 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3690 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3691 }
96b3c83d 3692 } else {
ca97b838
BZ
3693 pBss->AtimWin = AtimWin;
3694 }
91980990 3695
ca97b838 3696 pBss->CapabilityInfo = CapabilityInfo;
ec278fa2
BZ
3697 /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */
3698 /* Combine with AuthMode, they will decide the connection methods. */
ca97b838
BZ
3699 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3700 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3701 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3702 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3703 else
96b3c83d
BZ
3704 NdisMoveMemory(pBss->SupRate, SupRate,
3705 MAX_LEN_OF_SUPPORTED_RATES);
ca97b838
BZ
3706 pBss->SupRateLen = SupRateLen;
3707 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3708 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3709 pBss->NewExtChanOffset = NewExtChanOffset;
3710 pBss->ExtRateLen = ExtRateLen;
3711 pBss->Channel = Channel;
3712 pBss->CentralChannel = Channel;
3713 pBss->Rssi = Rssi;
ec278fa2 3714 /* Update CkipFlag. if not exists, the value is 0x0 */
ca97b838 3715 pBss->CkipFlag = CkipFlag;
91980990 3716
ec278fa2 3717 /* New for microsoft Fixed IEs */
ca97b838
BZ
3718 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3719 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3720 pBss->FixIEs.Capabilities = CapabilityInfo;
91980990 3721
ec278fa2 3722 /* New for microsoft Variable IEs */
96b3c83d 3723 if (LengthVIE != 0) {
ca97b838
BZ
3724 pBss->VarIELen = LengthVIE;
3725 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
96b3c83d 3726 } else {
ca97b838
BZ
3727 pBss->VarIELen = 0;
3728 }
91980990 3729
ca97b838
BZ
3730 pBss->AddHtInfoLen = 0;
3731 pBss->HtCapabilityLen = 0;
96b3c83d 3732 if (HtCapabilityLen > 0) {
ca97b838 3733 pBss->HtCapabilityLen = HtCapabilityLen;
96b3c83d
BZ
3734 NdisMoveMemory(&pBss->HtCapability, pHtCapability,
3735 HtCapabilityLen);
3736 if (AddHtInfoLen > 0) {
ca97b838 3737 pBss->AddHtInfoLen = AddHtInfoLen;
96b3c83d
BZ
3738 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo,
3739 AddHtInfoLen);
3740
3741 if ((pAddHtInfo->ControlChan > 2)
3742 && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
3743 EXTCHA_BELOW)
3744 && (pHtCapability->HtCapInfo.ChannelWidth ==
3745 BW_40)) {
3746 pBss->CentralChannel =
3747 pAddHtInfo->ControlChan - 2;
3748 } else
3749 if ((pAddHtInfo->AddHtInfo.ExtChanOffset ==
3750 EXTCHA_ABOVE)
3751 && (pHtCapability->HtCapInfo.ChannelWidth ==
3752 BW_40)) {
3753 pBss->CentralChannel =
3754 pAddHtInfo->ControlChan + 2;
3755 }
91980990 3756 }
91980990
GKH
3757 }
3758
ca97b838 3759 BssCipherParse(pBss);
91980990 3760
ec278fa2 3761 /* new for QOS */
ca97b838 3762 if (pEdcaParm)
62eb734b 3763 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm));
ca97b838
BZ
3764 else
3765 pBss->EdcaParm.bValid = FALSE;
3766 if (pQosCapability)
96b3c83d 3767 NdisMoveMemory(&pBss->QosCapability, pQosCapability,
62eb734b 3768 sizeof(struct rt_qos_capability_parm));
ca97b838
BZ
3769 else
3770 pBss->QosCapability.bValid = FALSE;
3771 if (pQbssLoad)
96b3c83d 3772 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad,
62eb734b 3773 sizeof(struct rt_qbss_load_parm));
ca97b838
BZ
3774 else
3775 pBss->QbssLoad.bValid = FALSE;
3776
3777 {
62eb734b 3778 struct rt_eid * pEid;
51126deb 3779 u16 Length = 0;
ca97b838
BZ
3780
3781 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3782 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
62eb734b 3783 pEid = (struct rt_eid *) pVIE;
51126deb 3784 while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) {
96b3c83d
BZ
3785 switch (pEid->Eid) {
3786 case IE_WPA:
3787 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) {
3788 if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3789 pBss->WpaIE.IELen = 0;
3790 break;
91980990 3791 }
96b3c83d
BZ
3792 pBss->WpaIE.IELen = pEid->Len + 2;
3793 NdisMoveMemory(pBss->WpaIE.IE, pEid,
3794 pBss->WpaIE.IELen);
91980990
GKH
3795 }
3796 break;
96b3c83d
BZ
3797 case IE_RSN:
3798 if (NdisEqualMemory
3799 (pEid->Octet + 2, RSN_OUI, 3)) {
3800 if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3801 pBss->RsnIE.IELen = 0;
3802 break;
91980990 3803 }
96b3c83d
BZ
3804 pBss->RsnIE.IELen = pEid->Len + 2;
3805 NdisMoveMemory(pBss->RsnIE.IE, pEid,
3806 pBss->RsnIE.IELen);
91980990
GKH
3807 }
3808 break;
96b3c83d 3809 }
51126deb 3810 Length = Length + 2 + (u16)pEid->Len; /* Eid[1] + Len[1]+ content[Len] */
62eb734b 3811 pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len);
ca97b838 3812 }
91980990 3813 }
91980990
GKH
3814}
3815
ca97b838
BZ
3816/*!
3817 * \brief insert an entry into the bss table
3818 * \param p_tab The BSS table
3819 * \param Bssid BSSID
3820 * \param ssid SSID
3821 * \param ssid_len Length of SSID
3822 * \param bss_type
3823 * \param beacon_period
3824 * \param timestamp
3825 * \param p_cf
3826 * \param atim_win
3827 * \param cap
3828 * \param rates
3829 * \param rates_len
3830 * \param channel_idx
3831 * \return none
3832 * \pre
3833 * \post
3834 * \note If SSID is identical, the old entry will be replaced by the new one
91980990 3835
ca97b838
BZ
3836 IRQL = DISPATCH_LEVEL
3837
3838 */
62eb734b 3839unsigned 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 */
51126deb
BZ
3840 u8 HtCapabilityLen,
3841 u8 AddHtInfoLen,
3842 u8 NewExtChanOffset,
3843 u8 ChannelNo,
3844 char Rssi,
96b3c83d 3845 IN LARGE_INTEGER TimeStamp,
51126deb 3846 u8 CkipFlag,
62eb734b
BZ
3847 struct rt_edca_parm *pEdcaParm,
3848 struct rt_qos_capability_parm *pQosCapability,
3849 struct rt_qbss_load_parm *pQbssLoad,
3850 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
91980990 3851{
51126deb 3852 unsigned long Idx;
91980990 3853
96b3c83d 3854 Idx =
51126deb 3855 BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen,
96b3c83d
BZ
3856 ChannelNo);
3857 if (Idx == BSS_NOT_FOUND) {
3858 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) {
ec278fa2
BZ
3859 /* */
3860 /* It may happen when BSS Table was full. */
3861 /* The desired AP will not be added into BSS Table */
3862 /* In this case, if we found the desired AP then overwrite BSS Table. */
3863 /* */
96b3c83d
BZ
3864 if (!OPSTATUS_TEST_FLAG
3865 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
3866 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid)
3867 || SSID_EQUAL(pAd->MlmeAux.Ssid,
3868 pAd->MlmeAux.SsidLen, Ssid,
3869 SsidLen)) {
ca97b838 3870 Idx = Tab->BssOverlapNr;
96b3c83d
BZ
3871 BssEntrySet(pAd, &Tab->BssEntry[Idx],
3872 pBssid, Ssid, SsidLen,
3873 BssType, BeaconPeriod,
3874 CfParm, AtimWin,
3875 CapabilityInfo, SupRate,
3876 SupRateLen, ExtRate,
3877 ExtRateLen, pHtCapability,
3878 pAddHtInfo, HtCapabilityLen,
3879 AddHtInfoLen,
3880 NewExtChanOffset, ChannelNo,
3881 Rssi, TimeStamp, CkipFlag,
3882 pEdcaParm, pQosCapability,
3883 pQbssLoad, LengthVIE, pVIE);
3884 Tab->BssOverlapNr =
3885 (Tab->BssOverlapNr++) %
3886 MAX_LEN_OF_BSS_TABLE;
91980990 3887 }
ca97b838 3888 return Idx;
96b3c83d
BZ
3889 } else {
3890 return BSS_NOT_FOUND;
3891 }
91980990 3892 }
ca97b838 3893 Idx = Tab->BssNr;
96b3c83d
BZ
3894 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen,
3895 BssType, BeaconPeriod, CfParm, AtimWin,
3896 CapabilityInfo, SupRate, SupRateLen, ExtRate,
3897 ExtRateLen, pHtCapability, pAddHtInfo,
3898 HtCapabilityLen, AddHtInfoLen, NewExtChanOffset,
3899 ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm,
3900 pQosCapability, pQbssLoad, LengthVIE, pVIE);
ca97b838 3901 Tab->BssNr++;
96b3c83d 3902 } else {
ca97b838 3903 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
96b3c83d
BZ
3904 if ((SSID_EQUAL
3905 (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid,
3906 Tab->BssEntry[Idx].SsidLen))
3907 ||
3908 (NdisEqualMemory
3909 (Tab->BssEntry[Idx].Ssid, ZeroSsid,
3910 Tab->BssEntry[Idx].SsidLen))) {
3911 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid,
3912 SsidLen, BssType, BeaconPeriod, CfParm,
3913 AtimWin, CapabilityInfo, SupRate,
3914 SupRateLen, ExtRate, ExtRateLen,
3915 pHtCapability, pAddHtInfo, HtCapabilityLen,
3916 AddHtInfoLen, NewExtChanOffset, ChannelNo,
3917 Rssi, TimeStamp, CkipFlag, pEdcaParm,
3918 pQosCapability, pQbssLoad, LengthVIE, pVIE);
91980990
GKH
3919 }
3920 }
91980990 3921
ca97b838
BZ
3922 return Idx;
3923}
59fe2d89 3924
ec278fa2 3925/* IRQL = DISPATCH_LEVEL */
62eb734b
BZ
3926void BssTableSsidSort(struct rt_rtmp_adapter *pAd,
3927 struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen)
59fe2d89 3928{
51126deb 3929 int i;
ca97b838 3930 BssTableInit(OutTab);
59fe2d89 3931
96b3c83d 3932 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
62eb734b 3933 struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i];
96b3c83d 3934 BOOLEAN bIsHiddenApIncluded = FALSE;
59fe2d89 3935
ca97b838 3936 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
96b3c83d
BZ
3937 (pAd->MlmeAux.Channel > 14) &&
3938 RadarChannelCheck(pAd, pInBss->Channel))
3939 ) {
ca97b838
BZ
3940 if (pInBss->Hidden)
3941 bIsHiddenApIncluded = TRUE;
96b3c83d 3942 }
59fe2d89 3943
ca97b838 3944 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
96b3c83d
BZ
3945 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen)
3946 || bIsHiddenApIncluded)) {
62eb734b 3947 struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
59fe2d89 3948
ec278fa2 3949 /* 2.4G/5G N only mode */
ca97b838 3950 if ((pInBss->HtCapabilityLen == 0) &&
96b3c83d
BZ
3951 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
3952 || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
3953 DBGPRINT(RT_DEBUG_TRACE,
3954 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
ca97b838 3955 continue;
96b3c83d 3956 }
ec278fa2
BZ
3957 /* New for WPA2 */
3958 /* Check the Authmode first */
96b3c83d 3959 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
ec278fa2 3960 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
96b3c83d
BZ
3961 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
3962 && (pAd->StaCfg.AuthMode !=
3963 pInBss->AuthModeAux))
ec278fa2 3964 /* None matched */
ca97b838 3965 continue;
59fe2d89 3966
ec278fa2 3967 /* Check cipher suite, AP must have more secured cipher than station setting */
96b3c83d
BZ
3968 if ((pAd->StaCfg.AuthMode ==
3969 Ndis802_11AuthModeWPA)
3970 || (pAd->StaCfg.AuthMode ==
3971 Ndis802_11AuthModeWPAPSK)) {
ec278fa2 3972 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 3973 if (pInBss->WPA.bMixMode == FALSE)
96b3c83d
BZ
3974 if (pAd->StaCfg.WepStatus !=
3975 pInBss->WPA.GroupCipher)
ca97b838 3976 continue;
91980990 3977
ec278fa2 3978 /* check group cipher */
96b3c83d
BZ
3979 if ((pAd->StaCfg.WepStatus <
3980 pInBss->WPA.GroupCipher)
3981 && (pInBss->WPA.GroupCipher !=
3982 Ndis802_11GroupWEP40Enabled)
3983 && (pInBss->WPA.GroupCipher !=
3984 Ndis802_11GroupWEP104Enabled))
ca97b838 3985 continue;
91980990 3986
ec278fa2
BZ
3987 /* check pairwise cipher, skip if none matched */
3988 /* If profile set to AES, let it pass without question. */
3989 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
3990 if ((pAd->StaCfg.WepStatus ==
3991 Ndis802_11Encryption2Enabled)
3992 && (pAd->StaCfg.WepStatus !=
3993 pInBss->WPA.PairCipher)
3994 && (pAd->StaCfg.WepStatus !=
3995 pInBss->WPA.PairCipherAux))
ca97b838 3996 continue;
96b3c83d
BZ
3997 } else
3998 if ((pAd->StaCfg.AuthMode ==
3999 Ndis802_11AuthModeWPA2)
4000 || (pAd->StaCfg.AuthMode ==
4001 Ndis802_11AuthModeWPA2PSK)) {
ec278fa2 4002 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 4003 if (pInBss->WPA2.bMixMode == FALSE)
96b3c83d
BZ
4004 if (pAd->StaCfg.WepStatus !=
4005 pInBss->WPA2.GroupCipher)
ca97b838
BZ
4006 continue;
4007
ec278fa2 4008 /* check group cipher */
96b3c83d
BZ
4009 if ((pAd->StaCfg.WepStatus <
4010 pInBss->WPA.GroupCipher)
4011 && (pInBss->WPA2.GroupCipher !=
4012 Ndis802_11GroupWEP40Enabled)
4013 && (pInBss->WPA2.GroupCipher !=
4014 Ndis802_11GroupWEP104Enabled))
ca97b838
BZ
4015 continue;
4016
ec278fa2
BZ
4017 /* check pairwise cipher, skip if none matched */
4018 /* If profile set to AES, let it pass without question. */
4019 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
4020 if ((pAd->StaCfg.WepStatus ==
4021 Ndis802_11Encryption2Enabled)
4022 && (pAd->StaCfg.WepStatus !=
4023 pInBss->WPA2.PairCipher)
4024 && (pAd->StaCfg.WepStatus !=
4025 pInBss->WPA2.PairCipherAux))
ca97b838
BZ
4026 continue;
4027 }
4028 }
ec278fa2
BZ
4029 /* Bss Type matched, SSID matched. */
4030 /* We will check wepstatus for qualification Bss */
96b3c83d
BZ
4031 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) {
4032 DBGPRINT(RT_DEBUG_TRACE,
4033 ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4034 pAd->StaCfg.WepStatus,
4035 pInBss->WepStatus));
ec278fa2
BZ
4036 /* */
4037 /* For the SESv2 case, we will not qualify WepStatus. */
4038 /* */
ca97b838
BZ
4039 if (!pInBss->bSES)
4040 continue;
4041 }
ec278fa2
BZ
4042 /* Since the AP is using hidden SSID, and we are trying to connect to ANY */
4043 /* It definitely will fail. So, skip it. */
06aea994 4044 /* CCX also require not even try to connect it! */
ca97b838
BZ
4045 if (SsidLen == 0)
4046 continue;
4047
ec278fa2
BZ
4048 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4049 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
ca97b838 4050 if ((pInBss->CentralChannel != pInBss->Channel) &&
96b3c83d
BZ
4051 (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4052 BW_40)) {
4053 if (RTMPCheckChannel
4054 (pAd, pInBss->CentralChannel,
4055 pInBss->Channel) == FALSE) {
4056 pAd->CommonCfg.RegTransmitSetting.field.
4057 BW = BW_20;
ca97b838 4058 SetCommonHT(pAd);
96b3c83d
BZ
4059 pAd->CommonCfg.RegTransmitSetting.field.
4060 BW = BW_40;
4061 } else {
4062 if (pAd->CommonCfg.DesiredHtPhy.
4063 ChannelWidth == BAND_WIDTH_20) {
ca97b838
BZ
4064 SetCommonHT(pAd);
4065 }
96b3c83d
BZ
4066 }
4067 }
ec278fa2 4068 /* copy matching BSS from InTab to OutTab */
62eb734b 4069 NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
ca97b838
BZ
4070
4071 OutTab->BssNr++;
96b3c83d
BZ
4072 } else if ((pInBss->BssType == pAd->StaCfg.BssType)
4073 && (SsidLen == 0)) {
62eb734b 4074 struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
ca97b838 4075
ec278fa2 4076 /* 2.4G/5G N only mode */
ca97b838 4077 if ((pInBss->HtCapabilityLen == 0) &&
96b3c83d
BZ
4078 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
4079 || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
4080 DBGPRINT(RT_DEBUG_TRACE,
4081 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
ca97b838
BZ
4082 continue;
4083 }
ec278fa2
BZ
4084 /* New for WPA2 */
4085 /* Check the Authmode first */
96b3c83d 4086 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
ec278fa2 4087 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
96b3c83d
BZ
4088 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
4089 && (pAd->StaCfg.AuthMode !=
4090 pInBss->AuthModeAux))
ec278fa2 4091 /* None matched */
ca97b838
BZ
4092 continue;
4093
ec278fa2 4094 /* Check cipher suite, AP must have more secured cipher than station setting */
96b3c83d
BZ
4095 if ((pAd->StaCfg.AuthMode ==
4096 Ndis802_11AuthModeWPA)
4097 || (pAd->StaCfg.AuthMode ==
4098 Ndis802_11AuthModeWPAPSK)) {
ec278fa2 4099 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 4100 if (pInBss->WPA.bMixMode == FALSE)
96b3c83d
BZ
4101 if (pAd->StaCfg.WepStatus !=
4102 pInBss->WPA.GroupCipher)
ca97b838 4103 continue;
91980990 4104
ec278fa2 4105 /* check group cipher */
96b3c83d
BZ
4106 if (pAd->StaCfg.WepStatus <
4107 pInBss->WPA.GroupCipher)
ca97b838 4108 continue;
59fe2d89 4109
ec278fa2
BZ
4110 /* check pairwise cipher, skip if none matched */
4111 /* If profile set to AES, let it pass without question. */
4112 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
4113 if ((pAd->StaCfg.WepStatus ==
4114 Ndis802_11Encryption2Enabled)
4115 && (pAd->StaCfg.WepStatus !=
4116 pInBss->WPA.PairCipher)
4117 && (pAd->StaCfg.WepStatus !=
4118 pInBss->WPA.PairCipherAux))
ca97b838 4119 continue;
96b3c83d
BZ
4120 } else
4121 if ((pAd->StaCfg.AuthMode ==
4122 Ndis802_11AuthModeWPA2)
4123 || (pAd->StaCfg.AuthMode ==
4124 Ndis802_11AuthModeWPA2PSK)) {
ec278fa2 4125 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 4126 if (pInBss->WPA2.bMixMode == FALSE)
96b3c83d
BZ
4127 if (pAd->StaCfg.WepStatus !=
4128 pInBss->WPA2.GroupCipher)
ca97b838
BZ
4129 continue;
4130
ec278fa2 4131 /* check group cipher */
96b3c83d
BZ
4132 if (pAd->StaCfg.WepStatus <
4133 pInBss->WPA2.GroupCipher)
ca97b838
BZ
4134 continue;
4135
ec278fa2
BZ
4136 /* check pairwise cipher, skip if none matched */
4137 /* If profile set to AES, let it pass without question. */
4138 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
4139 if ((pAd->StaCfg.WepStatus ==
4140 Ndis802_11Encryption2Enabled)
4141 && (pAd->StaCfg.WepStatus !=
4142 pInBss->WPA2.PairCipher)
4143 && (pAd->StaCfg.WepStatus !=
4144 pInBss->WPA2.PairCipherAux))
ca97b838 4145 continue;
59fe2d89 4146 }
ca97b838 4147 }
ec278fa2
BZ
4148 /* Bss Type matched, SSID matched. */
4149 /* We will check wepstatus for qualification Bss */
ca97b838 4150 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
96b3c83d 4151 continue;
ca97b838 4152
ec278fa2
BZ
4153 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4154 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
ca97b838 4155 if ((pInBss->CentralChannel != pInBss->Channel) &&
96b3c83d
BZ
4156 (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4157 BW_40)) {
4158 if (RTMPCheckChannel
4159 (pAd, pInBss->CentralChannel,
4160 pInBss->Channel) == FALSE) {
4161 pAd->CommonCfg.RegTransmitSetting.field.
4162 BW = BW_20;
ca97b838 4163 SetCommonHT(pAd);
96b3c83d
BZ
4164 pAd->CommonCfg.RegTransmitSetting.field.
4165 BW = BW_40;
59fe2d89 4166 }
96b3c83d 4167 }
ec278fa2 4168 /* copy matching BSS from InTab to OutTab */
62eb734b 4169 NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
ca97b838
BZ
4170
4171 OutTab->BssNr++;
4172 }
4173
4174 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
96b3c83d
BZ
4175 break;
4176 }
59fe2d89 4177
ca97b838
BZ
4178 BssTableSortByRssi(OutTab);
4179}
91980990 4180
ec278fa2 4181/* IRQL = DISPATCH_LEVEL */
62eb734b 4182void BssTableSortByRssi(struct rt_bss_table *OutTab)
ca97b838 4183{
51126deb 4184 int i, j;
62eb734b 4185 struct rt_bss_entry TmpBss;
ca97b838 4186
96b3c83d
BZ
4187 for (i = 0; i < OutTab->BssNr - 1; i++) {
4188 for (j = i + 1; j < OutTab->BssNr; j++) {
4189 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) {
4190 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j],
62eb734b 4191 sizeof(struct rt_bss_entry));
96b3c83d
BZ
4192 NdisMoveMemory(&OutTab->BssEntry[j],
4193 &OutTab->BssEntry[i],
62eb734b 4194 sizeof(struct rt_bss_entry));
96b3c83d 4195 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss,
62eb734b 4196 sizeof(struct rt_bss_entry));
96b3c83d
BZ
4197 }
4198 }
4199 }
ca97b838 4200}
91980990 4201
62eb734b 4202void BssCipherParse(struct rt_bss_entry *pBss)
ca97b838 4203{
62eb734b 4204 struct rt_eid * pEid;
51126deb 4205 u8 *pTmp;
62eb734b
BZ
4206 struct rt_rsn_ie_header * pRsnHeader;
4207 struct rt_cipher_suite_struct * pCipher;
4208 struct rt_akm_suite * pAKM;
51126deb
BZ
4209 u16 Count;
4210 int Length;
96b3c83d 4211 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
91980990 4212
ec278fa2
BZ
4213 /* */
4214 /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */
4215 /* */
96b3c83d
BZ
4216 if (pBss->Privacy) {
4217 pBss->WepStatus = Ndis802_11WEPEnabled;
4218 } else {
4219 pBss->WepStatus = Ndis802_11WEPDisabled;
4220 }
ec278fa2 4221 /* Set default to disable & open authentication before parsing variable IE */
96b3c83d
BZ
4222 pBss->AuthMode = Ndis802_11AuthModeOpen;
4223 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
91980990 4224
ec278fa2 4225 /* Init WPA setting */
96b3c83d 4226 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
ca97b838 4227 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
96b3c83d 4228 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
ca97b838 4229 pBss->WPA.RsnCapability = 0;
96b3c83d 4230 pBss->WPA.bMixMode = FALSE;
91980990 4231
ec278fa2 4232 /* Init WPA2 setting */
96b3c83d 4233 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
ca97b838 4234 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
96b3c83d 4235 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
ca97b838 4236 pBss->WPA2.RsnCapability = 0;
96b3c83d 4237 pBss->WPA2.bMixMode = FALSE;
91980990 4238
51126deb 4239 Length = (int)pBss->VarIELen;
91980990 4240
96b3c83d 4241 while (Length > 0) {
ec278fa2 4242 /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */
51126deb 4243 pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length;
62eb734b 4244 pEid = (struct rt_eid *) pTmp;
96b3c83d
BZ
4245 switch (pEid->Eid) {
4246 case IE_WPA:
4247 if (NdisEqualMemory(pEid->Octet, SES_OUI, 3)
4248 && (pEid->Len == 7)) {
4249 pBss->bSES = TRUE;
4250 break;
4251 } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) !=
4252 1) {
ec278fa2 4253 /* if unsupported vendor specific IE */
96b3c83d
BZ
4254 break;
4255 }
ec278fa2
BZ
4256 /* Skip OUI, version, and multicast suite */
4257 /* This part should be improved in the future when AP supported multiple cipher suite. */
4258 /* For now, it's OK since almost all APs have fixed cipher suite supported. */
51126deb 4259 /* pTmp = (u8 *)pEid->Octet; */
96b3c83d
BZ
4260 pTmp += 11;
4261
ec278fa2
BZ
4262 /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
4263 /* Value Meaning */
4264 /* 0 None */
4265 /* 1 WEP-40 */
4266 /* 2 Tkip */
4267 /* 3 WRAP */
4268 /* 4 AES */
4269 /* 5 WEP-104 */
4270 /* Parse group cipher */
96b3c83d
BZ
4271 switch (*pTmp) {
4272 case 1:
4273 pBss->WPA.GroupCipher =
4274 Ndis802_11GroupWEP40Enabled;
4275 break;
4276 case 5:
4277 pBss->WPA.GroupCipher =
4278 Ndis802_11GroupWEP104Enabled;
4279 break;
4280 case 2:
4281 pBss->WPA.GroupCipher =
4282 Ndis802_11Encryption2Enabled;
4283 break;
4284 case 4:
4285 pBss->WPA.GroupCipher =
4286 Ndis802_11Encryption3Enabled;
4287 break;
4288 default:
4289 break;
4290 }
ec278fa2 4291 /* number of unicast suite */
96b3c83d
BZ
4292 pTmp += 1;
4293
ec278fa2 4294 /* skip all unicast cipher suites */
51126deb 4295 /*Count = *(u16 *)pTmp; */
96b3c83d 4296 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4297 pTmp += sizeof(u16);
96b3c83d 4298
ec278fa2 4299 /* Parsing all unicast cipher suite */
96b3c83d 4300 while (Count > 0) {
ec278fa2 4301 /* Skip OUI */
96b3c83d
BZ
4302 pTmp += 3;
4303 TmpCipher = Ndis802_11WEPDisabled;
4304 switch (*pTmp) {
4305 case 1:
ec278fa2 4306 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
96b3c83d
BZ
4307 TmpCipher =
4308 Ndis802_11Encryption1Enabled;
ca97b838 4309 break;
96b3c83d
BZ
4310 case 2:
4311 TmpCipher =
4312 Ndis802_11Encryption2Enabled;
4313 break;
4314 case 4:
4315 TmpCipher =
4316 Ndis802_11Encryption3Enabled;
4317 break;
4318 default:
ca97b838 4319 break;
ca97b838 4320 }
96b3c83d 4321 if (TmpCipher > pBss->WPA.PairCipher) {
ec278fa2 4322 /* Move the lower cipher suite to PairCipherAux */
96b3c83d
BZ
4323 pBss->WPA.PairCipherAux =
4324 pBss->WPA.PairCipher;
4325 pBss->WPA.PairCipher = TmpCipher;
4326 } else {
4327 pBss->WPA.PairCipherAux = TmpCipher;
4328 }
4329 pTmp++;
4330 Count--;
4331 }
ca97b838 4332
ec278fa2 4333 /* 4. get AKM suite counts */
51126deb 4334 /*Count = *(u16 *)pTmp; */
96b3c83d 4335 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4336 pTmp += sizeof(u16);
96b3c83d
BZ
4337 pTmp += 3;
4338
4339 switch (*pTmp) {
4340 case 1:
ec278fa2 4341 /* Set AP support WPA-enterprise mode */
96b3c83d
BZ
4342 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4343 pBss->AuthMode = Ndis802_11AuthModeWPA;
4344 else
4345 pBss->AuthModeAux =
4346 Ndis802_11AuthModeWPA;
4347 break;
4348 case 2:
ec278fa2 4349 /* Set AP support WPA-PSK mode */
96b3c83d
BZ
4350 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4351 pBss->AuthMode =
4352 Ndis802_11AuthModeWPAPSK;
4353 else
4354 pBss->AuthModeAux =
4355 Ndis802_11AuthModeWPAPSK;
4356 break;
4357 default:
4358 break;
4359 }
4360 pTmp += 1;
4361
ec278fa2 4362 /* Fixed for WPA-None */
96b3c83d
BZ
4363 if (pBss->BssType == BSS_ADHOC) {
4364 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4365 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4366 pBss->WepStatus = pBss->WPA.GroupCipher;
ec278fa2 4367 /* Patched bugs for old driver */
96b3c83d
BZ
4368 if (pBss->WPA.PairCipherAux ==
4369 Ndis802_11WEPDisabled)
4370 pBss->WPA.PairCipherAux =
4371 pBss->WPA.GroupCipher;
4372 } else
4373 pBss->WepStatus = pBss->WPA.PairCipher;
4374
ec278fa2 4375 /* Check the Pair & Group, if different, turn on mixed mode flag */
96b3c83d
BZ
4376 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4377 pBss->WPA.bMixMode = TRUE;
ca97b838 4378
96b3c83d 4379 break;
91980990 4380
96b3c83d 4381 case IE_RSN:
62eb734b 4382 pRsnHeader = (struct rt_rsn_ie_header *) pTmp;
91980990 4383
ec278fa2 4384 /* 0. Version must be 1 */
96b3c83d 4385 if (le2cpu16(pRsnHeader->Version) != 1)
ca97b838 4386 break;
62eb734b 4387 pTmp += sizeof(struct rt_rsn_ie_header);
91980990 4388
ec278fa2 4389 /* 1. Check group cipher */
62eb734b 4390 pCipher = (struct rt_cipher_suite_struct *) pTmp;
96b3c83d
BZ
4391 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4392 break;
91980990 4393
ec278fa2 4394 /* Parse group cipher */
96b3c83d
BZ
4395 switch (pCipher->Type) {
4396 case 1:
4397 pBss->WPA2.GroupCipher =
4398 Ndis802_11GroupWEP40Enabled;
4399 break;
4400 case 5:
4401 pBss->WPA2.GroupCipher =
4402 Ndis802_11GroupWEP104Enabled;
4403 break;
4404 case 2:
4405 pBss->WPA2.GroupCipher =
4406 Ndis802_11Encryption2Enabled;
4407 break;
4408 case 4:
4409 pBss->WPA2.GroupCipher =
4410 Ndis802_11Encryption3Enabled;
4411 break;
4412 default:
4413 break;
4414 }
ec278fa2 4415 /* set to correct offset for next parsing */
62eb734b 4416 pTmp += sizeof(struct rt_cipher_suite_struct);
96b3c83d 4417
ec278fa2 4418 /* 2. Get pairwise cipher counts */
51126deb 4419 /*Count = *(u16 *)pTmp; */
96b3c83d 4420 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4421 pTmp += sizeof(u16);
96b3c83d 4422
ec278fa2
BZ
4423 /* 3. Get pairwise cipher */
4424 /* Parsing all unicast cipher suite */
96b3c83d 4425 while (Count > 0) {
ec278fa2 4426 /* Skip OUI */
62eb734b 4427 pCipher = (struct rt_cipher_suite_struct *) pTmp;
96b3c83d
BZ
4428 TmpCipher = Ndis802_11WEPDisabled;
4429 switch (pCipher->Type) {
4430 case 1:
ec278fa2 4431 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
96b3c83d
BZ
4432 TmpCipher =
4433 Ndis802_11Encryption1Enabled;
4434 break;
4435 case 2:
4436 TmpCipher =
4437 Ndis802_11Encryption2Enabled;
4438 break;
4439 case 4:
4440 TmpCipher =
4441 Ndis802_11Encryption3Enabled;
4442 break;
4443 default:
4444 break;
91980990 4445 }
96b3c83d 4446 if (TmpCipher > pBss->WPA2.PairCipher) {
ec278fa2 4447 /* Move the lower cipher suite to PairCipherAux */
96b3c83d
BZ
4448 pBss->WPA2.PairCipherAux =
4449 pBss->WPA2.PairCipher;
4450 pBss->WPA2.PairCipher = TmpCipher;
4451 } else {
4452 pBss->WPA2.PairCipherAux = TmpCipher;
4453 }
62eb734b 4454 pTmp += sizeof(struct rt_cipher_suite_struct);
96b3c83d
BZ
4455 Count--;
4456 }
91980990 4457
ec278fa2 4458 /* 4. get AKM suite counts */
51126deb 4459 /*Count = *(u16 *)pTmp; */
96b3c83d 4460 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4461 pTmp += sizeof(u16);
91980990 4462
ec278fa2
BZ
4463 /* 5. Get AKM ciphers */
4464 /* Parsing all AKM ciphers */
96b3c83d 4465 while (Count > 0) {
62eb734b 4466 pAKM = (struct rt_akm_suite *) pTmp;
96b3c83d
BZ
4467 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4468 break;
91980990 4469
96b3c83d
BZ
4470 switch (pAKM->Type) {
4471 case 1:
ec278fa2 4472 /* Set AP support WPA-enterprise mode */
96b3c83d
BZ
4473 if (pBss->AuthMode ==
4474 Ndis802_11AuthModeOpen)
4475 pBss->AuthMode =
4476 Ndis802_11AuthModeWPA2;
4477 else
4478 pBss->AuthModeAux =
4479 Ndis802_11AuthModeWPA2;
4480 break;
4481 case 2:
ec278fa2 4482 /* Set AP support WPA-PSK mode */
96b3c83d
BZ
4483 if (pBss->AuthMode ==
4484 Ndis802_11AuthModeOpen)
4485 pBss->AuthMode =
4486 Ndis802_11AuthModeWPA2PSK;
4487 else
4488 pBss->AuthModeAux =
4489 Ndis802_11AuthModeWPA2PSK;
4490 break;
4491 default:
4492 if (pBss->AuthMode ==
4493 Ndis802_11AuthModeOpen)
4494 pBss->AuthMode =
4495 Ndis802_11AuthModeMax;
4496 else
4497 pBss->AuthModeAux =
4498 Ndis802_11AuthModeMax;
4499 break;
91980990 4500 }
62eb734b 4501 pTmp += (Count * sizeof(struct rt_akm_suite));
96b3c83d 4502 Count--;
91980990
GKH
4503 }
4504
ec278fa2 4505 /* Fixed for WPA-None */
96b3c83d
BZ
4506 if (pBss->BssType == BSS_ADHOC) {
4507 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4508 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4509 pBss->WPA.PairCipherAux =
4510 pBss->WPA2.PairCipherAux;
4511 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4512 pBss->WepStatus = pBss->WPA.GroupCipher;
ec278fa2 4513 /* Patched bugs for old driver */
96b3c83d
BZ
4514 if (pBss->WPA.PairCipherAux ==
4515 Ndis802_11WEPDisabled)
4516 pBss->WPA.PairCipherAux =
4517 pBss->WPA.GroupCipher;
4518 }
4519 pBss->WepStatus = pBss->WPA2.PairCipher;
91980990 4520
ec278fa2 4521 /* 6. Get RSN capability */
51126deb 4522 /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */
96b3c83d 4523 pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0];
51126deb 4524 pTmp += sizeof(u16);
91980990 4525
ec278fa2 4526 /* Check the Pair & Group, if different, turn on mixed mode flag */
96b3c83d
BZ
4527 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4528 pBss->WPA2.bMixMode = TRUE;
91980990 4529
96b3c83d
BZ
4530 break;
4531 default:
4532 break;
ca97b838
BZ
4533 }
4534 Length -= (pEid->Len + 2);
4535 }
4536}
91980990 4537
ec278fa2
BZ
4538/* =========================================================================================== */
4539/* mac_table.c */
4540/* =========================================================================================== */
91980990 4541
ca97b838
BZ
4542/*! \brief generates a random mac address value for IBSS BSSID
4543 * \param Addr the bssid location
4544 * \return none
4545 * \pre
4546 * \post
91980990 4547 */
62eb734b 4548void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr)
91980990 4549{
51126deb 4550 int i;
91980990 4551
96b3c83d 4552 for (i = 0; i < MAC_ADDR_LEN; i++) {
ca97b838 4553 pAddr[i] = RandomByte(pAd);
91980990 4554 }
ca97b838 4555
ec278fa2 4556 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx */
91980990
GKH
4557}
4558
ca97b838
BZ
4559/*! \brief init the management mac frame header
4560 * \param p_hdr mac header
4561 * \param subtype subtype of the frame
4562 * \param p_ds destination address, don't care if it is a broadcast address
4563 * \return none
4564 * \pre the station has the following information in the pAd->StaCfg
4565 * - bssid
4566 * - station address
4567 * \post
4568 * \note this function initializes the following field
91980990
GKH
4569
4570 IRQL = PASSIVE_LEVEL
4571 IRQL = DISPATCH_LEVEL
4572
91980990 4573 */
62eb734b
BZ
4574void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd,
4575 struct rt_header_802_11 * pHdr80211,
51126deb
BZ
4576 u8 SubType,
4577 u8 ToDs, u8 *pDA, u8 *pBssid)
91980990 4578{
62eb734b 4579 NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
91980990 4580
ca97b838
BZ
4581 pHdr80211->FC.Type = BTYPE_MGMT;
4582 pHdr80211->FC.SubType = SubType;
ec278fa2
BZ
4583/* if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type */
4584/* pHdr80211->FC.Type = BTYPE_CNTL; */
ca97b838
BZ
4585 pHdr80211->FC.ToDs = ToDs;
4586 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
96b3c83d 4587 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
ca97b838 4588 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
91980990
GKH
4589}
4590
ec278fa2
BZ
4591/* =========================================================================================== */
4592/* mem_mgmt.c */
4593/* =========================================================================================== */
ca97b838
BZ
4594
4595/*!***************************************************************************
4596 * This routine build an outgoing frame, and fill all information specified
4597 * in argument list to the frame body. The actual frame size is the summation
4598 * of all arguments.
4599 * input params:
4600 * Buffer - pointer to a pre-allocated memory segment
4601 * args - a list of <int arg_size, arg> pairs.
06aea994
SD
4602 * NOTE NOTE NOTE! the last argument must be NULL, otherwise this
4603 * function will FAIL!
ca97b838
BZ
4604 * return:
4605 * Size of the buffer
4606 * usage:
4607 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
91980990 4608
ca97b838 4609 IRQL = PASSIVE_LEVEL
91980990
GKH
4610 IRQL = DISPATCH_LEVEL
4611
ca97b838 4612 ****************************************************************************/
51126deb 4613unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...)
91980990 4614{
51126deb 4615 u8 *p;
96b3c83d 4616 int leng;
51126deb 4617 unsigned long TotLeng;
ca97b838 4618 va_list Args;
6a28a69a 4619
ec278fa2 4620 /* calculates the total length */
ca97b838
BZ
4621 TotLeng = 0;
4622 va_start(Args, FrameLen);
96b3c83d 4623 do {
ca97b838 4624 leng = va_arg(Args, int);
96b3c83d 4625 if (leng == END_OF_ARGS) {
ca97b838 4626 break;
96b3c83d 4627 }
51126deb 4628 p = va_arg(Args, void *);
ca97b838
BZ
4629 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4630 TotLeng = TotLeng + leng;
96b3c83d 4631 } while (TRUE);
6a28a69a 4632
96b3c83d 4633 va_end(Args); /* clean up */
ca97b838
BZ
4634 *FrameLen = TotLeng;
4635 return TotLeng;
91980990
GKH
4636}
4637
ec278fa2
BZ
4638/* =========================================================================================== */
4639/* mlme_queue.c */
4640/* =========================================================================================== */
91980990 4641
ca97b838
BZ
4642/*! \brief Initialize The MLME Queue, used by MLME Functions
4643 * \param *Queue The MLME Queue
4644 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4645 * \pre
4646 * \post
4647 * \note Because this is done only once (at the init stage), no need to be locked
4648
4649 IRQL = PASSIVE_LEVEL
91980990 4650
91980990 4651 */
62eb734b 4652int MlmeQueueInit(struct rt_mlme_queue *Queue)
91980990 4653{
51126deb 4654 int i;
91980990 4655
ca97b838 4656 NdisAllocateSpinLock(&Queue->Lock);
91980990 4657
96b3c83d 4658 Queue->Num = 0;
ca97b838
BZ
4659 Queue->Head = 0;
4660 Queue->Tail = 0;
59fe2d89 4661
96b3c83d 4662 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) {
ca97b838
BZ
4663 Queue->Entry[i].Occupied = FALSE;
4664 Queue->Entry[i].MsgLen = 0;
4665 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
59fe2d89 4666 }
91980990 4667
ca97b838 4668 return NDIS_STATUS_SUCCESS;
91980990
GKH
4669}
4670
ca97b838
BZ
4671/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4672 * \param *Queue The MLME Queue
4673 * \param Machine The State Machine Id
4674 * \param MsgType The Message Type
4675 * \param MsgLen The Message length
4676 * \param *Msg The message pointer
4677 * \return TRUE if enqueue is successful, FALSE if the queue is full
4678 * \pre
4679 * \post
4680 * \note The message has to be initialized
91980990
GKH
4681
4682 IRQL = PASSIVE_LEVEL
4683 IRQL = DISPATCH_LEVEL
4684
91980990 4685 */
62eb734b 4686BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd,
51126deb
BZ
4687 unsigned long Machine,
4688 unsigned long MsgType, unsigned long MsgLen, void * Msg)
91980990 4689{
51126deb 4690 int Tail;
62eb734b 4691 struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
91980990 4692
ec278fa2
BZ
4693 /* Do nothing if the driver is starting halt state. */
4694 /* This might happen when timer already been fired before cancel timer with mlmehalt */
96b3c83d
BZ
4695 if (RTMP_TEST_FLAG
4696 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838 4697 return FALSE;
91980990 4698
ec278fa2 4699 /* First check the size, it MUST not exceed the mlme queue size */
96b3c83d 4700 if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
8c3d9092 4701 DBGPRINT_ERR("MlmeEnqueue: msg too large, size = %ld \n", MsgLen);
ca97b838
BZ
4702 return FALSE;
4703 }
4704
96b3c83d 4705 if (MlmeQueueFull(Queue)) {
ca97b838 4706 return FALSE;
96b3c83d 4707 }
ca97b838
BZ
4708
4709 NdisAcquireSpinLock(&(Queue->Lock));
4710 Tail = Queue->Tail;
4711 Queue->Tail++;
4712 Queue->Num++;
96b3c83d 4713 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
ca97b838 4714 Queue->Tail = 0;
96b3c83d 4715 }
ca97b838
BZ
4716
4717 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4718 Queue->Entry[Tail].Occupied = TRUE;
4719 Queue->Entry[Tail].Machine = Machine;
4720 Queue->Entry[Tail].MsgType = MsgType;
96b3c83d 4721 Queue->Entry[Tail].MsgLen = MsgLen;
ca97b838 4722
96b3c83d 4723 if (Msg != NULL) {
ca97b838 4724 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
96b3c83d 4725 }
91980990 4726
ca97b838
BZ
4727 NdisReleaseSpinLock(&(Queue->Lock));
4728 return TRUE;
4729}
91980990 4730
ca97b838
BZ
4731/*! \brief This function is used when Recv gets a MLME message
4732 * \param *Queue The MLME Queue
4733 * \param TimeStampHigh The upper 32 bit of timestamp
4734 * \param TimeStampLow The lower 32 bit of timestamp
4735 * \param Rssi The receiving RSSI strength
4736 * \param MsgLen The length of the message
4737 * \param *Msg The message pointer
4738 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4739 * \pre
4740 * \post
91980990 4741
ca97b838 4742 IRQL = DISPATCH_LEVEL
91980990 4743
ca97b838 4744 */
62eb734b 4745BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd,
51126deb
BZ
4746 unsigned long Wcid,
4747 unsigned long TimeStampHigh,
4748 unsigned long TimeStampLow,
4749 u8 Rssi0,
4750 u8 Rssi1,
4751 u8 Rssi2,
4752 unsigned long MsgLen, void * Msg, u8 Signal)
ca97b838 4753{
51126deb 4754 int Tail, Machine;
62eb734b 4755 struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg;
51126deb 4756 int MsgType;
62eb734b 4757 struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
91980990 4758
ec278fa2
BZ
4759 /* Do nothing if the driver is starting halt state. */
4760 /* This might happen when timer already been fired before cancel timer with mlmehalt */
96b3c83d
BZ
4761 if (RTMP_TEST_FLAG
4762 (pAd,
4763 fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) {
8c3d9092 4764 DBGPRINT_ERR("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n");
ca97b838
BZ
4765 return FALSE;
4766 }
ec278fa2 4767 /* First check the size, it MUST not exceed the mlme queue size */
96b3c83d 4768 if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
8c3d9092 4769 DBGPRINT_ERR("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen);
ca97b838
BZ
4770 return FALSE;
4771 }
6a28a69a 4772
96b3c83d 4773 if (MlmeQueueFull(Queue)) {
ca97b838
BZ
4774 return FALSE;
4775 }
59fe2d89 4776
96b3c83d
BZ
4777 {
4778 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) {
8c3d9092 4779 DBGPRINT_ERR("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType);
ca97b838 4780 return FALSE;
91980990 4781 }
96b3c83d 4782 }
91980990 4783
ec278fa2 4784 /* OK, we got all the informations, it is time to put things into queue */
ca97b838
BZ
4785 NdisAcquireSpinLock(&(Queue->Lock));
4786 Tail = Queue->Tail;
4787 Queue->Tail++;
4788 Queue->Num++;
96b3c83d 4789 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
ca97b838 4790 Queue->Tail = 0;
96b3c83d 4791 }
ca97b838
BZ
4792 Queue->Entry[Tail].Occupied = TRUE;
4793 Queue->Entry[Tail].Machine = Machine;
4794 Queue->Entry[Tail].MsgType = MsgType;
96b3c83d 4795 Queue->Entry[Tail].MsgLen = MsgLen;
ca97b838
BZ
4796 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4797 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4798 Queue->Entry[Tail].Rssi0 = Rssi0;
4799 Queue->Entry[Tail].Rssi1 = Rssi1;
4800 Queue->Entry[Tail].Rssi2 = Rssi2;
4801 Queue->Entry[Tail].Signal = Signal;
51126deb 4802 Queue->Entry[Tail].Wcid = (u8)Wcid;
91980990 4803
ca97b838 4804 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
91980990 4805
96b3c83d 4806 if (Msg != NULL) {
ca97b838
BZ
4807 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4808 }
6a28a69a 4809
ca97b838 4810 NdisReleaseSpinLock(&(Queue->Lock));
91980990 4811
ca97b838 4812 RTMP_MLME_HANDLER(pAd);
91980990 4813
ca97b838 4814 return TRUE;
91980990
GKH
4815}
4816
ca97b838
BZ
4817/*! \brief Dequeue a message from the MLME Queue
4818 * \param *Queue The MLME Queue
4819 * \param *Elem The message dequeued from MLME Queue
4820 * \return TRUE if the Elem contains something, FALSE otherwise
4821 * \pre
4822 * \post
4823
4824 IRQL = DISPATCH_LEVEL
91980990 4825
91980990 4826 */
62eb734b 4827BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem)
91980990 4828{
ca97b838
BZ
4829 NdisAcquireSpinLock(&(Queue->Lock));
4830 *Elem = &(Queue->Entry[Queue->Head]);
4831 Queue->Num--;
4832 Queue->Head++;
96b3c83d 4833 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) {
ca97b838 4834 Queue->Head = 0;
91980990 4835 }
ca97b838
BZ
4836 NdisReleaseSpinLock(&(Queue->Lock));
4837 return TRUE;
91980990
GKH
4838}
4839
ec278fa2 4840/* IRQL = DISPATCH_LEVEL */
62eb734b 4841void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd)
91980990 4842{
ca97b838 4843#ifdef RTMP_MAC_PCI
62eb734b 4844 struct rt_mlme_queue_elem *Elem = NULL;
ec278fa2 4845#endif /* RTMP_MAC_PCI // */
96b3c83d 4846 BOOLEAN Cancelled;
91980990 4847
ca97b838 4848 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
91980990 4849
ca97b838
BZ
4850#ifdef RTMP_MAC_PCI
4851 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
96b3c83d 4852 if (pAd->Mlme.bRunning) {
ca97b838
BZ
4853 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4854 return;
96b3c83d 4855 } else {
ca97b838 4856 pAd->Mlme.bRunning = TRUE;
91980990 4857 }
ca97b838 4858 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
59fe2d89 4859
ec278fa2 4860 /* Remove all Mlme queues elements */
96b3c83d 4861 while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
ec278fa2 4862 /*From message type, determine which state machine I should drive */
96b3c83d 4863 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
ec278fa2 4864 /* free MLME element */
ca97b838
BZ
4865 Elem->Occupied = FALSE;
4866 Elem->MsgLen = 0;
91980990 4867
96b3c83d 4868 } else {
8c3d9092 4869 DBGPRINT_ERR("MlmeRestartStateMachine: MlmeQueue empty\n");
96b3c83d 4870 }
91980990 4871 }
ec278fa2 4872#endif /* RTMP_MAC_PCI // */
ca97b838 4873
91980990 4874 {
ec278fa2
BZ
4875 /* Cancel all timer events */
4876 /* Be careful to cancel new added timer */
96b3c83d
BZ
4877 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4878 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4879 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4880 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4881 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4882 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
91980990 4883
ca97b838 4884 }
91980990 4885
ec278fa2 4886 /* Change back to original channel in case of doing scan */
ca97b838
BZ
4887 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4888 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
91980990 4889
ec278fa2 4890 /* Resume MSDU which is turned off durning scan */
ca97b838 4891 RTMPResumeMsduTransmission(pAd);
91980990 4892
91980990 4893 {
ec278fa2 4894 /* Set all state machines back IDLE */
96b3c83d
BZ
4895 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4896 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4897 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
ca97b838 4898 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
96b3c83d
BZ
4899 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4900 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
91980990 4901 }
91980990 4902
ca97b838 4903#ifdef RTMP_MAC_PCI
ec278fa2 4904 /* Remove running state */
ca97b838
BZ
4905 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4906 pAd->Mlme.bRunning = FALSE;
4907 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
ec278fa2 4908#endif /* RTMP_MAC_PCI // */
91980990
GKH
4909}
4910
ca97b838
BZ
4911/*! \brief test if the MLME Queue is empty
4912 * \param *Queue The MLME Queue
4913 * \return TRUE if the Queue is empty, FALSE otherwise
4914 * \pre
4915 * \post
91980990 4916
ca97b838 4917 IRQL = DISPATCH_LEVEL
91980990 4918
ca97b838 4919 */
62eb734b 4920BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue)
91980990 4921{
ca97b838 4922 BOOLEAN Ans;
91980990 4923
ca97b838
BZ
4924 NdisAcquireSpinLock(&(Queue->Lock));
4925 Ans = (Queue->Num == 0);
4926 NdisReleaseSpinLock(&(Queue->Lock));
91980990 4927
ca97b838 4928 return Ans;
91980990
GKH
4929}
4930
ca97b838
BZ
4931/*! \brief test if the MLME Queue is full
4932 * \param *Queue The MLME Queue
4933 * \return TRUE if the Queue is empty, FALSE otherwise
4934 * \pre
4935 * \post
4936
4937 IRQL = PASSIVE_LEVEL
4938 IRQL = DISPATCH_LEVEL
4939
4940 */
62eb734b 4941BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue)
91980990 4942{
ca97b838 4943 BOOLEAN Ans;
91980990 4944
ca97b838 4945 NdisAcquireSpinLock(&(Queue->Lock));
96b3c83d
BZ
4946 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE
4947 || Queue->Entry[Queue->Tail].Occupied);
ca97b838 4948 NdisReleaseSpinLock(&(Queue->Lock));
91980990 4949
ca97b838
BZ
4950 return Ans;
4951}
91980990 4952
ca97b838
BZ
4953/*! \brief The destructor of MLME Queue
4954 * \param
4955 * \return
4956 * \pre
4957 * \post
4958 * \note Clear Mlme Queue, Set Queue->Num to Zero.
91980990 4959
ca97b838 4960 IRQL = PASSIVE_LEVEL
91980990 4961
ca97b838 4962 */
62eb734b 4963void MlmeQueueDestroy(struct rt_mlme_queue *pQueue)
ca97b838
BZ
4964{
4965 NdisAcquireSpinLock(&(pQueue->Lock));
96b3c83d 4966 pQueue->Num = 0;
ca97b838
BZ
4967 pQueue->Head = 0;
4968 pQueue->Tail = 0;
4969 NdisReleaseSpinLock(&(pQueue->Lock));
4970 NdisFreeSpinLock(&(pQueue->Lock));
4971}
91980990 4972
ca97b838
BZ
4973/*! \brief To substitute the message type if the message is coming from external
4974 * \param pFrame The frame received
4975 * \param *Machine The state machine
4976 * \param *MsgType the message type for the state machine
4977 * \return TRUE if the substitution is successful, FALSE otherwise
4978 * \pre
4979 * \post
91980990 4980
ca97b838 4981 IRQL = DISPATCH_LEVEL
91980990 4982
ca97b838 4983 */
62eb734b
BZ
4984BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd,
4985 struct rt_frame_802_11 * pFrame,
51126deb 4986 int * Machine, int * MsgType)
91980990 4987{
51126deb
BZ
4988 u16 Seq, Alg;
4989 u8 EAPType;
4990 u8 *pData;
91980990 4991
ec278fa2 4992 /* Pointer to start of data frames including SNAP header */
51126deb 4993 pData = (u8 *)pFrame + LENGTH_802_11;
91980990 4994
ec278fa2 4995 /* The only data type will pass to this function is EAPOL frame */
96b3c83d 4996 if (pFrame->Hdr.FC.Type == BTYPE_DATA) {
91980990 4997 {
96b3c83d
BZ
4998 *Machine = WPA_STATE_MACHINE;
4999 EAPType =
51126deb 5000 *((u8 *) pFrame + LENGTH_802_11 +
96b3c83d 5001 LENGTH_802_1_H + 1);
51126deb 5002 return (WpaMsgTypeSubst(EAPType, (int *) MsgType));
91980990
GKH
5003 }
5004 }
91980990 5005
96b3c83d
BZ
5006 switch (pFrame->Hdr.FC.SubType) {
5007 case SUBTYPE_ASSOC_REQ:
5008 *Machine = ASSOC_STATE_MACHINE;
5009 *MsgType = MT2_PEER_ASSOC_REQ;
5010 break;
5011 case SUBTYPE_ASSOC_RSP:
5012 *Machine = ASSOC_STATE_MACHINE;
5013 *MsgType = MT2_PEER_ASSOC_RSP;
5014 break;
5015 case SUBTYPE_REASSOC_REQ:
5016 *Machine = ASSOC_STATE_MACHINE;
5017 *MsgType = MT2_PEER_REASSOC_REQ;
5018 break;
5019 case SUBTYPE_REASSOC_RSP:
5020 *Machine = ASSOC_STATE_MACHINE;
5021 *MsgType = MT2_PEER_REASSOC_RSP;
5022 break;
5023 case SUBTYPE_PROBE_REQ:
5024 *Machine = SYNC_STATE_MACHINE;
5025 *MsgType = MT2_PEER_PROBE_REQ;
5026 break;
5027 case SUBTYPE_PROBE_RSP:
5028 *Machine = SYNC_STATE_MACHINE;
5029 *MsgType = MT2_PEER_PROBE_RSP;
5030 break;
5031 case SUBTYPE_BEACON:
5032 *Machine = SYNC_STATE_MACHINE;
5033 *MsgType = MT2_PEER_BEACON;
5034 break;
5035 case SUBTYPE_ATIM:
5036 *Machine = SYNC_STATE_MACHINE;
5037 *MsgType = MT2_PEER_ATIM;
5038 break;
5039 case SUBTYPE_DISASSOC:
5040 *Machine = ASSOC_STATE_MACHINE;
5041 *MsgType = MT2_PEER_DISASSOC_REQ;
5042 break;
5043 case SUBTYPE_AUTH:
ec278fa2 5044 /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
51126deb
BZ
5045 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16));
5046 NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16));
96b3c83d 5047 if (Seq == 1 || Seq == 3) {
ca97b838 5048 *Machine = AUTH_RSP_STATE_MACHINE;
96b3c83d
BZ
5049 *MsgType = MT2_PEER_AUTH_ODD;
5050 } else if (Seq == 2 || Seq == 4) {
5051 if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) {
5052 *Machine = AUTH_STATE_MACHINE;
5053 *MsgType = MT2_PEER_AUTH_EVEN;
5054 }
5055 } else {
5056 return FALSE;
91980990 5057 }
96b3c83d
BZ
5058 break;
5059 case SUBTYPE_DEAUTH:
5060 *Machine = AUTH_RSP_STATE_MACHINE;
5061 *MsgType = MT2_PEER_DEAUTH;
5062 break;
5063 case SUBTYPE_ACTION:
5064 *Machine = ACTION_STATE_MACHINE;
ec278fa2 5065 /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
96b3c83d
BZ
5066 if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) {
5067 *MsgType = MT2_ACT_INVALID;
5068 } else {
5069 *MsgType = (pFrame->Octet[0] & 0x7F);
91980990 5070 }
96b3c83d
BZ
5071 break;
5072 default:
5073 return FALSE;
5074 break;
91980990
GKH
5075 }
5076
ca97b838 5077 return TRUE;
91980990
GKH
5078}
5079
ec278fa2
BZ
5080/* =========================================================================================== */
5081/* state_machine.c */
5082/* =========================================================================================== */
91980990 5083
ca97b838
BZ
5084/*! \brief Initialize the state machine.
5085 * \param *S pointer to the state machine
5086 * \param Trans State machine transition function
5087 * \param StNr number of states
5088 * \param MsgNr number of messages
5089 * \param DefFunc default function, when there is invalid state/message combination
5090 * \param InitState initial state of the state machine
5091 * \param Base StateMachine base, internal use only
5092 * \pre p_sm should be a legal pointer
5093 * \post
91980990 5094
ca97b838
BZ
5095 IRQL = PASSIVE_LEVEL
5096
5097 */
62eb734b 5098void StateMachineInit(struct rt_state_machine *S,
96b3c83d 5099 IN STATE_MACHINE_FUNC Trans[],
51126deb
BZ
5100 unsigned long StNr,
5101 unsigned long MsgNr,
96b3c83d 5102 IN STATE_MACHINE_FUNC DefFunc,
51126deb 5103 unsigned long InitState, unsigned long Base)
91980990 5104{
51126deb 5105 unsigned long i, j;
91980990 5106
ec278fa2 5107 /* set number of states and messages */
ca97b838 5108 S->NrState = StNr;
96b3c83d
BZ
5109 S->NrMsg = MsgNr;
5110 S->Base = Base;
91980990 5111
96b3c83d 5112 S->TransFunc = Trans;
ca97b838 5113
ec278fa2 5114 /* init all state transition to default function */
96b3c83d
BZ
5115 for (i = 0; i < StNr; i++) {
5116 for (j = 0; j < MsgNr; j++) {
ca97b838 5117 S->TransFunc[i * MsgNr + j] = DefFunc;
91980990 5118 }
91980990
GKH
5119 }
5120
ec278fa2 5121 /* set the starting state */
ca97b838
BZ
5122 S->CurrState = InitState;
5123}
5124
5125/*! \brief This function fills in the function pointer into the cell in the state machine
5126 * \param *S pointer to the state machine
5127 * \param St state
5128 * \param Msg incoming message
5129 * \param f the function to be executed when (state, message) combination occurs at the state machine
5130 * \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
5131 * \post
5132
5133 IRQL = PASSIVE_LEVEL
5134
5135 */
62eb734b 5136void StateMachineSetAction(struct rt_state_machine *S,
51126deb
BZ
5137 unsigned long St,
5138 unsigned long Msg, IN STATE_MACHINE_FUNC Func)
ca97b838 5139{
51126deb 5140 unsigned long MsgIdx;
ca97b838
BZ
5141
5142 MsgIdx = Msg - S->Base;
5143
96b3c83d 5144 if (St < S->NrState && MsgIdx < S->NrMsg) {
ec278fa2 5145 /* boundary checking before setting the action */
ca97b838 5146 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
91980990
GKH
5147 }
5148}
ca97b838
BZ
5149
5150/*! \brief This function does the state transition
5151 * \param *Adapter the NIC adapter pointer
5152 * \param *S the state machine
5153 * \param *Elem the message to be executed
5154 * \return None
5155
5156 IRQL = DISPATCH_LEVEL
5157
5158 */
62eb734b
BZ
5159void StateMachinePerformAction(struct rt_rtmp_adapter *pAd,
5160 struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem)
ca97b838 5161{
96b3c83d
BZ
5162 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))
5163 (pAd, Elem);
ca97b838
BZ
5164}
5165
91980990 5166/*
ca97b838 5167 ==========================================================================
91980990 5168 Description:
ca97b838
BZ
5169 The drop function, when machine executes this, the message is simply
5170 ignored. This function does nothing, the message is freed in
5171 StateMachinePerformAction()
5172 ==========================================================================
5173 */
62eb734b 5174void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
91980990 5175{
91980990
GKH
5176}
5177
ec278fa2
BZ
5178/* =========================================================================================== */
5179/* lfsr.c */
5180/* =========================================================================================== */
91980990 5181
ca97b838
BZ
5182/*
5183 ==========================================================================
5184 Description:
91980990 5185
ca97b838 5186 IRQL = PASSIVE_LEVEL
91980990 5187
ca97b838
BZ
5188 ==========================================================================
5189 */
62eb734b 5190void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed)
91980990 5191{
ca97b838
BZ
5192 if (Seed == 0)
5193 pAd->Mlme.ShiftReg = 1;
5194 else
5195 pAd->Mlme.ShiftReg = Seed;
5196}
91980990 5197
ca97b838
BZ
5198/*
5199 ==========================================================================
5200 Description:
5201 ==========================================================================
5202 */
62eb734b 5203u8 RandomByte(struct rt_rtmp_adapter *pAd)
ca97b838 5204{
51126deb
BZ
5205 unsigned long i;
5206 u8 R, Result;
91980990 5207
ca97b838 5208 R = 0;
91980990 5209
ca97b838 5210 if (pAd->Mlme.ShiftReg == 0)
51126deb 5211 NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg);
91980990 5212
96b3c83d
BZ
5213 for (i = 0; i < 8; i++) {
5214 if (pAd->Mlme.ShiftReg & 0x00000001) {
5215 pAd->Mlme.ShiftReg =
5216 ((pAd->Mlme.
5217 ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
ca97b838 5218 Result = 1;
96b3c83d 5219 } else {
ca97b838
BZ
5220 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5221 Result = 0;
5222 }
5223 R = (R << 1) | Result;
91980990 5224 }
91980990 5225
ca97b838 5226 return R;
91980990 5227}
ca97b838 5228
91980990
GKH
5229/*
5230 ========================================================================
5231
5232 Routine Description:
5233 Verify the support rate for different PHY type
5234
5235 Arguments:
5236 pAd Pointer to our adapter
5237
5238 Return Value:
5239 None
5240
5241 IRQL = PASSIVE_LEVEL
5242
5243 ========================================================================
5244*/
62eb734b 5245void RTMPCheckRates(struct rt_rtmp_adapter *pAd,
51126deb 5246 IN u8 SupRate[], IN u8 * SupRateLen)
91980990 5247{
51126deb
BZ
5248 u8 RateIdx, i, j;
5249 u8 NewRate[12], NewRateLen;
91980990
GKH
5250
5251 NewRateLen = 0;
5252
5253 if (pAd->CommonCfg.PhyMode == PHY_11B)
5254 RateIdx = 4;
5255 else
5256 RateIdx = 12;
5257
ec278fa2 5258 /* Check for support rates exclude basic rate bit */
91980990
GKH
5259 for (i = 0; i < *SupRateLen; i++)
5260 for (j = 0; j < RateIdx; j++)
5261 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5262 NewRate[NewRateLen++] = SupRate[i];
5263
5264 *SupRateLen = NewRateLen;
5265 NdisMoveMemory(SupRate, NewRate, NewRateLen);
5266}
5267
62eb734b 5268BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd,
51126deb 5269 u8 CentralChannel, u8 Channel)
91980990 5270{
51126deb
BZ
5271 u8 k;
5272 u8 UpperChannel = 0, LowerChannel = 0;
5273 u8 NoEffectChannelinList = 0;
91980990 5274
ec278fa2 5275 /* Find upper and lower channel according to 40MHz current operation. */
96b3c83d 5276 if (CentralChannel < Channel) {
91980990
GKH
5277 UpperChannel = Channel;
5278 if (CentralChannel > 2)
5279 LowerChannel = CentralChannel - 2;
5280 else
5281 return FALSE;
96b3c83d 5282 } else if (CentralChannel > Channel) {
91980990
GKH
5283 UpperChannel = CentralChannel + 2;
5284 LowerChannel = Channel;
5285 }
5286
96b3c83d
BZ
5287 for (k = 0; k < pAd->ChannelListNum; k++) {
5288 if (pAd->ChannelList[k].Channel == UpperChannel) {
5289 NoEffectChannelinList++;
91980990 5290 }
96b3c83d
BZ
5291 if (pAd->ChannelList[k].Channel == LowerChannel) {
5292 NoEffectChannelinList++;
91980990
GKH
5293 }
5294 }
5295
96b3c83d
BZ
5296 DBGPRINT(RT_DEBUG_TRACE,
5297 ("Total Channel in Channel List = [%d]\n",
5298 NoEffectChannelinList));
91980990
GKH
5299 if (NoEffectChannelinList == 2)
5300 return TRUE;
5301 else
5302 return FALSE;
5303}
5304
5305/*
5306 ========================================================================
5307
5308 Routine Description:
5309 Verify the support rate for HT phy type
5310
5311 Arguments:
5312 pAd Pointer to our adapter
5313
5314 Return Value:
5315 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
5316
5317 IRQL = PASSIVE_LEVEL
5318
5319 ========================================================================
5320*/
62eb734b 5321BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd,
51126deb 5322 u8 Wcid,
62eb734b
BZ
5323 struct rt_ht_capability_ie * pHtCapability,
5324 struct rt_add_ht_info_ie * pAddHtInfo)
91980990
GKH
5325{
5326 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5327 return FALSE;
5328
ec278fa2 5329 /* If use AMSDU, set flag. */
91980990 5330 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
96b3c83d
BZ
5331 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5332 fCLIENT_STATUS_AMSDU_INUSED);
ec278fa2 5333 /* Save Peer Capability */
91980990 5334 if (pHtCapability->HtCapInfo.ShortGIfor20)
96b3c83d
BZ
5335 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5336 fCLIENT_STATUS_SGI20_CAPABLE);
91980990 5337 if (pHtCapability->HtCapInfo.ShortGIfor40)
96b3c83d
BZ
5338 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5339 fCLIENT_STATUS_SGI40_CAPABLE);
91980990 5340 if (pHtCapability->HtCapInfo.TxSTBC)
96b3c83d
BZ
5341 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5342 fCLIENT_STATUS_TxSTBC_CAPABLE);
91980990 5343 if (pHtCapability->HtCapInfo.RxSTBC)
96b3c83d
BZ
5344 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5345 fCLIENT_STATUS_RxSTBC_CAPABLE);
5346 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) {
5347 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5348 fCLIENT_STATUS_RDG_CAPABLE);
91980990
GKH
5349 }
5350
96b3c83d
BZ
5351 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
5352 pAd->MacTab.Content[Wcid].MpduDensity =
5353 pHtCapability->HtCapParm.MpduDensity;
91980990 5354 }
ec278fa2 5355 /* Will check ChannelWidth for MCSSet[4] below */
91980990 5356 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
96b3c83d
BZ
5357 switch (pAd->CommonCfg.RxStream) {
5358 case 1:
5359 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5360 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5361 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5362 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5363 break;
5364 case 2:
5365 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5366 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5367 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5368 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5369 break;
5370 case 3:
5371 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5372 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5373 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5374 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5375 break;
5376 }
5377
5378 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth =
5379 pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.
5380 ChannelWidth;
5381
5382 DBGPRINT(RT_DEBUG_TRACE,
5383 ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5384 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth,
5385 pAddHtInfo->AddHtInfo.RecomWidth,
5386 pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5387 pAd->NicConfig2.field.BW40MAvailForA,
5388 pAd->NicConfig2.field.BW40MAvailForG,
5389 pAd->CommonCfg.PhyMode));
5390
5391 pAd->MlmeAux.HtCapability.HtCapInfo.GF =
5392 pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF;
91980990 5393
ec278fa2 5394 /* Send Assoc Req with my HT capability. */
96b3c83d
BZ
5395 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =
5396 pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5397 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =
5398 pAd->CommonCfg.DesiredHtPhy.MimoPs;
5399 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =
5400 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->
5401 HtCapInfo.
5402 ShortGIfor20);
5403 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =
5404 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->
5405 HtCapInfo.
5406 ShortGIfor40);
5407 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =
5408 (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo.
5409 RxSTBC);
5410 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =
5411 (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo.
5412 TxSTBC);
5413 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor =
5414 pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5415 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity =
5416 pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5417 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC =
5418 pHtCapability->ExtHtCapInfo.PlusHTC;
5419 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC =
5420 pHtCapability->ExtHtCapInfo.PlusHTC;
5421 if (pAd->CommonCfg.bRdg) {
5422 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport =
5423 pHtCapability->ExtHtCapInfo.RDGSupport;
5424 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5425 }
5426
5427 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
ec278fa2 5428 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; /* BW20 can't transmit MCS32 */
91980990
GKH
5429
5430 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5431 return TRUE;
5432}
91980990
GKH
5433
5434/*
5435 ========================================================================
5436
5437 Routine Description:
5438 Verify the support rate for different PHY type
5439
5440 Arguments:
5441 pAd Pointer to our adapter
5442
5443 Return Value:
5444 None
5445
5446 IRQL = PASSIVE_LEVEL
5447
5448 ========================================================================
5449*/
62eb734b 5450void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd)
91980990 5451{
51126deb
BZ
5452 u8 MinimumRate;
5453 u8 ProperMlmeRate; /*= RATE_54; */
5454 u8 i, j, RateIdx = 12; /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
96b3c83d
BZ
5455 BOOLEAN bMatch = FALSE;
5456
5457 switch (pAd->CommonCfg.PhyMode) {
5458 case PHY_11B:
5459 ProperMlmeRate = RATE_11;
5460 MinimumRate = RATE_1;
5461 break;
5462 case PHY_11BG_MIXED:
5463 case PHY_11ABGN_MIXED:
5464 case PHY_11BGN_MIXED:
5465 if ((pAd->MlmeAux.SupRateLen == 4) &&
5466 (pAd->MlmeAux.ExtRateLen == 0))
ec278fa2 5467 /* B only AP */
91980990 5468 ProperMlmeRate = RATE_11;
96b3c83d 5469 else
91980990 5470 ProperMlmeRate = RATE_24;
96b3c83d
BZ
5471
5472 if (pAd->MlmeAux.Channel <= 14)
5473 MinimumRate = RATE_1;
5474 else
91980990 5475 MinimumRate = RATE_6;
96b3c83d
BZ
5476 break;
5477 case PHY_11A:
ec278fa2 5478 case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n */
96b3c83d
BZ
5479 case PHY_11GN_MIXED:
5480 case PHY_11AGN_MIXED:
5481 case PHY_11AN_MIXED:
5482 case PHY_11N_5G:
5483 ProperMlmeRate = RATE_24;
5484 MinimumRate = RATE_6;
5485 break;
5486 case PHY_11ABG_MIXED:
5487 ProperMlmeRate = RATE_24;
5488 if (pAd->MlmeAux.Channel <= 14)
91980990 5489 MinimumRate = RATE_1;
96b3c83d
BZ
5490 else
5491 MinimumRate = RATE_6;
5492 break;
ec278fa2 5493 default: /* error */
96b3c83d
BZ
5494 ProperMlmeRate = RATE_1;
5495 MinimumRate = RATE_1;
5496 break;
5497 }
5498
5499 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) {
5500 for (j = 0; j < RateIdx; j++) {
5501 if ((pAd->MlmeAux.SupRate[i] & 0x7f) ==
5502 RateIdTo500Kbps[j]) {
5503 if (j == ProperMlmeRate) {
91980990
GKH
5504 bMatch = TRUE;
5505 break;
5506 }
5507 }
5508 }
5509
5510 if (bMatch)
5511 break;
5512 }
5513
96b3c83d
BZ
5514 if (bMatch == FALSE) {
5515 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) {
5516 for (j = 0; j < RateIdx; j++) {
5517 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) ==
5518 RateIdTo500Kbps[j]) {
5519 if (j == ProperMlmeRate) {
91980990
GKH
5520 bMatch = TRUE;
5521 break;
5522 }
5523 }
5524 }
5525
5526 if (bMatch)
5527 break;
5528 }
5529 }
5530
96b3c83d 5531 if (bMatch == FALSE) {
91980990
GKH
5532 ProperMlmeRate = MinimumRate;
5533 }
5534
5535 pAd->CommonCfg.MlmeRate = MinimumRate;
5536 pAd->CommonCfg.RtsRate = ProperMlmeRate;
96b3c83d 5537 if (pAd->CommonCfg.MlmeRate >= RATE_6) {
91980990 5538 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
96b3c83d
BZ
5539 pAd->CommonCfg.MlmeTransmit.field.MCS =
5540 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5541 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5542 MODE_OFDM;
5543 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5544 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5545 } else {
91980990
GKH
5546 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5547 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
96b3c83d
BZ
5548 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5549 MODE_CCK;
5550 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5551 pAd->CommonCfg.MlmeRate;
91980990
GKH
5552 }
5553
96b3c83d
BZ
5554 DBGPRINT(RT_DEBUG_TRACE,
5555 ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n",
5556 pAd->CommonCfg.MlmeTransmit.word));
91980990
GKH
5557}
5558
62eb734b 5559char RTMPMaxRssi(struct rt_rtmp_adapter *pAd,
51126deb 5560 char Rssi0, char Rssi1, char Rssi2)
91980990 5561{
51126deb 5562 char larger = -127;
91980990 5563
96b3c83d 5564 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) {
91980990
GKH
5565 larger = Rssi0;
5566 }
5567
96b3c83d 5568 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) {
91980990
GKH
5569 larger = max(Rssi0, Rssi1);
5570 }
5571
96b3c83d 5572 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) {
91980990
GKH
5573 larger = max(larger, Rssi2);
5574 }
5575
5576 if (larger == -127)
5577 larger = 0;
5578
5579 return larger;
5580}
5581
5582/*
5583 ========================================================================
5584 Routine Description:
5585 Periodic evaluate antenna link status
5586
5587 Arguments:
5588 pAd - Adapter pointer
5589
5590 Return Value:
5591 None
5592
5593 ========================================================================
5594*/
62eb734b 5595void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd)
91980990 5596{
51126deb 5597 u8 BBPR3 = 0;
91980990 5598
e932e724 5599 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
96b3c83d
BZ
5600 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5601 fRTMP_ADAPTER_RADIO_OFF |
5602 fRTMP_ADAPTER_NIC_NOT_EXIST |
5603 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5604 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
ca97b838 5605#ifdef RT30xx
96b3c83d 5606 || (pAd->EepromAccess)
ec278fa2 5607#endif /* RT30xx // */
e44fd1cf 5608#ifdef RT3090
96b3c83d 5609 || (pAd->bPCIclkOff == TRUE)
ec278fa2 5610#endif /* RT3090 // */
96b3c83d
BZ
5611 )
5612 return;
59fe2d89 5613
ca97b838 5614 {
ec278fa2
BZ
5615 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5616 /* return; */
59fe2d89 5617
96b3c83d 5618 {
ca97b838 5619
96b3c83d
BZ
5620 if (pAd->StaCfg.Psm == PWR_SAVE)
5621 return;
59fe2d89 5622
96b3c83d
BZ
5623 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5624 BBPR3 &= (~0x18);
5625 if (pAd->Antenna.field.RxPath == 3) {
5626 BBPR3 |= (0x10);
5627 } else if (pAd->Antenna.field.RxPath == 2) {
5628 BBPR3 |= (0x8);
5629 } else if (pAd->Antenna.field.RxPath == 1) {
5630 BBPR3 |= (0x0);
5631 }
5632 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
ca97b838 5633#ifdef RTMP_MAC_PCI
96b3c83d 5634 pAd->StaCfg.BBPR3 = BBPR3;
ec278fa2 5635#endif /* RTMP_MAC_PCI // */
96b3c83d
BZ
5636 if (OPSTATUS_TEST_FLAG
5637 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5638 ) {
51126deb 5639 unsigned long TxTotalCnt =
96b3c83d
BZ
5640 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5641 pAd->RalinkCounters.OneSecTxRetryOkCount +
5642 pAd->RalinkCounters.OneSecTxFailCount;
5643
ec278fa2 5644 /* dynamic adjust antenna evaluation period according to the traffic */
96b3c83d
BZ
5645 if (TxTotalCnt > 50) {
5646 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5647 20);
5648 pAd->Mlme.bLowThroughput = FALSE;
5649 } else {
5650 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5651 300);
5652 pAd->Mlme.bLowThroughput = TRUE;
5653 }
5654 }
ca97b838
BZ
5655 }
5656
5657 }
5658
91980990
GKH
5659}
5660
5661/*
5662 ========================================================================
5663 Routine Description:
5664 After evaluation, check antenna link status
5665
5666 Arguments:
5667 pAd - Adapter pointer
5668
5669 Return Value:
5670 None
5671
5672 ========================================================================
5673*/
51126deb
BZ
5674void AsicRxAntEvalTimeout(void *SystemSpecific1,
5675 void *FunctionContext,
5676 void *SystemSpecific2, void *SystemSpecific3)
91980990 5677{
62eb734b 5678 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
51126deb
BZ
5679 u8 BBPR3 = 0;
5680 char larger = -127, rssi0, rssi1, rssi2;
96b3c83d
BZ
5681
5682 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5683 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5684 fRTMP_ADAPTER_RADIO_OFF |
5685 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5686 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
ca97b838 5687#ifdef RT30xx
96b3c83d 5688 || (pAd->EepromAccess)
ec278fa2 5689#endif /* RT30xx // */
e44fd1cf 5690#ifdef RT3090
96b3c83d 5691 || (pAd->bPCIclkOff == TRUE)
ec278fa2 5692#endif /* RT3090 // */
96b3c83d 5693 )
59fe2d89
BZ
5694 return;
5695
5696 {
ec278fa2
BZ
5697 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5698 /* return; */
59fe2d89
BZ
5699 {
5700 if (pAd->StaCfg.Psm == PWR_SAVE)
5701 return;
5702
ec278fa2 5703 /* if the traffic is low, use average rssi as the criteria */
96b3c83d 5704 if (pAd->Mlme.bLowThroughput == TRUE) {
59fe2d89
BZ
5705 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5706 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5707 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
96b3c83d 5708 } else {
59fe2d89
BZ
5709 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5710 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5711 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5712 }
5713
96b3c83d 5714 if (pAd->Antenna.field.RxPath == 3) {
59fe2d89
BZ
5715 larger = max(rssi0, rssi1);
5716
5717 if (larger > (rssi2 + 20))
5718 pAd->Mlme.RealRxPath = 2;
5719 else
5720 pAd->Mlme.RealRxPath = 3;
96b3c83d 5721 } else if (pAd->Antenna.field.RxPath == 2) {
59fe2d89
BZ
5722 if (rssi0 > (rssi1 + 20))
5723 pAd->Mlme.RealRxPath = 1;
5724 else
5725 pAd->Mlme.RealRxPath = 2;
5726 }
5727
5728 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5729 BBPR3 &= (~0x18);
96b3c83d 5730 if (pAd->Mlme.RealRxPath == 3) {
59fe2d89 5731 BBPR3 |= (0x10);
96b3c83d 5732 } else if (pAd->Mlme.RealRxPath == 2) {
59fe2d89 5733 BBPR3 |= (0x8);
96b3c83d 5734 } else if (pAd->Mlme.RealRxPath == 1) {
59fe2d89
BZ
5735 BBPR3 |= (0x0);
5736 }
5737 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
ca97b838 5738#ifdef RTMP_MAC_PCI
331e0c16 5739 pAd->StaCfg.BBPR3 = BBPR3;
ec278fa2 5740#endif /* RTMP_MAC_PCI // */
59fe2d89
BZ
5741 }
5742 }
ca97b838 5743
91980990
GKH
5744}
5745
51126deb
BZ
5746void APSDPeriodicExec(void *SystemSpecific1,
5747 void *FunctionContext,
5748 void *SystemSpecific2, void *SystemSpecific3)
91980990 5749{
62eb734b 5750 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
91980990
GKH
5751
5752 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5753 return;
5754
5755 pAd->CommonCfg.TriggerTimerCount++;
5756
ec278fa2 5757/* Driver should not send trigger frame, it should be send by application layer */
ca97b838
BZ
5758/*
5759 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5760 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5761 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5762 {
5763 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5764 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5765 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5766 pAd->CommonCfg.TriggerTimerCount = 0;
5767 pAd->CommonCfg.bInServicePeriod = TRUE;
5768 }*/
91980990
GKH
5769}
5770
5771/*
5772 ========================================================================
5773 Routine Description:
5774 Set/reset MAC registers according to bPiggyBack parameter
5775
5776 Arguments:
5777 pAd - Adapter pointer
5778 bPiggyBack - Enable / Disable Piggy-Back
5779
5780 Return Value:
5781 None
5782
5783 ========================================================================
5784*/
62eb734b 5785void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack)
91980990 5786{
96b3c83d 5787 TX_LINK_CFG_STRUC TxLinkCfg;
91980990
GKH
5788
5789 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5790
5791 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5792 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5793}
5794
5795/*
5796 ========================================================================
5797 Routine Description:
5798 check if this entry need to switch rate automatically
5799
5800 Arguments:
5801 pAd
5802 pEntry
5803
5804 Return Value:
5805 TURE
5806 FALSE
5807
5808 ========================================================================
5809*/
62eb734b
BZ
5810BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd,
5811 struct rt_mac_table_entry *pEntry)
91980990 5812{
96b3c83d 5813 BOOLEAN result = TRUE;
91980990 5814
91980990 5815 {
ec278fa2 5816 /* only associated STA counts */
96b3c83d
BZ
5817 if (pEntry && (pEntry->ValidAsCLI)
5818 && (pEntry->Sst == SST_ASSOC)) {
91980990 5819 result = pAd->StaCfg.bAutoTxRateSwitch;
96b3c83d 5820 } else
91980990 5821 result = FALSE;
91980990 5822 }
91980990
GKH
5823
5824 return result;
5825}
5826
62eb734b 5827BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd)
91980990 5828{
ca97b838 5829 {
96b3c83d
BZ
5830 if (pAd->StaCfg.bAutoTxRateSwitch)
5831 return TRUE;
ca97b838 5832 }
91980990
GKH
5833 return FALSE;
5834}
5835
91980990
GKH
5836/*
5837 ========================================================================
5838 Routine Description:
5839 check if this entry need to fix tx legacy rate
5840
5841 Arguments:
5842 pAd
5843 pEntry
5844
5845 Return Value:
5846 TURE
5847 FALSE
5848
5849 ========================================================================
5850*/
62eb734b 5851u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
91980990 5852{
51126deb 5853 u8 tx_mode = FIXED_TXMODE_HT;
91980990 5854
ca97b838 5855 {
96b3c83d 5856 tx_mode =
51126deb 5857 (u8)pAd->StaCfg.DesiredTransmitSetting.field.
96b3c83d 5858 FixedTxMode;
ca97b838 5859 }
91980990
GKH
5860
5861 return tx_mode;
5862}
5863
5864/*
5865 ========================================================================
5866 Routine Description:
5867 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5868
5869 Arguments:
5870 pAd
5871 pEntry
5872
5873 Return Value:
5874 TURE
5875 FALSE
5876
5877 ========================================================================
5878*/
62eb734b 5879void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry)
91980990
GKH
5880{
5881 HTTRANSMIT_SETTING TransmitSetting;
5882
5883 if (fixed_tx_mode == FIXED_TXMODE_HT)
5884 return;
5885
5886 TransmitSetting.word = 0;
5887
5888 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5889 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5890
96b3c83d 5891 if (fixed_tx_mode == FIXED_TXMODE_CCK) {
91980990 5892 TransmitSetting.field.MODE = MODE_CCK;
ec278fa2 5893 /* CCK mode allow MCS 0~3 */
91980990
GKH
5894 if (TransmitSetting.field.MCS > MCS_3)
5895 TransmitSetting.field.MCS = MCS_3;
96b3c83d 5896 } else {
91980990 5897 TransmitSetting.field.MODE = MODE_OFDM;
ec278fa2 5898 /* OFDM mode allow MCS 0~7 */
91980990
GKH
5899 if (TransmitSetting.field.MCS > MCS_7)
5900 TransmitSetting.field.MCS = MCS_7;
5901 }
5902
96b3c83d 5903 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) {
91980990 5904 pEntry->HTPhyMode.word = TransmitSetting.word;
96b3c83d
BZ
5905 DBGPRINT(RT_DEBUG_TRACE,
5906 ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5907 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE),
5908 pEntry->HTPhyMode.field.MCS));
91980990
GKH
5909 }
5910}
5911
91980990
GKH
5912/*
5913 ==========================================================================
5914 Description:
5915 dynamic tune BBP R66 to find a balance between sensibility and
5916 noise isolation
5917
5918 IRQL = DISPATCH_LEVEL
5919
5920 ==========================================================================
5921 */
62eb734b 5922void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd)
91980990 5923{
51126deb
BZ
5924 u8 OrigR66Value = 0, R66; /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */
5925 char Rssi;
91980990 5926
ec278fa2 5927 /* 2860C did not support Fase CCA, therefore can't tune */
91980990
GKH
5928 if (pAd->MACVersion == 0x28600100)
5929 return;
5930
ec278fa2
BZ
5931 /* */
5932 /* work as a STA */
5933 /* */
5934 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) /* no R66 tuning when SCANNING */
91980990
GKH
5935 return;
5936
5937 if ((pAd->OpMode == OPMODE_STA)
96b3c83d
BZ
5938 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5939 )
5940 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
ca97b838 5941#ifdef RTMP_MAC_PCI
96b3c83d 5942 && (pAd->bPCIclkOff == FALSE)
ec278fa2 5943#endif /* RTMP_MAC_PCI // */
96b3c83d 5944 ) {
91980990
GKH
5945 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5946 R66 = OrigR66Value;
5947
5948 if (pAd->Antenna.field.RxPath > 1)
96b3c83d
BZ
5949 Rssi =
5950 (pAd->StaCfg.RssiSample.AvgRssi0 +
5951 pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
91980990
GKH
5952 else
5953 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5954
ec278fa2 5955 if (pAd->LatchRfRegs.Channel <= 14) { /*BG band */
ca97b838 5956#ifdef RT30xx
ec278fa2
BZ
5957 /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */
5958 /* Otherwise, it will have some throughput side effect when low RSSI */
ca97b838 5959
96b3c83d
BZ
5960 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
5961 || IS_RT3390(pAd)) {
5962 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5963 R66 =
5964 0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20;
5965 if (OrigR66Value != R66) {
5966 RTMP_BBP_IO_WRITE8_BY_REG_ID
5967 (pAd, BBP_R66, R66);
5968 }
5969 } else {
5970 R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
5971 if (OrigR66Value != R66) {
5972 RTMP_BBP_IO_WRITE8_BY_REG_ID
5973 (pAd, BBP_R66, R66);
5974 }
59fe2d89 5975 }
96b3c83d 5976 } else
ec278fa2 5977#endif /* RT30xx // */
91980990 5978 {
96b3c83d 5979 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
91980990 5980 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
96b3c83d
BZ
5981 if (OrigR66Value != R66) {
5982 RTMP_BBP_IO_WRITE8_BY_REG_ID
5983 (pAd, BBP_R66, R66);
91980990 5984 }
96b3c83d 5985 } else {
91980990 5986 R66 = 0x2E + GET_LNA_GAIN(pAd);
96b3c83d
BZ
5987 if (OrigR66Value != R66) {
5988 RTMP_BBP_IO_WRITE8_BY_REG_ID
5989 (pAd, BBP_R66, R66);
91980990
GKH
5990 }
5991 }
5992 }
ec278fa2 5993 } else { /*A band */
96b3c83d
BZ
5994 if (pAd->CommonCfg.BBPCurrentBW == BW_20) {
5995 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5996 R66 =
5997 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 +
5998 0x10;
5999 if (OrigR66Value != R66) {
6000 RTMP_BBP_IO_WRITE8_BY_REG_ID
6001 (pAd, BBP_R66, R66);
91980990 6002 }
96b3c83d
BZ
6003 } else {
6004 R66 =
6005 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3;
6006 if (OrigR66Value != R66) {
6007 RTMP_BBP_IO_WRITE8_BY_REG_ID
6008 (pAd, BBP_R66, R66);
91980990
GKH
6009 }
6010 }
96b3c83d
BZ
6011 } else {
6012 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6013 R66 =
6014 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 +
6015 0x10;
6016 if (OrigR66Value != R66) {
6017 RTMP_BBP_IO_WRITE8_BY_REG_ID
6018 (pAd, BBP_R66, R66);
91980990 6019 }
96b3c83d
BZ
6020 } else {
6021 R66 =
6022 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3;
6023 if (OrigR66Value != R66) {
6024 RTMP_BBP_IO_WRITE8_BY_REG_ID
6025 (pAd, BBP_R66, R66);
91980990
GKH
6026 }
6027 }
6028 }
6029 }
6030
91980990
GKH
6031 }
6032}
ed291e80 6033
62eb734b 6034void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth)
91980990 6035{
51126deb 6036 u8 R66 = 0x30;
91980990 6037
ec278fa2 6038 if (pAd->LatchRfRegs.Channel <= 14) { /* BG band */
ca97b838
BZ
6039#ifdef RT30xx
6040 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6041
96b3c83d
BZ
6042 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
6043 || IS_RT3390(pAd)) {
6044 R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
ca97b838 6045 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
96b3c83d 6046 } else
ec278fa2 6047#endif /* RT30xx // */
ca97b838 6048 {
96b3c83d 6049 R66 = 0x2E + GET_LNA_GAIN(pAd);
91980990
GKH
6050 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6051 }
ec278fa2 6052 } else { /*A band */
91980990 6053 {
96b3c83d
BZ
6054 if (BandWidth == BW_20) {
6055 R66 =
51126deb 6056 (u8)(0x32 +
96b3c83d
BZ
6057 (GET_LNA_GAIN(pAd) * 5) / 3);
6058 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6059 } else {
6060 R66 =
51126deb 6061 (u8)(0x3A +
96b3c83d
BZ
6062 (GET_LNA_GAIN(pAd) * 5) / 3);
6063 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6064 }
91980990 6065 }
91980990 6066 }
91980990 6067
91980990 6068}