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