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 | ||
42 | UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; | |
43 | ||
44 | UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; | |
45 | UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac}; | |
46 | UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72}; | |
47 | UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; | |
48 | UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; | |
49 | UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04}; | |
50 | UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; | |
51 | UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c}; | |
52 | UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; | |
53 | #ifdef CONFIG_STA_SUPPORT | |
54 | #ifdef DOT11_N_SUPPORT | |
55 | UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c}; | |
56 | #endif // DOT11_N_SUPPORT // | |
57 | #endif // CONFIG_STA_SUPPORT // | |
58 | ||
59 | UCHAR RateSwitchTable[] = { | |
60 | // 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) | |
61 | 0x11, 0x00, 0, 0, 0, // Initial used item after association | |
62 | 0x00, 0x00, 0, 40, 101, | |
63 | 0x01, 0x00, 1, 40, 50, | |
64 | 0x02, 0x00, 2, 35, 45, | |
65 | 0x03, 0x00, 3, 20, 45, | |
66 | 0x04, 0x21, 0, 30, 50, | |
67 | 0x05, 0x21, 1, 20, 50, | |
68 | 0x06, 0x21, 2, 20, 50, | |
69 | 0x07, 0x21, 3, 15, 50, | |
70 | 0x08, 0x21, 4, 15, 30, | |
71 | 0x09, 0x21, 5, 10, 25, | |
72 | 0x0a, 0x21, 6, 8, 25, | |
73 | 0x0b, 0x21, 7, 8, 25, | |
74 | 0x0c, 0x20, 12, 15, 30, | |
75 | 0x0d, 0x20, 13, 8, 20, | |
76 | 0x0e, 0x20, 14, 8, 20, | |
77 | 0x0f, 0x20, 15, 8, 25, | |
78 | 0x10, 0x22, 15, 8, 25, | |
79 | 0x11, 0x00, 0, 0, 0, | |
80 | 0x12, 0x00, 0, 0, 0, | |
81 | 0x13, 0x00, 0, 0, 0, | |
82 | 0x14, 0x00, 0, 0, 0, | |
83 | 0x15, 0x00, 0, 0, 0, | |
84 | 0x16, 0x00, 0, 0, 0, | |
85 | 0x17, 0x00, 0, 0, 0, | |
86 | 0x18, 0x00, 0, 0, 0, | |
87 | 0x19, 0x00, 0, 0, 0, | |
88 | 0x1a, 0x00, 0, 0, 0, | |
89 | 0x1b, 0x00, 0, 0, 0, | |
90 | 0x1c, 0x00, 0, 0, 0, | |
91 | 0x1d, 0x00, 0, 0, 0, | |
92 | 0x1e, 0x00, 0, 0, 0, | |
93 | 0x1f, 0x00, 0, 0, 0, | |
94 | }; | |
95 | ||
96 | UCHAR RateSwitchTable11B[] = { | |
97 | // 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) | |
98 | 0x04, 0x03, 0, 0, 0, // Initial used item after association | |
99 | 0x00, 0x00, 0, 40, 101, | |
100 | 0x01, 0x00, 1, 40, 50, | |
101 | 0x02, 0x00, 2, 35, 45, | |
102 | 0x03, 0x00, 3, 20, 45, | |
103 | }; | |
104 | ||
105 | UCHAR RateSwitchTable11BG[] = { | |
106 | // 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) | |
107 | 0x0a, 0x00, 0, 0, 0, // Initial used item after association | |
108 | 0x00, 0x00, 0, 40, 101, | |
109 | 0x01, 0x00, 1, 40, 50, | |
110 | 0x02, 0x00, 2, 35, 45, | |
111 | 0x03, 0x00, 3, 20, 45, | |
112 | 0x04, 0x10, 2, 20, 35, | |
113 | 0x05, 0x10, 3, 16, 35, | |
114 | 0x06, 0x10, 4, 10, 25, | |
115 | 0x07, 0x10, 5, 16, 25, | |
116 | 0x08, 0x10, 6, 10, 25, | |
117 | 0x09, 0x10, 7, 10, 13, | |
118 | }; | |
119 | ||
120 | UCHAR RateSwitchTable11G[] = { | |
121 | // 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) | |
122 | 0x08, 0x00, 0, 0, 0, // Initial used item after association | |
123 | 0x00, 0x10, 0, 20, 101, | |
124 | 0x01, 0x10, 1, 20, 35, | |
125 | 0x02, 0x10, 2, 20, 35, | |
126 | 0x03, 0x10, 3, 16, 35, | |
127 | 0x04, 0x10, 4, 10, 25, | |
128 | 0x05, 0x10, 5, 16, 25, | |
129 | 0x06, 0x10, 6, 10, 25, | |
130 | 0x07, 0x10, 7, 10, 13, | |
131 | }; | |
132 | ||
133 | #ifdef DOT11_N_SUPPORT | |
134 | UCHAR RateSwitchTable11N1S[] = { | |
135 | // 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) | |
136 | 0x09, 0x00, 0, 0, 0, // Initial used item after association | |
137 | 0x00, 0x21, 0, 30, 101, | |
138 | 0x01, 0x21, 1, 20, 50, | |
139 | 0x02, 0x21, 2, 20, 50, | |
140 | 0x03, 0x21, 3, 15, 50, | |
141 | 0x04, 0x21, 4, 15, 30, | |
142 | 0x05, 0x21, 5, 10, 25, | |
143 | 0x06, 0x21, 6, 8, 14, | |
144 | 0x07, 0x21, 7, 8, 14, | |
145 | 0x08, 0x23, 7, 8, 14, | |
146 | }; | |
147 | ||
148 | UCHAR RateSwitchTable11N2S[] = { | |
149 | // 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) | |
150 | 0x0a, 0x00, 0, 0, 0, // Initial used item after association | |
151 | 0x00, 0x21, 0, 30, 101, | |
152 | 0x01, 0x21, 1, 20, 50, | |
153 | 0x02, 0x21, 2, 20, 50, | |
154 | 0x03, 0x21, 3, 15, 50, | |
155 | 0x04, 0x21, 4, 15, 30, | |
156 | 0x05, 0x20, 12, 15, 30, | |
157 | 0x06, 0x20, 13, 8, 20, | |
158 | 0x07, 0x20, 14, 8, 20, | |
159 | 0x08, 0x20, 15, 8, 25, | |
160 | 0x09, 0x22, 15, 8, 25, | |
161 | }; | |
162 | ||
163 | UCHAR RateSwitchTable11N3S[] = { | |
164 | // 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) | |
165 | 0x0a, 0x00, 0, 0, 0, // Initial used item after association | |
166 | 0x00, 0x21, 0, 30, 101, | |
167 | 0x01, 0x21, 1, 20, 50, | |
168 | 0x02, 0x21, 2, 20, 50, | |
169 | 0x03, 0x21, 3, 15, 50, | |
170 | 0x04, 0x21, 4, 15, 30, | |
171 | 0x05, 0x20, 12, 15, 30, | |
172 | 0x06, 0x20, 13, 8, 20, | |
173 | 0x07, 0x20, 14, 8, 20, | |
174 | 0x08, 0x20, 15, 8, 25, | |
175 | 0x09, 0x22, 15, 8, 25, | |
176 | }; | |
177 | ||
178 | UCHAR RateSwitchTable11N2SForABand[] = { | |
179 | // 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) | |
180 | 0x0b, 0x09, 0, 0, 0, // Initial used item after association | |
181 | 0x00, 0x21, 0, 30, 101, | |
182 | 0x01, 0x21, 1, 20, 50, | |
183 | 0x02, 0x21, 2, 20, 50, | |
184 | 0x03, 0x21, 3, 15, 50, | |
185 | 0x04, 0x21, 4, 15, 30, | |
186 | 0x05, 0x21, 5, 15, 30, | |
187 | 0x06, 0x20, 12, 15, 30, | |
188 | 0x07, 0x20, 13, 8, 20, | |
189 | 0x08, 0x20, 14, 8, 20, | |
190 | 0x09, 0x20, 15, 8, 25, | |
191 | 0x0a, 0x22, 15, 8, 25, | |
192 | }; | |
193 | ||
194 | UCHAR RateSwitchTable11N3SForABand[] = { // 3*3 | |
195 | // 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) | |
196 | 0x0b, 0x09, 0, 0, 0, // Initial used item after association | |
197 | 0x00, 0x21, 0, 30, 101, | |
198 | 0x01, 0x21, 1, 20, 50, | |
199 | 0x02, 0x21, 2, 20, 50, | |
200 | 0x03, 0x21, 3, 15, 50, | |
201 | 0x04, 0x21, 4, 15, 30, | |
202 | 0x05, 0x21, 5, 15, 30, | |
203 | 0x06, 0x20, 12, 15, 30, | |
204 | 0x07, 0x20, 13, 8, 20, | |
205 | 0x08, 0x20, 14, 8, 20, | |
206 | 0x09, 0x20, 15, 8, 25, | |
207 | 0x0a, 0x22, 15, 8, 25, | |
208 | }; | |
209 | ||
210 | UCHAR RateSwitchTable11BGN1S[] = { | |
211 | // 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) | |
212 | 0x0d, 0x00, 0, 0, 0, // Initial used item after association | |
213 | 0x00, 0x00, 0, 40, 101, | |
214 | 0x01, 0x00, 1, 40, 50, | |
215 | 0x02, 0x00, 2, 35, 45, | |
216 | 0x03, 0x00, 3, 20, 45, | |
217 | 0x04, 0x21, 0, 30,101, //50 | |
218 | 0x05, 0x21, 1, 20, 50, | |
219 | 0x06, 0x21, 2, 20, 50, | |
220 | 0x07, 0x21, 3, 15, 50, | |
221 | 0x08, 0x21, 4, 15, 30, | |
222 | 0x09, 0x21, 5, 10, 25, | |
223 | 0x0a, 0x21, 6, 8, 14, | |
224 | 0x0b, 0x21, 7, 8, 14, | |
225 | 0x0c, 0x23, 7, 8, 14, | |
226 | }; | |
227 | ||
228 | UCHAR RateSwitchTable11BGN2S[] = { | |
229 | // 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) | |
230 | 0x0a, 0x00, 0, 0, 0, // Initial used item after association | |
231 | 0x00, 0x21, 0, 30,101, //50 | |
232 | 0x01, 0x21, 1, 20, 50, | |
233 | 0x02, 0x21, 2, 20, 50, | |
234 | 0x03, 0x21, 3, 15, 50, | |
235 | 0x04, 0x21, 4, 15, 30, | |
236 | 0x05, 0x20, 12, 15, 30, | |
237 | 0x06, 0x20, 13, 8, 20, | |
238 | 0x07, 0x20, 14, 8, 20, | |
239 | 0x08, 0x20, 15, 8, 25, | |
240 | 0x09, 0x22, 15, 8, 25, | |
241 | }; | |
242 | ||
243 | UCHAR RateSwitchTable11BGN3S[] = { // 3*3 | |
244 | // 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) | |
245 | 0x0a, 0x00, 0, 0, 0, // Initial used item after association | |
246 | 0x00, 0x21, 0, 30,101, //50 | |
247 | 0x01, 0x21, 1, 20, 50, | |
248 | 0x02, 0x21, 2, 20, 50, | |
249 | 0x03, 0x21, 3, 20, 50, | |
250 | 0x04, 0x21, 4, 15, 50, | |
251 | 0x05, 0x20, 20, 15, 30, | |
252 | 0x06, 0x20, 21, 8, 20, | |
253 | 0x07, 0x20, 22, 8, 20, | |
254 | 0x08, 0x20, 23, 8, 25, | |
255 | 0x09, 0x22, 23, 8, 25, | |
256 | }; | |
257 | ||
258 | UCHAR RateSwitchTable11BGN2SForABand[] = { | |
259 | // 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) | |
260 | 0x0b, 0x09, 0, 0, 0, // Initial used item after association | |
261 | 0x00, 0x21, 0, 30,101, //50 | |
262 | 0x01, 0x21, 1, 20, 50, | |
263 | 0x02, 0x21, 2, 20, 50, | |
264 | 0x03, 0x21, 3, 15, 50, | |
265 | 0x04, 0x21, 4, 15, 30, | |
266 | 0x05, 0x21, 5, 15, 30, | |
267 | 0x06, 0x20, 12, 15, 30, | |
268 | 0x07, 0x20, 13, 8, 20, | |
269 | 0x08, 0x20, 14, 8, 20, | |
270 | 0x09, 0x20, 15, 8, 25, | |
271 | 0x0a, 0x22, 15, 8, 25, | |
272 | }; | |
273 | ||
274 | UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3 | |
275 | // 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) | |
276 | 0x0c, 0x09, 0, 0, 0, // Initial used item after association | |
277 | 0x00, 0x21, 0, 30,101, //50 | |
278 | 0x01, 0x21, 1, 20, 50, | |
279 | 0x02, 0x21, 2, 20, 50, | |
280 | 0x03, 0x21, 3, 15, 50, | |
281 | 0x04, 0x21, 4, 15, 30, | |
282 | 0x05, 0x21, 5, 15, 30, | |
283 | 0x06, 0x21, 12, 15, 30, | |
284 | 0x07, 0x20, 20, 15, 30, | |
285 | 0x08, 0x20, 21, 8, 20, | |
286 | 0x09, 0x20, 22, 8, 20, | |
287 | 0x0a, 0x20, 23, 8, 25, | |
288 | 0x0b, 0x22, 23, 8, 25, | |
289 | }; | |
290 | #endif // DOT11_N_SUPPORT // | |
291 | ||
292 | PUCHAR ReasonString[] = { | |
293 | /* 0 */ "Reserved", | |
294 | /* 1 */ "Unspecified Reason", | |
295 | /* 2 */ "Previous Auth no longer valid", | |
296 | /* 3 */ "STA is leaving / has left", | |
297 | /* 4 */ "DIS-ASSOC due to inactivity", | |
298 | /* 5 */ "AP unable to hanle all associations", | |
299 | /* 6 */ "class 2 error", | |
300 | /* 7 */ "class 3 error", | |
301 | /* 8 */ "STA is leaving / has left", | |
302 | /* 9 */ "require auth before assoc/re-assoc", | |
303 | /* 10 */ "Reserved", | |
304 | /* 11 */ "Reserved", | |
305 | /* 12 */ "Reserved", | |
306 | /* 13 */ "invalid IE", | |
307 | /* 14 */ "MIC error", | |
308 | /* 15 */ "4-way handshake timeout", | |
309 | /* 16 */ "2-way (group key) handshake timeout", | |
310 | /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon", | |
311 | /* 18 */ | |
312 | }; | |
313 | ||
314 | extern UCHAR OfdmRateToRxwiMCS[]; | |
315 | // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. | |
316 | // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate | |
317 | ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */, | |
318 | 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */, | |
319 | 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */}; | |
320 | ||
321 | UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
322 | UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
323 | UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
324 | ||
325 | // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than | |
326 | // this value, then it's quaranteed capable of operating in 36 mbps TX rate in | |
327 | // clean environment. | |
328 | // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 | |
329 | CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; | |
330 | ||
331 | UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100}; | |
332 | USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200}; | |
333 | ||
334 | UCHAR SsidIe = IE_SSID; | |
335 | UCHAR SupRateIe = IE_SUPP_RATES; | |
336 | UCHAR ExtRateIe = IE_EXT_SUPP_RATES; | |
337 | #ifdef DOT11_N_SUPPORT | |
338 | UCHAR HtCapIe = IE_HT_CAP; | |
339 | UCHAR AddHtInfoIe = IE_ADD_HT; | |
340 | UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET; | |
91980990 GKH |
341 | #endif // DOT11_N_SUPPORT // |
342 | UCHAR ErpIe = IE_ERP; | |
343 | UCHAR DsIe = IE_DS_PARM; | |
344 | UCHAR TimIe = IE_TIM; | |
345 | UCHAR WpaIe = IE_WPA; | |
346 | UCHAR Wpa2Ie = IE_WPA2; | |
347 | UCHAR IbssIe = IE_IBSS_PARM; | |
348 | UCHAR Ccx2Ie = IE_CCX_V2; | |
349 | ||
350 | extern UCHAR WPA_OUI[]; | |
351 | ||
352 | UCHAR SES_OUI[] = {0x00, 0x90, 0x4c}; | |
353 | ||
354 | UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
355 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; | |
356 | ||
357 | // Reset the RFIC setting to new series | |
358 | RTMP_RF_REGS RF2850RegTable[] = { | |
359 | // ch R1 R2 R3(TX0~4=0) R4 | |
360 | {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b}, | |
361 | {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f}, | |
362 | {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b}, | |
363 | {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f}, | |
364 | {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b}, | |
365 | {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f}, | |
366 | {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b}, | |
367 | {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f}, | |
368 | {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b}, | |
369 | {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f}, | |
370 | {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b}, | |
371 | {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f}, | |
372 | {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b}, | |
373 | {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193}, | |
374 | ||
375 | // 802.11 UNI / HyperLan 2 | |
376 | {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3}, | |
377 | {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193}, | |
378 | {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183}, | |
379 | {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3}, | |
380 | {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b}, | |
381 | {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b}, | |
382 | {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193}, | |
383 | {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3}, | |
384 | {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b}, | |
385 | {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183}, | |
386 | {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193}, | |
387 | {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5. | |
388 | ||
389 | // 802.11 HyperLan 2 | |
390 | {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783}, | |
391 | ||
392 | // 2008.04.30 modified | |
393 | // The system team has AN to improve the EVM value | |
394 | // for channel 102 to 108 for the RT2850/RT2750 dual band solution. | |
395 | {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793}, | |
396 | {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3}, | |
397 | {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193}, | |
398 | ||
399 | {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183}, | |
400 | {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b}, | |
401 | {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3}, | |
402 | {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193}, | |
403 | {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183}, | |
404 | {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193}, | |
405 | {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927 | |
406 | {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3}, | |
407 | {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b}, | |
408 | {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193}, | |
409 | {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b}, | |
410 | {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183}, | |
411 | ||
412 | // 802.11 UNII | |
413 | {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7}, | |
414 | {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187}, | |
415 | {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f}, | |
416 | {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f}, | |
417 | {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7}, | |
418 | {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187}, | |
419 | {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197}, | |
420 | ||
421 | // Japan | |
422 | {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}, | |
423 | {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}, | |
424 | {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}, | |
425 | {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}, | |
426 | {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}, | |
427 | {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}, | |
428 | {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}, | |
429 | ||
430 | // still lack of MMAC(Japan) ch 34,38,42,46 | |
431 | }; | |
432 | UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); | |
433 | ||
434 | FREQUENCY_ITEM FreqItems3020[] = | |
435 | { | |
436 | /**************************************************/ | |
437 | // ISM : 2.4 to 2.483 GHz // | |
438 | /**************************************************/ | |
439 | // 11g | |
440 | /**************************************************/ | |
441 | //-CH---N-------R---K----------- | |
442 | {1, 241, 2, 2}, | |
443 | {2, 241, 2, 7}, | |
444 | {3, 242, 2, 2}, | |
445 | {4, 242, 2, 7}, | |
446 | {5, 243, 2, 2}, | |
447 | {6, 243, 2, 7}, | |
448 | {7, 244, 2, 2}, | |
449 | {8, 244, 2, 7}, | |
450 | {9, 245, 2, 2}, | |
451 | {10, 245, 2, 7}, | |
452 | {11, 246, 2, 2}, | |
453 | {12, 246, 2, 7}, | |
454 | {13, 247, 2, 2}, | |
455 | {14, 248, 2, 4}, | |
456 | }; | |
457 | #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM)) | |
458 | ||
459 | /* | |
460 | ========================================================================== | |
461 | Description: | |
462 | initialize the MLME task and its data structure (queue, spinlock, | |
463 | timer, state machines). | |
464 | ||
465 | IRQL = PASSIVE_LEVEL | |
466 | ||
467 | Return: | |
468 | always return NDIS_STATUS_SUCCESS | |
469 | ||
470 | ========================================================================== | |
471 | */ | |
472 | NDIS_STATUS MlmeInit( | |
473 | IN PRTMP_ADAPTER pAd) | |
474 | { | |
475 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | |
476 | ||
477 | DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); | |
478 | ||
479 | do | |
480 | { | |
481 | Status = MlmeQueueInit(&pAd->Mlme.Queue); | |
482 | if(Status != NDIS_STATUS_SUCCESS) | |
483 | break; | |
484 | ||
485 | pAd->Mlme.bRunning = FALSE; | |
486 | NdisAllocateSpinLock(&pAd->Mlme.TaskLock); | |
487 | ||
488 | #ifdef CONFIG_STA_SUPPORT | |
489 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
490 | { | |
491 | BssTableInit(&pAd->ScanTab); | |
492 | ||
493 | // init STA state machines | |
494 | AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc); | |
495 | AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc); | |
496 | AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc); | |
497 | SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc); | |
498 | WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc); | |
499 | AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc); | |
500 | ||
91980990 GKH |
501 | // Since we are using switch/case to implement it, the init is different from the above |
502 | // state machine init | |
503 | MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL); | |
504 | } | |
505 | #endif // CONFIG_STA_SUPPORT // | |
506 | ||
507 | ||
508 | ||
509 | ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc); | |
510 | ||
511 | // Init mlme periodic timer | |
512 | RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); | |
513 | ||
514 | // Set mlme periodic timer | |
515 | RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); | |
516 | ||
517 | // software-based RX Antenna diversity | |
518 | RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE); | |
519 | ||
520 | ||
521 | #ifdef CONFIG_STA_SUPPORT | |
91980990 GKH |
522 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) |
523 | { | |
524 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) | |
525 | { | |
526 | // only PCIe cards need these two timers | |
527 | RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE); | |
528 | RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE); | |
529 | } | |
530 | } | |
91980990 GKH |
531 | #endif // CONFIG_STA_SUPPORT // |
532 | ||
533 | } while (FALSE); | |
534 | ||
535 | DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); | |
536 | ||
537 | return Status; | |
538 | } | |
539 | ||
540 | /* | |
541 | ========================================================================== | |
542 | Description: | |
543 | main loop of the MLME | |
544 | Pre: | |
545 | Mlme has to be initialized, and there are something inside the queue | |
546 | Note: | |
547 | This function is invoked from MPSetInformation and MPReceive; | |
548 | This task guarantee only one MlmeHandler will run. | |
549 | ||
550 | IRQL = DISPATCH_LEVEL | |
551 | ||
552 | ========================================================================== | |
553 | */ | |
554 | VOID MlmeHandler( | |
555 | IN PRTMP_ADAPTER pAd) | |
556 | { | |
557 | MLME_QUEUE_ELEM *Elem = NULL; | |
91980990 GKH |
558 | |
559 | // Only accept MLME and Frame from peer side, no other (control/data) frame should | |
560 | // get into this state machine | |
561 | ||
562 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); | |
563 | if(pAd->Mlme.bRunning) | |
564 | { | |
565 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | |
566 | return; | |
567 | } | |
568 | else | |
569 | { | |
570 | pAd->Mlme.bRunning = TRUE; | |
571 | } | |
572 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | |
573 | ||
574 | while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) | |
575 | { | |
576 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || | |
577 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || | |
578 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) | |
579 | { | |
580 | DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num)); | |
581 | break; | |
582 | } | |
583 | ||
91980990 GKH |
584 | //From message type, determine which state machine I should drive |
585 | if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) | |
586 | { | |
587 | ||
588 | // if dequeue success | |
589 | switch (Elem->Machine) | |
590 | { | |
591 | // STA state machines | |
592 | #ifdef CONFIG_STA_SUPPORT | |
593 | case ASSOC_STATE_MACHINE: | |
594 | StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem); | |
595 | break; | |
596 | case AUTH_STATE_MACHINE: | |
597 | StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem); | |
598 | break; | |
599 | case AUTH_RSP_STATE_MACHINE: | |
600 | StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem); | |
601 | break; | |
602 | case SYNC_STATE_MACHINE: | |
603 | StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem); | |
604 | break; | |
605 | case MLME_CNTL_STATE_MACHINE: | |
606 | MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem); | |
607 | break; | |
608 | case WPA_PSK_STATE_MACHINE: | |
609 | StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem); | |
610 | break; | |
91980990 GKH |
611 | case AIRONET_STATE_MACHINE: |
612 | StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem); | |
613 | break; | |
91980990 GKH |
614 | #endif // CONFIG_STA_SUPPORT // |
615 | ||
616 | case ACTION_STATE_MACHINE: | |
617 | StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem); | |
618 | break; | |
619 | ||
620 | ||
621 | ||
622 | ||
623 | default: | |
624 | DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine)); | |
625 | break; | |
626 | } // end of switch | |
627 | ||
628 | // free MLME element | |
629 | Elem->Occupied = FALSE; | |
630 | Elem->MsgLen = 0; | |
631 | ||
632 | } | |
633 | else { | |
634 | DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n")); | |
635 | } | |
636 | } | |
637 | ||
638 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); | |
639 | pAd->Mlme.bRunning = FALSE; | |
640 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | |
641 | } | |
642 | ||
643 | /* | |
644 | ========================================================================== | |
645 | Description: | |
646 | Destructor of MLME (Destroy queue, state machine, spin lock and timer) | |
647 | Parameters: | |
648 | Adapter - NIC Adapter pointer | |
649 | Post: | |
650 | The MLME task will no longer work properly | |
651 | ||
652 | IRQL = PASSIVE_LEVEL | |
653 | ||
654 | ========================================================================== | |
655 | */ | |
656 | VOID MlmeHalt( | |
657 | IN PRTMP_ADAPTER pAd) | |
658 | { | |
659 | BOOLEAN Cancelled; | |
660 | ||
661 | DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); | |
662 | ||
663 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) | |
664 | { | |
665 | // disable BEACON generation and other BEACON related hardware timers | |
666 | AsicDisableSync(pAd); | |
667 | } | |
668 | ||
669 | #ifdef CONFIG_STA_SUPPORT | |
670 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
671 | { | |
91980990 GKH |
672 | // Cancel pending timers |
673 | RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); | |
674 | RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); | |
675 | RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); | |
676 | RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); | |
677 | RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); | |
678 | RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); | |
91980990 GKH |
679 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) |
680 | { | |
681 | RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); | |
682 | RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); | |
683 | } | |
91980990 GKH |
684 | } |
685 | #endif // CONFIG_STA_SUPPORT // | |
686 | ||
687 | RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); | |
688 | RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); | |
689 | ||
690 | ||
691 | ||
692 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) | |
693 | { | |
694 | // Set LED | |
695 | RTMPSetLED(pAd, LED_HALT); | |
696 | RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. | |
697 | } | |
698 | ||
699 | RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled | |
700 | ||
701 | MlmeQueueDestroy(&pAd->Mlme.Queue); | |
702 | NdisFreeSpinLock(&pAd->Mlme.TaskLock); | |
703 | ||
704 | DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); | |
705 | } | |
706 | ||
707 | VOID MlmeResetRalinkCounters( | |
708 | IN PRTMP_ADAPTER pAd) | |
709 | { | |
710 | pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt; | |
711 | // clear all OneSecxxx counters. | |
712 | pAd->RalinkCounters.OneSecBeaconSentCnt = 0; | |
713 | pAd->RalinkCounters.OneSecFalseCCACnt = 0; | |
714 | pAd->RalinkCounters.OneSecRxFcsErrCnt = 0; | |
715 | pAd->RalinkCounters.OneSecRxOkCnt = 0; | |
716 | pAd->RalinkCounters.OneSecTxFailCount = 0; | |
717 | pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0; | |
718 | pAd->RalinkCounters.OneSecTxRetryOkCount = 0; | |
719 | pAd->RalinkCounters.OneSecRxOkDataCnt = 0; | |
720 | ||
721 | // TODO: for debug only. to be removed | |
722 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0; | |
723 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0; | |
724 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0; | |
725 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0; | |
726 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0; | |
727 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0; | |
728 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0; | |
729 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0; | |
730 | pAd->RalinkCounters.OneSecTxDoneCount = 0; | |
731 | pAd->RalinkCounters.OneSecRxCount = 0; | |
732 | pAd->RalinkCounters.OneSecTxAggregationCount = 0; | |
733 | pAd->RalinkCounters.OneSecRxAggregationCount = 0; | |
734 | ||
735 | return; | |
736 | } | |
737 | ||
738 | unsigned long rx_AMSDU; | |
739 | unsigned long rx_Total; | |
740 | ||
741 | /* | |
742 | ========================================================================== | |
743 | Description: | |
744 | This routine is executed periodically to - | |
745 | 1. Decide if it's a right time to turn on PwrMgmt bit of all | |
746 | outgoiing frames | |
747 | 2. Calculate ChannelQuality based on statistics of the last | |
748 | period, so that TX rate won't toggling very frequently between a | |
749 | successful TX and a failed TX. | |
750 | 3. If the calculated ChannelQuality indicated current connection not | |
751 | healthy, then a ROAMing attempt is tried here. | |
752 | ||
753 | IRQL = DISPATCH_LEVEL | |
754 | ||
755 | ========================================================================== | |
756 | */ | |
757 | #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec | |
758 | VOID MlmePeriodicExec( | |
759 | IN PVOID SystemSpecific1, | |
760 | IN PVOID FunctionContext, | |
761 | IN PVOID SystemSpecific2, | |
762 | IN PVOID SystemSpecific3) | |
763 | { | |
764 | ULONG TxTotalCnt; | |
765 | PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; | |
766 | ||
ed291e80 AM |
767 | //Baron 2008/07/10 |
768 | //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus)); | |
769 | //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0. | |
770 | //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1. | |
771 | if(pAd->StaCfg.WepStatus<2) | |
772 | { | |
773 | pAd->StaCfg.WpaSupplicantUP = 0; | |
774 | } | |
775 | else | |
776 | { | |
777 | pAd->StaCfg.WpaSupplicantUP = 1; | |
778 | } | |
779 | ||
91980990 | 780 | #ifdef CONFIG_STA_SUPPORT |
91980990 GKH |
781 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) |
782 | { | |
783 | // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. | |
784 | // Move code to here, because following code will return when radio is off | |
ed291e80 AM |
785 | if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && |
786 | (pAd->StaCfg.bHardwareRadio == TRUE) && | |
787 | (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) && | |
91980990 | 788 | (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && |
ed291e80 | 789 | (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) |
91980990 GKH |
790 | { |
791 | UINT32 data = 0; | |
792 | ||
793 | // Read GPIO pin2 as Hardware controlled radio state | |
ed291e80 | 794 | RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); |
91980990 GKH |
795 | if (data & 0x04) |
796 | { | |
797 | pAd->StaCfg.bHwRadio = TRUE; | |
798 | } | |
799 | else | |
800 | { | |
801 | pAd->StaCfg.bHwRadio = FALSE; | |
802 | } | |
803 | if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) | |
804 | { | |
805 | pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); | |
806 | if (pAd->StaCfg.bRadio == TRUE) | |
807 | { | |
808 | MlmeRadioOn(pAd); | |
809 | // Update extra information | |
810 | pAd->ExtraInfo = EXTRA_INFO_CLEAR; | |
811 | } | |
812 | else | |
813 | { | |
814 | MlmeRadioOff(pAd); | |
815 | // Update extra information | |
816 | pAd->ExtraInfo = HW_RADIO_OFF; | |
817 | } | |
818 | } | |
819 | } | |
820 | } | |
91980990 GKH |
821 | #endif // CONFIG_STA_SUPPORT // |
822 | ||
823 | // Do nothing if the driver is starting halt state. | |
824 | // This might happen when timer already been fired before cancel timer with mlmehalt | |
825 | if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS | | |
826 | fRTMP_ADAPTER_RADIO_OFF | | |
827 | fRTMP_ADAPTER_RADIO_MEASUREMENT | | |
828 | fRTMP_ADAPTER_RESET_IN_PROGRESS)))) | |
829 | return; | |
830 | ||
ed291e80 AM |
831 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) |
832 | { | |
833 | if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE)) | |
834 | { | |
835 | // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1. | |
836 | pAd->SameRxByteCount++; | |
837 | } | |
838 | else | |
839 | pAd->SameRxByteCount = 0; | |
840 | ||
841 | // If after BBP, still not work...need to check to reset PBF&MAC. | |
842 | if (pAd->SameRxByteCount == 702) | |
843 | { | |
844 | pAd->SameRxByteCount = 0; | |
845 | AsicResetPBF(pAd); | |
846 | AsicResetMAC(pAd); | |
847 | } | |
848 | ||
849 | // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode. | |
850 | if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600))) | |
851 | { | |
852 | if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700)) | |
853 | { | |
f72c4bf5 | 854 | DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount)); |
ed291e80 AM |
855 | pAd->SameRxByteCount = 700; |
856 | AsicResetBBP(pAd); | |
857 | } | |
858 | } | |
859 | ||
860 | // Update lastReceiveByteCount. | |
861 | pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount; | |
862 | ||
863 | if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd))) | |
864 | { | |
865 | pAd->CheckDmaBusyCount = 0; | |
866 | AsicResetFromDMABusy(pAd); | |
867 | } | |
868 | } | |
869 | ||
91980990 GKH |
870 | RT28XX_MLME_PRE_SANITY_CHECK(pAd); |
871 | ||
91980990 GKH |
872 | #ifdef CONFIG_STA_SUPPORT |
873 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
874 | { | |
875 | // Do nothing if monitor mode is on | |
876 | if (MONITOR_ON(pAd)) | |
877 | return; | |
878 | ||
879 | if (pAd->Mlme.PeriodicRound & 0x1) | |
880 | { | |
881 | // This is the fix for wifi 11n extension channel overlapping test case. for 2860D | |
882 | if (((pAd->MACVersion & 0xffff) == 0x0101) && | |
883 | (STA_TGN_WIFI_ON(pAd)) && | |
884 | (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) | |
885 | ||
886 | { | |
887 | RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); | |
888 | pAd->CommonCfg.IOTestParm.bToggle = TRUE; | |
889 | } | |
890 | else if ((STA_TGN_WIFI_ON(pAd)) && | |
891 | ((pAd->MACVersion & 0xffff) == 0x0101)) | |
892 | { | |
893 | RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); | |
894 | pAd->CommonCfg.IOTestParm.bToggle = FALSE; | |
895 | } | |
896 | } | |
897 | } | |
898 | #endif // CONFIG_STA_SUPPORT // | |
899 | ||
900 | pAd->bUpdateBcnCntDone = FALSE; | |
901 | ||
902 | // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); | |
903 | pAd->Mlme.PeriodicRound ++; | |
904 | ||
905 | // execute every 500ms | |
906 | if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/) | |
907 | { | |
908 | #ifdef CONFIG_STA_SUPPORT | |
909 | // perform dynamic tx rate switching based on past TX history | |
910 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
911 | { | |
912 | if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | |
913 | ) | |
914 | && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) | |
915 | MlmeDynamicTxRateSwitching(pAd); | |
916 | } | |
917 | #endif // CONFIG_STA_SUPPORT // | |
918 | } | |
919 | ||
920 | // Normal 1 second Mlme PeriodicExec. | |
921 | if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) | |
922 | { | |
923 | pAd->Mlme.OneSecPeriodicRound ++; | |
924 | ||
91980990 GKH |
925 | if (rx_Total) |
926 | { | |
927 | ||
928 | // reset counters | |
929 | rx_AMSDU = 0; | |
930 | rx_Total = 0; | |
931 | } | |
932 | ||
933 | // Media status changed, report to NDIS | |
934 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) | |
935 | { | |
936 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); | |
937 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
938 | { | |
939 | pAd->IndicateMediaState = NdisMediaStateConnected; | |
940 | RTMP_IndicateMediaState(pAd); | |
941 | ||
942 | } | |
943 | else | |
944 | { | |
945 | pAd->IndicateMediaState = NdisMediaStateDisconnected; | |
946 | RTMP_IndicateMediaState(pAd); | |
947 | } | |
948 | } | |
949 | ||
950 | NdisGetSystemUpTime(&pAd->Mlme.Now32); | |
951 | ||
952 | // add the most up-to-date h/w raw counters into software variable, so that | |
953 | // the dynamic tuning mechanism below are based on most up-to-date information | |
954 | NICUpdateRawCounters(pAd); | |
955 | ||
956 | ||
957 | #ifdef DOT11_N_SUPPORT | |
958 | // Need statistics after read counter. So put after NICUpdateRawCounters | |
959 | ORIBATimerTimeout(pAd); | |
960 | #endif // DOT11_N_SUPPORT // | |
961 | ||
962 | ||
963 | // The time period for checking antenna is according to traffic | |
964 | if (pAd->Mlme.bEnableAutoAntennaCheck) | |
965 | { | |
966 | TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + | |
967 | pAd->RalinkCounters.OneSecTxRetryOkCount + | |
968 | pAd->RalinkCounters.OneSecTxFailCount; | |
969 | ||
970 | if (TxTotalCnt > 50) | |
971 | { | |
972 | if (pAd->Mlme.OneSecPeriodicRound % 10 == 0) | |
973 | { | |
974 | AsicEvaluateRxAnt(pAd); | |
975 | } | |
976 | } | |
977 | else | |
978 | { | |
979 | if (pAd->Mlme.OneSecPeriodicRound % 3 == 0) | |
980 | { | |
981 | AsicEvaluateRxAnt(pAd); | |
982 | } | |
983 | } | |
984 | } | |
985 | ||
986 | #ifdef CONFIG_STA_SUPPORT | |
987 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
988 | STAMlmePeriodicExec(pAd); | |
989 | #endif // CONFIG_STA_SUPPORT // | |
990 | ||
991 | MlmeResetRalinkCounters(pAd); | |
992 | ||
993 | #ifdef CONFIG_STA_SUPPORT | |
994 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
995 | { | |
91980990 | 996 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE)) |
91980990 GKH |
997 | { |
998 | // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock | |
999 | // and sending CTS-to-self over and over. | |
1000 | // Software Patch Solution: | |
1001 | // 1. Polling debug state register 0x10F4 every one second. | |
1002 | // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. | |
1003 | // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. | |
1004 | ||
1005 | UINT32 MacReg = 0; | |
1006 | ||
1007 | RTMP_IO_READ32(pAd, 0x10F4, &MacReg); | |
1008 | if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20))) | |
1009 | { | |
1010 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); | |
1011 | RTMPusecDelay(1); | |
1012 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); | |
1013 | ||
1014 | DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n")); | |
1015 | } | |
1016 | } | |
1017 | } | |
1018 | #endif // CONFIG_STA_SUPPORT // | |
1019 | ||
1020 | RT28XX_MLME_HANDLER(pAd); | |
1021 | } | |
1022 | ||
1023 | ||
1024 | pAd->bUpdateBcnCntDone = FALSE; | |
1025 | } | |
1026 | ||
1027 | #ifdef CONFIG_STA_SUPPORT | |
1028 | VOID STAMlmePeriodicExec( | |
1029 | PRTMP_ADAPTER pAd) | |
1030 | { | |
1031 | ULONG TxTotalCnt; | |
1032 | ||
91980990 GKH |
1033 | #ifdef WPA_SUPPLICANT_SUPPORT |
1034 | if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) | |
1035 | #endif // WPA_SUPPLICANT_SUPPORT // | |
1036 | { | |
1037 | // WPA MIC error should block association attempt for 60 seconds | |
1038 | if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32)) | |
1039 | pAd->StaCfg.bBlockAssoc = FALSE; | |
1040 | } | |
1041 | ||
ed291e80 AM |
1042 | //Baron 2008/07/10 |
1043 | //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus)); | |
1044 | //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0. | |
1045 | //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1. | |
1046 | if(pAd->StaCfg.WepStatus<2) | |
1047 | { | |
1048 | pAd->StaCfg.WpaSupplicantUP = 0; | |
1049 | } | |
1050 | else | |
1051 | { | |
1052 | pAd->StaCfg.WpaSupplicantUP = 1; | |
1053 | } | |
1054 | ||
91980990 GKH |
1055 | if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent)) |
1056 | { | |
1057 | if (pAd->IndicateMediaState == NdisMediaStateConnected) | |
1058 | { | |
1059 | RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); | |
1060 | } | |
1061 | pAd->PreMediaState = pAd->IndicateMediaState; | |
1062 | } | |
1063 | ||
ed291e80 AM |
1064 | if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) && |
1065 | (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && | |
1066 | (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) && | |
1067 | (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && | |
1068 | (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) && | |
1069 | (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) | |
1070 | { | |
1071 | RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0); | |
1072 | } | |
91980990 GKH |
1073 | |
1074 | ||
1075 | ||
1076 | AsicStaBbpTuning(pAd); | |
1077 | ||
1078 | TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + | |
1079 | pAd->RalinkCounters.OneSecTxRetryOkCount + | |
1080 | pAd->RalinkCounters.OneSecTxFailCount; | |
1081 | ||
1082 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
1083 | { | |
1084 | // update channel quality for Roaming and UI LinkQuality display | |
1085 | MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32); | |
1086 | } | |
1087 | ||
1088 | // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if | |
1089 | // Radio is currently in noisy environment | |
1090 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | |
1091 | AsicAdjustTxPower(pAd); | |
1092 | ||
1093 | if (INFRA_ON(pAd)) | |
1094 | { | |
91980990 GKH |
1095 | // Is PSM bit consistent with user power management policy? |
1096 | // This is the only place that will set PSM bit ON. | |
1097 | if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | |
1098 | MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); | |
1099 | ||
1100 | pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; | |
1101 | ||
1102 | if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) && | |
1103 | (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && | |
1104 | ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600))) | |
1105 | { | |
1106 | RTMPSetAGCInitValue(pAd, BW_20); | |
1107 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd)))); | |
1108 | } | |
1109 | ||
1110 | { | |
1111 | if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) | |
1112 | { | |
1113 | // When APSD is enabled, the period changes as 20 sec | |
1114 | if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) | |
1115 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); | |
1116 | } | |
1117 | else | |
1118 | { | |
1119 | // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) | |
1120 | if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) | |
1121 | { | |
1122 | if (pAd->CommonCfg.bWmmCapable) | |
1123 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); | |
1124 | else | |
1125 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); | |
1126 | } | |
1127 | } | |
1128 | } | |
1129 | ||
1130 | if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) | |
1131 | { | |
1132 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); | |
1133 | pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE; | |
1134 | pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime; | |
1135 | ||
1136 | // Lost AP, send disconnect & link down event | |
1137 | LinkDown(pAd, FALSE); | |
1138 | ||
1139 | #ifdef WPA_SUPPLICANT_SUPPORT | |
1140 | #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT | |
1141 | if (pAd->StaCfg.WpaSupplicantUP) | |
1142 | { | |
1143 | union iwreq_data wrqu; | |
1144 | //send disassociate event to wpa_supplicant | |
1145 | memset(&wrqu, 0, sizeof(wrqu)); | |
1146 | wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; | |
1147 | wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); | |
1148 | } | |
1149 | #endif // NATIVE_WPA_SUPPLICANT_SUPPORT // | |
1150 | #endif // WPA_SUPPLICANT_SUPPORT // | |
1151 | ||
1152 | #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT | |
1153 | { | |
1154 | union iwreq_data wrqu; | |
1155 | memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); | |
1156 | wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); | |
1157 | } | |
1158 | #endif // NATIVE_WPA_SUPPLICANT_SUPPORT // | |
1159 | ||
1160 | MlmeAutoReconnectLastSSID(pAd); | |
1161 | } | |
1162 | else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) | |
1163 | { | |
1164 | pAd->RalinkCounters.BadCQIAutoRecoveryCount ++; | |
1165 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); | |
1166 | MlmeAutoReconnectLastSSID(pAd); | |
1167 | } | |
1168 | ||
1169 | // Add auto seamless roaming | |
1170 | if (pAd->StaCfg.bFastRoaming) | |
1171 | { | |
1172 | SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam; | |
1173 | ||
1174 | DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam)); | |
1175 | ||
1176 | if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam) | |
1177 | { | |
1178 | MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32); | |
1179 | } | |
1180 | } | |
1181 | } | |
1182 | else if (ADHOC_ON(pAd)) | |
1183 | { | |
1184 | // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails | |
1185 | // the "TX BEACON competition" for the entire past 1 sec. | |
1186 | // So that even when ASIC's BEACONgen engine been blocked | |
1187 | // by peer's BEACON due to slower system clock, this STA still can send out | |
1188 | // minimum BEACON to tell the peer I'm alive. | |
1189 | // drawback is that this BEACON won't be well aligned at TBTT boundary. | |
1190 | // EnqueueBeaconFrame(pAd); // software send BEACON | |
1191 | ||
1192 | // if all 11b peers leave this BSS more than 5 seconds, update Tx rate, | |
1193 | // restore outgoing BEACON to support B/G-mixed mode | |
1194 | if ((pAd->CommonCfg.Channel <= 14) && | |
1195 | (pAd->CommonCfg.MaxTxRate <= RATE_11) && | |
1196 | (pAd->CommonCfg.MaxDesiredRate > RATE_11) && | |
1197 | ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32)) | |
1198 | { | |
1199 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n")); | |
1200 | NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); | |
1201 | pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen; | |
1202 | MlmeUpdateTxRates(pAd, FALSE, 0); | |
1203 | MakeIbssBeacon(pAd); // re-build BEACON frame | |
1204 | AsicEnableIbssSync(pAd); // copy to on-chip memory | |
1205 | pAd->StaCfg.AdhocBOnlyJoined = FALSE; | |
1206 | } | |
1207 | ||
1208 | #ifdef DOT11_N_SUPPORT | |
1209 | if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) | |
1210 | { | |
1211 | if ((pAd->StaCfg.AdhocBGJoined) && | |
1212 | ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32)) | |
1213 | { | |
1214 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n")); | |
1215 | pAd->StaCfg.AdhocBGJoined = FALSE; | |
1216 | } | |
1217 | ||
1218 | if ((pAd->StaCfg.Adhoc20NJoined) && | |
1219 | ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32)) | |
1220 | { | |
1221 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n")); | |
1222 | pAd->StaCfg.Adhoc20NJoined = FALSE; | |
1223 | } | |
1224 | } | |
1225 | #endif // DOT11_N_SUPPORT // | |
1226 | ||
1227 | //radar detect | |
1228 | if ((pAd->CommonCfg.Channel > 14) | |
1229 | && (pAd->CommonCfg.bIEEE80211H == 1) | |
1230 | && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) | |
1231 | { | |
1232 | RadarDetectPeriodic(pAd); | |
1233 | } | |
1234 | ||
1235 | // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState | |
1236 | // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can | |
1237 | // join later. | |
1238 | if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) && | |
1239 | OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
1240 | { | |
1241 | MLME_START_REQ_STRUCT StartReq; | |
1242 | ||
1243 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n")); | |
1244 | LinkDown(pAd, FALSE); | |
1245 | ||
1246 | StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); | |
1247 | MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); | |
1248 | pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; | |
1249 | } | |
1250 | } | |
1251 | else // no INFRA nor ADHOC connection | |
1252 | { | |
1253 | ||
1254 | if (pAd->StaCfg.bScanReqIsFromWebUI && | |
1255 | ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32)) | |
1256 | goto SKIP_AUTO_SCAN_CONN; | |
1257 | else | |
1258 | pAd->StaCfg.bScanReqIsFromWebUI = FALSE; | |
1259 | ||
1260 | if ((pAd->StaCfg.bAutoReconnect == TRUE) | |
1261 | && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) | |
1262 | && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) | |
1263 | { | |
1264 | if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) | |
1265 | { | |
1266 | MLME_SCAN_REQ_STRUCT ScanReq; | |
1267 | ||
1268 | if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) | |
1269 | { | |
1270 | DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid)); | |
1271 | ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); | |
1272 | MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); | |
1273 | pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; | |
1274 | // Reset Missed scan number | |
1275 | pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; | |
1276 | } | |
1277 | else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room | |
1278 | MlmeAutoReconnectLastSSID(pAd); | |
1279 | } | |
1280 | else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) | |
1281 | { | |
1282 | if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) | |
1283 | { | |
1284 | MlmeAutoScan(pAd); | |
1285 | pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; | |
1286 | } | |
1287 | else | |
1288 | { | |
91980990 GKH |
1289 | MlmeAutoReconnectLastSSID(pAd); |
1290 | } | |
1291 | } | |
1292 | } | |
1293 | } | |
1294 | ||
1295 | SKIP_AUTO_SCAN_CONN: | |
1296 | ||
1297 | #ifdef DOT11_N_SUPPORT | |
1298 | if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE)) | |
1299 | { | |
1300 | pAd->MacTab.fAnyBASession = TRUE; | |
1301 | AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE); | |
1302 | } | |
1303 | else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE)) | |
1304 | { | |
1305 | pAd->MacTab.fAnyBASession = FALSE; | |
1306 | AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); | |
1307 | } | |
1308 | #endif // DOT11_N_SUPPORT // | |
1309 | ||
91980990 GKH |
1310 | return; |
1311 | } | |
1312 | ||
1313 | // Link down report | |
1314 | VOID LinkDownExec( | |
1315 | IN PVOID SystemSpecific1, | |
1316 | IN PVOID FunctionContext, | |
1317 | IN PVOID SystemSpecific2, | |
1318 | IN PVOID SystemSpecific3) | |
1319 | { | |
1320 | ||
1321 | RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; | |
1322 | ||
1323 | pAd->IndicateMediaState = NdisMediaStateDisconnected; | |
1324 | RTMP_IndicateMediaState(pAd); | |
1325 | pAd->ExtraInfo = GENERAL_LINK_DOWN; | |
1326 | } | |
1327 | ||
1328 | // IRQL = DISPATCH_LEVEL | |
1329 | VOID MlmeAutoScan( | |
1330 | IN PRTMP_ADAPTER pAd) | |
1331 | { | |
1332 | // check CntlMachine.CurrState to avoid collision with NDIS SetOID request | |
1333 | if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) | |
1334 | { | |
1335 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n")); | |
1336 | MlmeEnqueue(pAd, | |
1337 | MLME_CNTL_STATE_MACHINE, | |
1338 | OID_802_11_BSSID_LIST_SCAN, | |
1339 | 0, | |
1340 | NULL); | |
1341 | RT28XX_MLME_HANDLER(pAd); | |
1342 | } | |
1343 | } | |
1344 | ||
1345 | // IRQL = DISPATCH_LEVEL | |
1346 | VOID MlmeAutoReconnectLastSSID( | |
1347 | IN PRTMP_ADAPTER pAd) | |
1348 | { | |
1349 | ||
1350 | ||
1351 | // check CntlMachine.CurrState to avoid collision with NDIS SetOID request | |
1352 | if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && | |
1353 | (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) | |
1354 | { | |
1355 | NDIS_802_11_SSID OidSsid; | |
1356 | OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; | |
1357 | NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); | |
1358 | ||
1359 | DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen)); | |
1360 | MlmeEnqueue(pAd, | |
1361 | MLME_CNTL_STATE_MACHINE, | |
1362 | OID_802_11_SSID, | |
1363 | sizeof(NDIS_802_11_SSID), | |
1364 | &OidSsid); | |
1365 | RT28XX_MLME_HANDLER(pAd); | |
1366 | } | |
1367 | } | |
1368 | #endif // CONFIG_STA_SUPPORT // | |
1369 | ||
1370 | /* | |
1371 | ========================================================================== | |
1372 | Validate SSID for connection try and rescan purpose | |
1373 | Valid SSID will have visible chars only. | |
1374 | The valid length is from 0 to 32. | |
1375 | IRQL = DISPATCH_LEVEL | |
1376 | ========================================================================== | |
1377 | */ | |
1378 | BOOLEAN MlmeValidateSSID( | |
1379 | IN PUCHAR pSsid, | |
1380 | IN UCHAR SsidLen) | |
1381 | { | |
1382 | int index; | |
1383 | ||
1384 | if (SsidLen > MAX_LEN_OF_SSID) | |
1385 | return (FALSE); | |
1386 | ||
1387 | // Check each character value | |
1388 | for (index = 0; index < SsidLen; index++) | |
1389 | { | |
1390 | if (pSsid[index] < 0x20) | |
1391 | return (FALSE); | |
1392 | } | |
1393 | ||
1394 | // All checked | |
1395 | return (TRUE); | |
1396 | } | |
1397 | ||
1398 | VOID MlmeSelectTxRateTable( | |
1399 | IN PRTMP_ADAPTER pAd, | |
1400 | IN PMAC_TABLE_ENTRY pEntry, | |
1401 | IN PUCHAR *ppTable, | |
1402 | IN PUCHAR pTableSize, | |
1403 | IN PUCHAR pInitTxRateIdx) | |
1404 | { | |
1405 | do | |
1406 | { | |
1407 | // decide the rate table for tuning | |
1408 | if (pAd->CommonCfg.TxRateTableSize > 0) | |
1409 | { | |
1410 | *ppTable = RateSwitchTable; | |
1411 | *pTableSize = RateSwitchTable[0]; | |
1412 | *pInitTxRateIdx = RateSwitchTable[1]; | |
1413 | ||
1414 | break; | |
1415 | } | |
1416 | ||
1417 | #ifdef CONFIG_STA_SUPPORT | |
1418 | if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) | |
1419 | { | |
1420 | #ifdef DOT11_N_SUPPORT | |
1421 | if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && | |
1422 | !pAd->StaCfg.AdhocBOnlyJoined && | |
1423 | !pAd->StaCfg.AdhocBGJoined && | |
1424 | (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && | |
1425 | ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) | |
1426 | {// 11N 1S Adhoc | |
1427 | *ppTable = RateSwitchTable11N1S; | |
1428 | *pTableSize = RateSwitchTable11N1S[0]; | |
1429 | *pInitTxRateIdx = RateSwitchTable11N1S[1]; | |
1430 | ||
1431 | } | |
1432 | else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && | |
1433 | !pAd->StaCfg.AdhocBOnlyJoined && | |
1434 | !pAd->StaCfg.AdhocBGJoined && | |
1435 | (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && | |
1436 | (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && | |
1437 | (pAd->Antenna.field.TxPath == 2)) | |
1438 | {// 11N 2S Adhoc | |
1439 | if (pAd->LatchRfRegs.Channel <= 14) | |
1440 | { | |
1441 | *ppTable = RateSwitchTable11N2S; | |
1442 | *pTableSize = RateSwitchTable11N2S[0]; | |
1443 | *pInitTxRateIdx = RateSwitchTable11N2S[1]; | |
1444 | } | |
1445 | else | |
1446 | { | |
1447 | *ppTable = RateSwitchTable11N2SForABand; | |
1448 | *pTableSize = RateSwitchTable11N2SForABand[0]; | |
1449 | *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; | |
1450 | } | |
1451 | ||
1452 | } | |
1453 | else | |
1454 | #endif // DOT11_N_SUPPORT // | |
1455 | if (pAd->CommonCfg.PhyMode == PHY_11B) | |
1456 | { | |
1457 | *ppTable = RateSwitchTable11B; | |
1458 | *pTableSize = RateSwitchTable11B[0]; | |
1459 | *pInitTxRateIdx = RateSwitchTable11B[1]; | |
1460 | ||
1461 | } | |
1462 | else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE)) | |
1463 | { | |
1464 | // USe B Table when Only b-only Station in my IBSS . | |
1465 | *ppTable = RateSwitchTable11B; | |
1466 | *pTableSize = RateSwitchTable11B[0]; | |
1467 | *pInitTxRateIdx = RateSwitchTable11B[1]; | |
1468 | ||
1469 | } | |
1470 | else if (pAd->LatchRfRegs.Channel <= 14) | |
1471 | { | |
1472 | *ppTable = RateSwitchTable11BG; | |
1473 | *pTableSize = RateSwitchTable11BG[0]; | |
1474 | *pInitTxRateIdx = RateSwitchTable11BG[1]; | |
1475 | ||
1476 | } | |
1477 | else | |
1478 | { | |
1479 | *ppTable = RateSwitchTable11G; | |
1480 | *pTableSize = RateSwitchTable11G[0]; | |
1481 | *pInitTxRateIdx = RateSwitchTable11G[1]; | |
1482 | ||
1483 | } | |
1484 | break; | |
1485 | } | |
1486 | #endif // CONFIG_STA_SUPPORT // | |
1487 | ||
1488 | #ifdef DOT11_N_SUPPORT | |
1489 | if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && | |
1490 | ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) | |
1491 | {// 11BGN 1S AP | |
1492 | *ppTable = RateSwitchTable11BGN1S; | |
1493 | *pTableSize = RateSwitchTable11BGN1S[0]; | |
1494 | *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; | |
1495 | ||
1496 | break; | |
1497 | } | |
1498 | ||
1499 | if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && | |
1500 | (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) | |
1501 | {// 11BGN 2S AP | |
1502 | if (pAd->LatchRfRegs.Channel <= 14) | |
1503 | { | |
1504 | *ppTable = RateSwitchTable11BGN2S; | |
1505 | *pTableSize = RateSwitchTable11BGN2S[0]; | |
1506 | *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; | |
1507 | ||
1508 | } | |
1509 | else | |
1510 | { | |
1511 | *ppTable = RateSwitchTable11BGN2SForABand; | |
1512 | *pTableSize = RateSwitchTable11BGN2SForABand[0]; | |
1513 | *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1]; | |
1514 | ||
1515 | } | |
1516 | break; | |
1517 | } | |
1518 | ||
1519 | if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) | |
1520 | {// 11N 1S AP | |
1521 | *ppTable = RateSwitchTable11N1S; | |
1522 | *pTableSize = RateSwitchTable11N1S[0]; | |
1523 | *pInitTxRateIdx = RateSwitchTable11N1S[1]; | |
1524 | ||
1525 | break; | |
1526 | } | |
1527 | ||
1528 | if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) | |
1529 | {// 11N 2S AP | |
1530 | if (pAd->LatchRfRegs.Channel <= 14) | |
1531 | { | |
1532 | *ppTable = RateSwitchTable11N2S; | |
1533 | *pTableSize = RateSwitchTable11N2S[0]; | |
1534 | *pInitTxRateIdx = RateSwitchTable11N2S[1]; | |
1535 | } | |
1536 | else | |
1537 | { | |
1538 | *ppTable = RateSwitchTable11N2SForABand; | |
1539 | *pTableSize = RateSwitchTable11N2SForABand[0]; | |
1540 | *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; | |
1541 | } | |
1542 | ||
1543 | break; | |
1544 | } | |
1545 | #endif // DOT11_N_SUPPORT // | |
1546 | //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) | |
1547 | if ((pEntry->RateLen == 4) | |
1548 | #ifdef DOT11_N_SUPPORT | |
1549 | && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) | |
1550 | #endif // DOT11_N_SUPPORT // | |
1551 | ) | |
1552 | {// B only AP | |
1553 | *ppTable = RateSwitchTable11B; | |
1554 | *pTableSize = RateSwitchTable11B[0]; | |
1555 | *pInitTxRateIdx = RateSwitchTable11B[1]; | |
1556 | ||
1557 | break; | |
1558 | } | |
1559 | ||
1560 | //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) | |
1561 | if ((pEntry->RateLen > 8) | |
1562 | #ifdef DOT11_N_SUPPORT | |
1563 | && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) | |
1564 | #endif // DOT11_N_SUPPORT // | |
1565 | ) | |
1566 | {// B/G mixed AP | |
1567 | *ppTable = RateSwitchTable11BG; | |
1568 | *pTableSize = RateSwitchTable11BG[0]; | |
1569 | *pInitTxRateIdx = RateSwitchTable11BG[1]; | |
1570 | ||
1571 | break; | |
1572 | } | |
1573 | ||
1574 | //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) | |
1575 | if ((pEntry->RateLen == 8) | |
1576 | #ifdef DOT11_N_SUPPORT | |
1577 | && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) | |
1578 | #endif // DOT11_N_SUPPORT // | |
1579 | ) | |
1580 | {// G only AP | |
1581 | *ppTable = RateSwitchTable11G; | |
1582 | *pTableSize = RateSwitchTable11G[0]; | |
1583 | *pInitTxRateIdx = RateSwitchTable11G[1]; | |
1584 | ||
1585 | break; | |
1586 | } | |
1587 | #ifdef DOT11_N_SUPPORT | |
1588 | #endif // DOT11_N_SUPPORT // | |
1589 | ||
1590 | #ifdef CONFIG_STA_SUPPORT | |
1591 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1592 | { | |
1593 | #ifdef DOT11_N_SUPPORT | |
1594 | //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) | |
1595 | if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) | |
1596 | #endif // DOT11_N_SUPPORT // | |
1597 | { // Legacy mode | |
1598 | if (pAd->CommonCfg.MaxTxRate <= RATE_11) | |
1599 | { | |
1600 | *ppTable = RateSwitchTable11B; | |
1601 | *pTableSize = RateSwitchTable11B[0]; | |
1602 | *pInitTxRateIdx = RateSwitchTable11B[1]; | |
1603 | } | |
1604 | else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11)) | |
1605 | { | |
1606 | *ppTable = RateSwitchTable11G; | |
1607 | *pTableSize = RateSwitchTable11G[0]; | |
1608 | *pInitTxRateIdx = RateSwitchTable11G[1]; | |
1609 | ||
1610 | } | |
1611 | else | |
1612 | { | |
1613 | *ppTable = RateSwitchTable11BG; | |
1614 | *pTableSize = RateSwitchTable11BG[0]; | |
1615 | *pInitTxRateIdx = RateSwitchTable11BG[1]; | |
1616 | } | |
1617 | break; | |
1618 | } | |
1619 | #ifdef DOT11_N_SUPPORT | |
1620 | if (pAd->LatchRfRegs.Channel <= 14) | |
1621 | { | |
1622 | if (pAd->CommonCfg.TxStream == 1) | |
1623 | { | |
1624 | *ppTable = RateSwitchTable11N1S; | |
1625 | *pTableSize = RateSwitchTable11N1S[0]; | |
1626 | *pInitTxRateIdx = RateSwitchTable11N1S[1]; | |
1627 | DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); | |
1628 | } | |
1629 | else | |
1630 | { | |
1631 | *ppTable = RateSwitchTable11N2S; | |
1632 | *pTableSize = RateSwitchTable11N2S[0]; | |
1633 | *pInitTxRateIdx = RateSwitchTable11N2S[1]; | |
1634 | DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); | |
1635 | } | |
1636 | } | |
1637 | else | |
1638 | { | |
1639 | if (pAd->CommonCfg.TxStream == 1) | |
1640 | { | |
1641 | *ppTable = RateSwitchTable11N1S; | |
1642 | *pTableSize = RateSwitchTable11N1S[0]; | |
1643 | *pInitTxRateIdx = RateSwitchTable11N1S[1]; | |
1644 | DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); | |
1645 | } | |
1646 | else | |
1647 | { | |
1648 | *ppTable = RateSwitchTable11N2SForABand; | |
1649 | *pTableSize = RateSwitchTable11N2SForABand[0]; | |
1650 | *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; | |
1651 | DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); | |
1652 | } | |
1653 | } | |
1654 | #endif // DOT11_N_SUPPORT // | |
1655 | DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", | |
1656 | pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1])); | |
1657 | } | |
1658 | #endif // CONFIG_STA_SUPPORT // | |
1659 | } while(FALSE); | |
1660 | } | |
1661 | ||
1662 | #ifdef CONFIG_STA_SUPPORT | |
1663 | /* | |
1664 | ========================================================================== | |
1665 | Description: | |
1666 | This routine checks if there're other APs out there capable for | |
1667 | roaming. Caller should call this routine only when Link up in INFRA mode | |
1668 | and channel quality is below CQI_GOOD_THRESHOLD. | |
1669 | ||
1670 | IRQL = DISPATCH_LEVEL | |
1671 | ||
1672 | Output: | |
1673 | ========================================================================== | |
1674 | */ | |
1675 | VOID MlmeCheckForRoaming( | |
1676 | IN PRTMP_ADAPTER pAd, | |
1677 | IN ULONG Now32) | |
1678 | { | |
1679 | USHORT i; | |
1680 | BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; | |
1681 | BSS_ENTRY *pBss; | |
1682 | ||
1683 | DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); | |
1684 | // put all roaming candidates into RoamTab, and sort in RSSI order | |
1685 | BssTableInit(pRoamTab); | |
1686 | for (i = 0; i < pAd->ScanTab.BssNr; i++) | |
1687 | { | |
1688 | pBss = &pAd->ScanTab.BssEntry[i]; | |
1689 | ||
1690 | if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32) | |
1691 | continue; // AP disappear | |
1692 | if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) | |
1693 | continue; // RSSI too weak. forget it. | |
1694 | if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) | |
1695 | continue; // skip current AP | |
1696 | if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) | |
1697 | continue; // only AP with stronger RSSI is eligible for roaming | |
1698 | ||
1699 | // AP passing all above rules is put into roaming candidate table | |
1700 | NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); | |
1701 | pRoamTab->BssNr += 1; | |
1702 | } | |
1703 | ||
1704 | if (pRoamTab->BssNr > 0) | |
1705 | { | |
1706 | // check CntlMachine.CurrState to avoid collision with NDIS SetOID request | |
1707 | if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) | |
1708 | { | |
1709 | pAd->RalinkCounters.PoorCQIRoamingCount ++; | |
1710 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); | |
1711 | MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); | |
1712 | RT28XX_MLME_HANDLER(pAd); | |
1713 | } | |
1714 | } | |
1715 | DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr)); | |
1716 | } | |
1717 | ||
1718 | /* | |
1719 | ========================================================================== | |
1720 | Description: | |
1721 | This routine checks if there're other APs out there capable for | |
1722 | roaming. Caller should call this routine only when link up in INFRA mode | |
1723 | and channel quality is below CQI_GOOD_THRESHOLD. | |
1724 | ||
1725 | IRQL = DISPATCH_LEVEL | |
1726 | ||
1727 | Output: | |
1728 | ========================================================================== | |
1729 | */ | |
1730 | VOID MlmeCheckForFastRoaming( | |
1731 | IN PRTMP_ADAPTER pAd, | |
1732 | IN ULONG Now) | |
1733 | { | |
1734 | USHORT i; | |
1735 | BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; | |
1736 | BSS_ENTRY *pBss; | |
1737 | ||
1738 | DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); | |
1739 | // put all roaming candidates into RoamTab, and sort in RSSI order | |
1740 | BssTableInit(pRoamTab); | |
1741 | for (i = 0; i < pAd->ScanTab.BssNr; i++) | |
1742 | { | |
1743 | pBss = &pAd->ScanTab.BssEntry[i]; | |
1744 | ||
1745 | if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel)) | |
1746 | continue; // RSSI too weak. forget it. | |
1747 | if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) | |
1748 | continue; // skip current AP | |
1749 | if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) | |
1750 | continue; // skip different SSID | |
1751 | if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) | |
1752 | continue; // skip AP without better RSSI | |
1753 | ||
1754 | DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi)); | |
1755 | // AP passing all above rules is put into roaming candidate table | |
1756 | NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); | |
1757 | pRoamTab->BssNr += 1; | |
1758 | } | |
1759 | ||
1760 | if (pRoamTab->BssNr > 0) | |
1761 | { | |
1762 | // check CntlMachine.CurrState to avoid collision with NDIS SetOID request | |
1763 | if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) | |
1764 | { | |
1765 | pAd->RalinkCounters.PoorCQIRoamingCount ++; | |
1766 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); | |
1767 | MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); | |
1768 | RT28XX_MLME_HANDLER(pAd); | |
1769 | } | |
1770 | } | |
1771 | // Maybe site survey required | |
1772 | else | |
1773 | { | |
1774 | if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now) | |
1775 | { | |
1776 | // check CntlMachine.CurrState to avoid collision with NDIS SetOID request | |
1777 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n")); | |
1778 | pAd->StaCfg.ScanCnt = 2; | |
1779 | pAd->StaCfg.LastScanTime = Now; | |
1780 | MlmeAutoScan(pAd); | |
1781 | } | |
1782 | } | |
1783 | ||
1784 | DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); | |
1785 | } | |
1786 | ||
1787 | /* | |
1788 | ========================================================================== | |
1789 | Description: | |
1790 | This routine calculates TxPER, RxPER of the past N-sec period. And | |
1791 | according to the calculation result, ChannelQuality is calculated here | |
1792 | to decide if current AP is still doing the job. | |
1793 | ||
1794 | If ChannelQuality is not good, a ROAMing attempt may be tried later. | |
1795 | Output: | |
1796 | StaCfg.ChannelQuality - 0..100 | |
1797 | ||
1798 | IRQL = DISPATCH_LEVEL | |
1799 | ||
1800 | NOTE: This routine decide channle quality based on RX CRC error ratio. | |
1801 | Caller should make sure a function call to NICUpdateRawCounters(pAd) | |
1802 | is performed right before this routine, so that this routine can decide | |
1803 | channel quality based on the most up-to-date information | |
1804 | ========================================================================== | |
1805 | */ | |
1806 | VOID MlmeCalculateChannelQuality( | |
1807 | IN PRTMP_ADAPTER pAd, | |
1808 | IN ULONG Now32) | |
1809 | { | |
1810 | ULONG TxOkCnt, TxCnt, TxPER, TxPRR; | |
1811 | ULONG RxCnt, RxPER; | |
1812 | UCHAR NorRssi; | |
1813 | CHAR MaxRssi; | |
1814 | ULONG BeaconLostTime = BEACON_LOST_TIME; | |
1815 | ||
91980990 GKH |
1816 | MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); |
1817 | ||
1818 | // | |
1819 | // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics | |
1820 | // | |
1821 | TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount; | |
1822 | TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount; | |
1823 | if (TxCnt < 5) | |
1824 | { | |
1825 | TxPER = 0; | |
1826 | TxPRR = 0; | |
1827 | } | |
1828 | else | |
1829 | { | |
1830 | TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt; | |
1831 | TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt; | |
1832 | } | |
1833 | ||
1834 | // | |
1835 | // calculate RX PER - don't take RxPER into consideration if too few sample | |
1836 | // | |
1837 | RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt; | |
1838 | if (RxCnt < 5) | |
1839 | RxPER = 0; | |
1840 | else | |
1841 | RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt; | |
1842 | ||
1843 | // | |
1844 | // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER | |
1845 | // | |
1846 | if (INFRA_ON(pAd) && | |
1847 | (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic | |
1848 | (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32)) | |
1849 | { | |
1850 | DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt)); | |
1851 | pAd->Mlme.ChannelQuality = 0; | |
1852 | } | |
1853 | else | |
1854 | { | |
1855 | // Normalize Rssi | |
1856 | if (MaxRssi > -40) | |
1857 | NorRssi = 100; | |
1858 | else if (MaxRssi < -90) | |
1859 | NorRssi = 0; | |
1860 | else | |
1861 | NorRssi = (MaxRssi + 90) * 2; | |
1862 | ||
1863 | // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) | |
1864 | pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi + | |
1865 | TX_WEIGHTING * (100 - TxPRR) + | |
1866 | RX_WEIGHTING* (100 - RxPER)) / 100; | |
1867 | if (pAd->Mlme.ChannelQuality >= 100) | |
1868 | pAd->Mlme.ChannelQuality = 100; | |
1869 | } | |
1870 | ||
1871 | } | |
1872 | ||
1873 | VOID MlmeSetTxRate( | |
1874 | IN PRTMP_ADAPTER pAd, | |
1875 | IN PMAC_TABLE_ENTRY pEntry, | |
1876 | IN PRTMP_TX_RATE_SWITCH pTxRate) | |
1877 | { | |
1878 | UCHAR MaxMode = MODE_OFDM; | |
1879 | ||
1880 | #ifdef DOT11_N_SUPPORT | |
1881 | MaxMode = MODE_HTGREENFIELD; | |
1882 | ||
1883 | if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2)) | |
1884 | pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; | |
1885 | else | |
1886 | #endif // DOT11_N_SUPPORT // | |
1887 | pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; | |
1888 | ||
1889 | if (pTxRate->CurrMCS < MCS_AUTO) | |
1890 | pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; | |
1891 | ||
1892 | if (pAd->StaCfg.HTPhyMode.field.MCS > 7) | |
1893 | pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; | |
1894 | ||
1895 | if (ADHOC_ON(pAd)) | |
1896 | { | |
1897 | // If peer adhoc is b-only mode, we can't send 11g rate. | |
1898 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | |
1899 | pEntry->HTPhyMode.field.STBC = STBC_NONE; | |
1900 | ||
1901 | // | |
1902 | // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary | |
1903 | // | |
1904 | pEntry->HTPhyMode.field.MODE = pTxRate->Mode; | |
1905 | pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; | |
1906 | pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; | |
1907 | ||
1908 | // Patch speed error in status page | |
1909 | pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; | |
1910 | } | |
1911 | else | |
1912 | { | |
1913 | if (pTxRate->Mode <= MaxMode) | |
1914 | pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; | |
1915 | ||
1916 | #ifdef DOT11_N_SUPPORT | |
1917 | if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) | |
1918 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; | |
1919 | else | |
1920 | #endif // DOT11_N_SUPPORT // | |
1921 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | |
1922 | ||
1923 | #ifdef DOT11_N_SUPPORT | |
1924 | // Reexam each bandwidth's SGI support. | |
1925 | if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) | |
1926 | { | |
1927 | if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE))) | |
1928 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | |
1929 | if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) | |
1930 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | |
1931 | } | |
1932 | ||
1933 | // Turn RTS/CTS rate to 6Mbps. | |
1934 | if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) | |
1935 | { | |
1936 | pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; | |
1937 | if (pAd->MacTab.fAnyBASession) | |
1938 | { | |
1939 | AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); | |
1940 | } | |
1941 | else | |
1942 | { | |
1943 | AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); | |
1944 | } | |
1945 | } | |
1946 | else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) | |
1947 | { | |
1948 | pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; | |
1949 | if (pAd->MacTab.fAnyBASession) | |
1950 | { | |
1951 | AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); | |
1952 | } | |
1953 | else | |
1954 | { | |
1955 | AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); | |
1956 | } | |
1957 | } | |
1958 | else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) | |
1959 | { | |
1960 | AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); | |
1961 | ||
1962 | } | |
1963 | else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) | |
1964 | { | |
1965 | AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); | |
1966 | } | |
1967 | #endif // DOT11_N_SUPPORT // | |
1968 | ||
1969 | pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; | |
1970 | pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; | |
1971 | pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; | |
1972 | pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; | |
1973 | #ifdef DOT11_N_SUPPORT | |
1974 | if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) && | |
1975 | pAd->WIFItestbed.bGreenField) | |
1976 | pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; | |
1977 | #endif // DOT11_N_SUPPORT // | |
1978 | } | |
1979 | ||
1980 | pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); | |
1981 | } | |
1982 | ||
1983 | /* | |
1984 | ========================================================================== | |
1985 | Description: | |
1986 | This routine calculates the acumulated TxPER of eaxh TxRate. And | |
1987 | according to the calculation result, change CommonCfg.TxRate which | |
1988 | is the stable TX Rate we expect the Radio situation could sustained. | |
1989 | ||
1990 | CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} | |
1991 | Output: | |
1992 | CommonCfg.TxRate - | |
1993 | ||
1994 | IRQL = DISPATCH_LEVEL | |
1995 | ||
1996 | NOTE: | |
1997 | call this routine every second | |
1998 | ========================================================================== | |
1999 | */ | |
2000 | VOID MlmeDynamicTxRateSwitching( | |
2001 | IN PRTMP_ADAPTER pAd) | |
2002 | { | |
2003 | UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; | |
2004 | ULONG i, AccuTxTotalCnt = 0, TxTotalCnt; | |
2005 | ULONG TxErrorRatio = 0; | |
2006 | BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE; | |
2007 | PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; | |
2008 | PUCHAR pTable; | |
2009 | UCHAR TableSize = 0; | |
2010 | UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; | |
2011 | CHAR Rssi, RssiOffset = 0; | |
2012 | TX_STA_CNT1_STRUC StaTx1; | |
2013 | TX_STA_CNT0_STRUC TxStaCnt0; | |
2014 | ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; | |
2015 | MAC_TABLE_ENTRY *pEntry; | |
2016 | ||
91980990 GKH |
2017 | /*if (pAd->Antenna.field.RxPath > 1) |
2018 | Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; | |
2019 | else | |
2020 | Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/ | |
2021 | ||
2022 | // | |
2023 | // walk through MAC table, see if need to change AP's TX rate toward each entry | |
2024 | // | |
2025 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) | |
2026 | { | |
2027 | pEntry = &pAd->MacTab.Content[i]; | |
2028 | ||
2029 | // check if this entry need to switch rate automatically | |
2030 | if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) | |
2031 | continue; | |
2032 | ||
2033 | if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) | |
2034 | { | |
2035 | Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2); | |
2036 | ||
2037 | // Update statistic counter | |
2038 | RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); | |
2039 | RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); | |
2040 | pAd->bUpdateBcnCntDone = TRUE; | |
2041 | TxRetransmit = StaTx1.field.TxRetransmit; | |
2042 | TxSuccess = StaTx1.field.TxSuccess; | |
2043 | TxFailCount = TxStaCnt0.field.TxFailCount; | |
2044 | TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; | |
2045 | ||
2046 | pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; | |
2047 | pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; | |
2048 | pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; | |
2049 | pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; | |
2050 | pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; | |
2051 | pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; | |
2052 | ||
2053 | // if no traffic in the past 1-sec period, don't change TX rate, | |
2054 | // but clear all bad history. because the bad history may affect the next | |
2055 | // Chariot throughput test | |
2056 | AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + | |
2057 | pAd->RalinkCounters.OneSecTxRetryOkCount + | |
2058 | pAd->RalinkCounters.OneSecTxFailCount; | |
2059 | ||
2060 | if (TxTotalCnt) | |
2061 | TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; | |
2062 | } | |
2063 | else | |
2064 | { | |
2065 | Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2); | |
2066 | ||
2067 | TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + | |
2068 | pEntry->OneSecTxRetryOkCount + | |
2069 | pEntry->OneSecTxFailCount; | |
2070 | ||
2071 | if (TxTotalCnt) | |
2072 | TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; | |
2073 | } | |
2074 | ||
2075 | CurrRateIdx = pEntry->CurrTxRateIndex; | |
2076 | ||
2077 | MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); | |
2078 | ||
2079 | if (CurrRateIdx >= TableSize) | |
2080 | { | |
2081 | CurrRateIdx = TableSize - 1; | |
2082 | } | |
2083 | ||
2084 | // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. | |
2085 | // So need to sync here. | |
2086 | pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; | |
2087 | if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) | |
2088 | //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) | |
2089 | ) | |
2090 | { | |
2091 | ||
2092 | // Need to sync Real Tx rate and our record. | |
2093 | // Then return for next DRS. | |
2094 | pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5]; | |
2095 | pEntry->CurrTxRateIndex = InitTxRateIdx; | |
2096 | MlmeSetTxRate(pAd, pEntry, pCurrTxRate); | |
2097 | ||
2098 | // reset all OneSecTx counters | |
2099 | RESET_ONE_SEC_TX_CNT(pEntry); | |
2100 | continue; | |
2101 | } | |
2102 | ||
2103 | // decide the next upgrade rate and downgrade rate, if any | |
2104 | if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) | |
2105 | { | |
2106 | UpRateIdx = CurrRateIdx + 1; | |
2107 | DownRateIdx = CurrRateIdx -1; | |
2108 | } | |
2109 | else if (CurrRateIdx == 0) | |
2110 | { | |
2111 | UpRateIdx = CurrRateIdx + 1; | |
2112 | DownRateIdx = CurrRateIdx; | |
2113 | } | |
2114 | else if (CurrRateIdx == (TableSize - 1)) | |
2115 | { | |
2116 | UpRateIdx = CurrRateIdx; | |
2117 | DownRateIdx = CurrRateIdx - 1; | |
2118 | } | |
2119 | ||
2120 | pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; | |
2121 | ||
2122 | #ifdef DOT11_N_SUPPORT | |
2123 | if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) | |
2124 | { | |
2125 | TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); | |
2126 | TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); | |
2127 | } | |
2128 | else | |
2129 | #endif // DOT11_N_SUPPORT // | |
2130 | { | |
2131 | TrainUp = pCurrTxRate->TrainUp; | |
2132 | TrainDown = pCurrTxRate->TrainDown; | |
2133 | } | |
2134 | ||
2135 | //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; | |
2136 | ||
2137 | // | |
2138 | // Keep the last time TxRateChangeAction status. | |
2139 | // | |
2140 | pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; | |
2141 | ||
2142 | ||
2143 | ||
2144 | // | |
2145 | // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI | |
2146 | // (criteria copied from RT2500 for Netopia case) | |
2147 | // | |
2148 | if (TxTotalCnt <= 15) | |
2149 | { | |
2150 | CHAR idx = 0; | |
2151 | UCHAR TxRateIdx; | |
2152 | //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; | |
2153 | UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0; | |
2154 | UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; | |
2155 | UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3 | |
2156 | ||
2157 | // check the existence and index of each needed MCS | |
2158 | while (idx < pTable[0]) | |
2159 | { | |
2160 | pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5]; | |
2161 | ||
2162 | if (pCurrTxRate->CurrMCS == MCS_0) | |
2163 | { | |
2164 | MCS0 = idx; | |
2165 | } | |
2166 | else if (pCurrTxRate->CurrMCS == MCS_1) | |
2167 | { | |
2168 | MCS1 = idx; | |
2169 | } | |
2170 | else if (pCurrTxRate->CurrMCS == MCS_2) | |
2171 | { | |
2172 | MCS2 = idx; | |
2173 | } | |
2174 | else if (pCurrTxRate->CurrMCS == MCS_3) | |
2175 | { | |
2176 | MCS3 = idx; | |
2177 | } | |
2178 | else if (pCurrTxRate->CurrMCS == MCS_4) | |
2179 | { | |
2180 | MCS4 = idx; | |
2181 | } | |
2182 | else if (pCurrTxRate->CurrMCS == MCS_5) | |
2183 | { | |
2184 | MCS5 = idx; | |
2185 | } | |
2186 | else if (pCurrTxRate->CurrMCS == MCS_6) | |
2187 | { | |
2188 | MCS6 = idx; | |
2189 | } | |
2190 | //else if (pCurrTxRate->CurrMCS == MCS_7) | |
2191 | else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput | |
2192 | { | |
2193 | MCS7 = idx; | |
2194 | } | |
2195 | else if (pCurrTxRate->CurrMCS == MCS_12) | |
2196 | { | |
2197 | MCS12 = idx; | |
2198 | } | |
2199 | else if (pCurrTxRate->CurrMCS == MCS_13) | |
2200 | { | |
2201 | MCS13 = idx; | |
2202 | } | |
2203 | else if (pCurrTxRate->CurrMCS == MCS_14) | |
2204 | { | |
2205 | MCS14 = idx; | |
2206 | } | |
2207 | //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate | |
2208 | 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 | |
2209 | { | |
2210 | MCS15 = idx; | |
2211 | } | |
2212 | else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3 | |
2213 | { | |
2214 | MCS20 = idx; | |
2215 | } | |
2216 | else if (pCurrTxRate->CurrMCS == MCS_21) | |
2217 | { | |
2218 | MCS21 = idx; | |
2219 | } | |
2220 | else if (pCurrTxRate->CurrMCS == MCS_22) | |
2221 | { | |
2222 | MCS22 = idx; | |
2223 | } | |
2224 | else if (pCurrTxRate->CurrMCS == MCS_23) | |
2225 | { | |
2226 | MCS23 = idx; | |
2227 | } | |
2228 | idx ++; | |
2229 | } | |
2230 | ||
2231 | if (pAd->LatchRfRegs.Channel <= 14) | |
2232 | { | |
2233 | if (pAd->NicConfig2.field.ExternalLNAForG) | |
2234 | { | |
2235 | RssiOffset = 2; | |
2236 | } | |
2237 | else | |
2238 | { | |
2239 | RssiOffset = 5; | |
2240 | } | |
2241 | } | |
2242 | else | |
2243 | { | |
2244 | if (pAd->NicConfig2.field.ExternalLNAForA) | |
2245 | { | |
2246 | RssiOffset = 5; | |
2247 | } | |
2248 | else | |
2249 | { | |
2250 | RssiOffset = 8; | |
2251 | } | |
2252 | } | |
2253 | #ifdef DOT11_N_SUPPORT | |
2254 | /*if (MCS15)*/ | |
2255 | if ((pTable == RateSwitchTable11BGN3S) || | |
2256 | (pTable == RateSwitchTable11N3S) || | |
2257 | (pTable == RateSwitchTable)) | |
2258 | {// N mode with 3 stream // 3*3 | |
2259 | if (MCS23 && (Rssi >= -70)) | |
2260 | TxRateIdx = MCS15; | |
2261 | else if (MCS22 && (Rssi >= -72)) | |
2262 | TxRateIdx = MCS14; | |
2263 | else if (MCS21 && (Rssi >= -76)) | |
2264 | TxRateIdx = MCS13; | |
2265 | else if (MCS20 && (Rssi >= -78)) | |
2266 | TxRateIdx = MCS12; | |
2267 | else if (MCS4 && (Rssi >= -82)) | |
2268 | TxRateIdx = MCS4; | |
2269 | else if (MCS3 && (Rssi >= -84)) | |
2270 | TxRateIdx = MCS3; | |
2271 | else if (MCS2 && (Rssi >= -86)) | |
2272 | TxRateIdx = MCS2; | |
2273 | else if (MCS1 && (Rssi >= -88)) | |
2274 | TxRateIdx = MCS1; | |
2275 | else | |
2276 | TxRateIdx = MCS0; | |
2277 | } | |
2278 | else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3 | |
2279 | {// N mode with 2 stream | |
2280 | if (MCS15 && (Rssi >= (-70+RssiOffset))) | |
2281 | TxRateIdx = MCS15; | |
2282 | else if (MCS14 && (Rssi >= (-72+RssiOffset))) | |
2283 | TxRateIdx = MCS14; | |
2284 | else if (MCS13 && (Rssi >= (-76+RssiOffset))) | |
2285 | TxRateIdx = MCS13; | |
2286 | else if (MCS12 && (Rssi >= (-78+RssiOffset))) | |
2287 | TxRateIdx = MCS12; | |
2288 | else if (MCS4 && (Rssi >= (-82+RssiOffset))) | |
2289 | TxRateIdx = MCS4; | |
2290 | else if (MCS3 && (Rssi >= (-84+RssiOffset))) | |
2291 | TxRateIdx = MCS3; | |
2292 | else if (MCS2 && (Rssi >= (-86+RssiOffset))) | |
2293 | TxRateIdx = MCS2; | |
2294 | else if (MCS1 && (Rssi >= (-88+RssiOffset))) | |
2295 | TxRateIdx = MCS1; | |
2296 | else | |
2297 | TxRateIdx = MCS0; | |
2298 | } | |
2299 | else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) | |
2300 | {// N mode with 1 stream | |
2301 | if (MCS7 && (Rssi > (-72+RssiOffset))) | |
2302 | TxRateIdx = MCS7; | |
2303 | else if (MCS6 && (Rssi > (-74+RssiOffset))) | |
2304 | TxRateIdx = MCS6; | |
2305 | else if (MCS5 && (Rssi > (-77+RssiOffset))) | |
2306 | TxRateIdx = MCS5; | |
2307 | else if (MCS4 && (Rssi > (-79+RssiOffset))) | |
2308 | TxRateIdx = MCS4; | |
2309 | else if (MCS3 && (Rssi > (-81+RssiOffset))) | |
2310 | TxRateIdx = MCS3; | |
2311 | else if (MCS2 && (Rssi > (-83+RssiOffset))) | |
2312 | TxRateIdx = MCS2; | |
2313 | else if (MCS1 && (Rssi > (-86+RssiOffset))) | |
2314 | TxRateIdx = MCS1; | |
2315 | else | |
2316 | TxRateIdx = MCS0; | |
2317 | } | |
2318 | else | |
2319 | #endif // DOT11_N_SUPPORT // | |
2320 | {// Legacy mode | |
2321 | if (MCS7 && (Rssi > -70)) | |
2322 | TxRateIdx = MCS7; | |
2323 | else if (MCS6 && (Rssi > -74)) | |
2324 | TxRateIdx = MCS6; | |
2325 | else if (MCS5 && (Rssi > -78)) | |
2326 | TxRateIdx = MCS5; | |
2327 | else if (MCS4 && (Rssi > -82)) | |
2328 | TxRateIdx = MCS4; | |
2329 | else if (MCS4 == 0) // for B-only mode | |
2330 | TxRateIdx = MCS3; | |
2331 | else if (MCS3 && (Rssi > -85)) | |
2332 | TxRateIdx = MCS3; | |
2333 | else if (MCS2 && (Rssi > -87)) | |
2334 | TxRateIdx = MCS2; | |
2335 | else if (MCS1 && (Rssi > -90)) | |
2336 | TxRateIdx = MCS1; | |
2337 | else | |
2338 | TxRateIdx = MCS0; | |
2339 | } | |
2340 | ||
2341 | { | |
2342 | pEntry->CurrTxRateIndex = TxRateIdx; | |
2343 | pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; | |
2344 | MlmeSetTxRate(pAd, pEntry, pNextTxRate); | |
2345 | } | |
2346 | ||
2347 | NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2348 | NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2349 | pEntry->fLastSecAccordingRSSI = TRUE; | |
2350 | // reset all OneSecTx counters | |
2351 | RESET_ONE_SEC_TX_CNT(pEntry); | |
2352 | ||
2353 | continue; | |
2354 | } | |
2355 | ||
2356 | if (pEntry->fLastSecAccordingRSSI == TRUE) | |
2357 | { | |
2358 | pEntry->fLastSecAccordingRSSI = FALSE; | |
2359 | pEntry->LastSecTxRateChangeAction = 0; | |
2360 | // reset all OneSecTx counters | |
2361 | RESET_ONE_SEC_TX_CNT(pEntry); | |
2362 | ||
2363 | continue; | |
2364 | } | |
2365 | ||
2366 | do | |
2367 | { | |
2368 | BOOLEAN bTrainUpDown = FALSE; | |
2369 | ||
2370 | pEntry->CurrTxRateStableTime ++; | |
2371 | ||
2372 | // downgrade TX quality if PER >= Rate-Down threshold | |
2373 | if (TxErrorRatio >= TrainDown) | |
2374 | { | |
2375 | bTrainUpDown = TRUE; | |
2376 | pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; | |
2377 | } | |
2378 | // upgrade TX quality if PER <= Rate-Up threshold | |
2379 | else if (TxErrorRatio <= TrainUp) | |
2380 | { | |
2381 | bTrainUpDown = TRUE; | |
2382 | bUpgradeQuality = TRUE; | |
2383 | if (pEntry->TxQuality[CurrRateIdx]) | |
2384 | pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate | |
2385 | ||
2386 | if (pEntry->TxRateUpPenalty) | |
2387 | pEntry->TxRateUpPenalty --; | |
2388 | else if (pEntry->TxQuality[UpRateIdx]) | |
2389 | pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality | |
2390 | } | |
2391 | ||
2392 | pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; | |
2393 | ||
2394 | if (bTrainUpDown) | |
2395 | { | |
2396 | // perform DRS - consider TxRate Down first, then rate up. | |
2397 | if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND)) | |
2398 | { | |
2399 | pEntry->CurrTxRateIndex = DownRateIdx; | |
2400 | } | |
2401 | else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0)) | |
2402 | { | |
2403 | pEntry->CurrTxRateIndex = UpRateIdx; | |
2404 | } | |
2405 | } | |
2406 | } while (FALSE); | |
2407 | ||
2408 | // if rate-up happen, clear all bad history of all TX rates | |
2409 | if (pEntry->CurrTxRateIndex > CurrRateIdx) | |
2410 | { | |
2411 | pEntry->CurrTxRateStableTime = 0; | |
2412 | pEntry->TxRateUpPenalty = 0; | |
2413 | pEntry->LastSecTxRateChangeAction = 1; // rate UP | |
2414 | NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2415 | NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2416 | ||
2417 | // | |
2418 | // For TxRate fast train up | |
2419 | // | |
2420 | if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) | |
2421 | { | |
2422 | RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); | |
2423 | ||
2424 | pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; | |
2425 | } | |
2426 | bTxRateChanged = TRUE; | |
2427 | } | |
2428 | // if rate-down happen, only clear DownRate's bad history | |
2429 | else if (pEntry->CurrTxRateIndex < CurrRateIdx) | |
2430 | { | |
2431 | pEntry->CurrTxRateStableTime = 0; | |
2432 | pEntry->TxRateUpPenalty = 0; // no penalty | |
2433 | pEntry->LastSecTxRateChangeAction = 2; // rate DOWN | |
2434 | pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; | |
2435 | pEntry->PER[pEntry->CurrTxRateIndex] = 0; | |
2436 | ||
2437 | // | |
2438 | // For TxRate fast train down | |
2439 | // | |
2440 | if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) | |
2441 | { | |
2442 | RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); | |
2443 | ||
2444 | pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; | |
2445 | } | |
2446 | bTxRateChanged = TRUE; | |
2447 | } | |
2448 | else | |
2449 | { | |
2450 | pEntry->LastSecTxRateChangeAction = 0; // rate no change | |
2451 | bTxRateChanged = FALSE; | |
2452 | } | |
2453 | ||
2454 | pEntry->LastTxOkCount = TxSuccess; | |
2455 | ||
2456 | // reset all OneSecTx counters | |
2457 | RESET_ONE_SEC_TX_CNT(pEntry); | |
2458 | ||
2459 | pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; | |
2460 | if (bTxRateChanged && pNextTxRate) | |
2461 | { | |
2462 | MlmeSetTxRate(pAd, pEntry, pNextTxRate); | |
2463 | } | |
2464 | } | |
2465 | } | |
2466 | ||
2467 | /* | |
2468 | ======================================================================== | |
2469 | Routine Description: | |
2470 | Station side, Auto TxRate faster train up timer call back function. | |
2471 | ||
2472 | Arguments: | |
2473 | SystemSpecific1 - Not used. | |
2474 | FunctionContext - Pointer to our Adapter context. | |
2475 | SystemSpecific2 - Not used. | |
2476 | SystemSpecific3 - Not used. | |
2477 | ||
2478 | Return Value: | |
2479 | None | |
2480 | ||
2481 | ======================================================================== | |
2482 | */ | |
2483 | VOID StaQuickResponeForRateUpExec( | |
2484 | IN PVOID SystemSpecific1, | |
2485 | IN PVOID FunctionContext, | |
2486 | IN PVOID SystemSpecific2, | |
2487 | IN PVOID SystemSpecific3) | |
2488 | { | |
2489 | PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; | |
2490 | UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; | |
2491 | ULONG TxTotalCnt; | |
2492 | ULONG TxErrorRatio = 0; | |
2493 | BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE; | |
2494 | PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; | |
2495 | PUCHAR pTable; | |
2496 | UCHAR TableSize = 0; | |
2497 | UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; | |
2498 | TX_STA_CNT1_STRUC StaTx1; | |
2499 | TX_STA_CNT0_STRUC TxStaCnt0; | |
2500 | CHAR Rssi, ratio; | |
2501 | ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; | |
2502 | MAC_TABLE_ENTRY *pEntry; | |
2503 | ULONG i; | |
2504 | ||
2505 | pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; | |
2506 | ||
2507 | // | |
2508 | // walk through MAC table, see if need to change AP's TX rate toward each entry | |
2509 | // | |
2510 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) | |
2511 | { | |
2512 | pEntry = &pAd->MacTab.Content[i]; | |
2513 | ||
2514 | // check if this entry need to switch rate automatically | |
2515 | if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) | |
2516 | continue; | |
2517 | ||
2518 | //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2); | |
2519 | if (pAd->Antenna.field.TxPath > 1) | |
2520 | Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; | |
2521 | else | |
2522 | Rssi = pAd->StaCfg.RssiSample.AvgRssi0; | |
2523 | ||
2524 | CurrRateIdx = pAd->CommonCfg.TxRateIndex; | |
2525 | ||
2526 | MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); | |
2527 | ||
2528 | // decide the next upgrade rate and downgrade rate, if any | |
2529 | if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) | |
2530 | { | |
2531 | UpRateIdx = CurrRateIdx + 1; | |
2532 | DownRateIdx = CurrRateIdx -1; | |
2533 | } | |
2534 | else if (CurrRateIdx == 0) | |
2535 | { | |
2536 | UpRateIdx = CurrRateIdx + 1; | |
2537 | DownRateIdx = CurrRateIdx; | |
2538 | } | |
2539 | else if (CurrRateIdx == (TableSize - 1)) | |
2540 | { | |
2541 | UpRateIdx = CurrRateIdx; | |
2542 | DownRateIdx = CurrRateIdx - 1; | |
2543 | } | |
2544 | ||
2545 | pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; | |
2546 | ||
2547 | #ifdef DOT11_N_SUPPORT | |
2548 | if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) | |
2549 | { | |
2550 | TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); | |
2551 | TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); | |
2552 | } | |
2553 | else | |
2554 | #endif // DOT11_N_SUPPORT // | |
2555 | { | |
2556 | TrainUp = pCurrTxRate->TrainUp; | |
2557 | TrainDown = pCurrTxRate->TrainDown; | |
2558 | } | |
2559 | ||
2560 | if (pAd->MacTab.Size == 1) | |
2561 | { | |
2562 | // Update statistic counter | |
2563 | RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); | |
2564 | RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); | |
2565 | ||
2566 | TxRetransmit = StaTx1.field.TxRetransmit; | |
2567 | TxSuccess = StaTx1.field.TxSuccess; | |
2568 | TxFailCount = TxStaCnt0.field.TxFailCount; | |
2569 | TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; | |
2570 | ||
2571 | pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; | |
2572 | pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; | |
2573 | pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; | |
2574 | pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; | |
2575 | pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; | |
2576 | pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; | |
2577 | ||
2578 | if (TxTotalCnt) | |
2579 | TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; | |
2580 | } | |
2581 | else | |
2582 | { | |
2583 | TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + | |
2584 | pEntry->OneSecTxRetryOkCount + | |
2585 | pEntry->OneSecTxFailCount; | |
2586 | ||
2587 | if (TxTotalCnt) | |
2588 | TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; | |
2589 | } | |
2590 | ||
2591 | ||
2592 | // | |
2593 | // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI | |
2594 | // (criteria copied from RT2500 for Netopia case) | |
2595 | // | |
2596 | if (TxTotalCnt <= 12) | |
2597 | { | |
2598 | NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2599 | NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2600 | ||
2601 | if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) | |
2602 | { | |
2603 | pAd->CommonCfg.TxRateIndex = DownRateIdx; | |
2604 | pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; | |
2605 | } | |
2606 | else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) | |
2607 | { | |
2608 | pAd->CommonCfg.TxRateIndex = UpRateIdx; | |
2609 | } | |
2610 | ||
2611 | DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n")); | |
2612 | return; | |
2613 | } | |
2614 | ||
2615 | do | |
2616 | { | |
2617 | ULONG OneSecTxNoRetryOKRationCount; | |
2618 | ||
2619 | if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0) | |
2620 | ratio = 5; | |
2621 | else | |
2622 | ratio = 4; | |
2623 | ||
2624 | // downgrade TX quality if PER >= Rate-Down threshold | |
2625 | if (TxErrorRatio >= TrainDown) | |
2626 | { | |
2627 | pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; | |
2628 | } | |
2629 | ||
2630 | pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio; | |
2631 | ||
2632 | OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); | |
2633 | ||
2634 | // perform DRS - consider TxRate Down first, then rate up. | |
2635 | if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) | |
2636 | { | |
2637 | if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) | |
2638 | { | |
2639 | pAd->CommonCfg.TxRateIndex = DownRateIdx; | |
2640 | pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; | |
2641 | ||
2642 | } | |
2643 | ||
2644 | } | |
2645 | else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) | |
2646 | { | |
2647 | if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) | |
2648 | { | |
2649 | ||
2650 | } | |
2651 | else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) | |
2652 | { | |
2653 | pAd->CommonCfg.TxRateIndex = UpRateIdx; | |
2654 | } | |
2655 | } | |
2656 | }while (FALSE); | |
2657 | ||
2658 | // if rate-up happen, clear all bad history of all TX rates | |
2659 | if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) | |
2660 | { | |
2661 | pAd->DrsCounters.TxRateUpPenalty = 0; | |
2662 | NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2663 | NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); | |
2664 | } | |
2665 | // if rate-down happen, only clear DownRate's bad history | |
2666 | else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) | |
2667 | { | |
2668 | DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex)); | |
2669 | ||
2670 | pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty | |
2671 | pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0; | |
2672 | pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0; | |
2673 | } | |
2674 | else | |
2675 | { | |
2676 | bTxRateChanged = FALSE; | |
2677 | } | |
2678 | ||
2679 | pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5]; | |
2680 | if (bTxRateChanged && pNextTxRate) | |
2681 | { | |
2682 | MlmeSetTxRate(pAd, pEntry, pNextTxRate); | |
2683 | } | |
2684 | } | |
2685 | } | |
2686 | ||
2687 | /* | |
2688 | ========================================================================== | |
2689 | Description: | |
2690 | This routine is executed periodically inside MlmePeriodicExec() after | |
2691 | association with an AP. | |
2692 | It checks if StaCfg.Psm is consistent with user policy (recorded in | |
2693 | StaCfg.WindowsPowerMode). If not, enforce user policy. However, | |
2694 | there're some conditions to consider: | |
2695 | 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all | |
2696 | the time when Mibss==TRUE | |
2697 | 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE | |
2698 | if outgoing traffic available in TxRing or MgmtRing. | |
2699 | Output: | |
2700 | 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched | |
2701 | ||
2702 | IRQL = DISPATCH_LEVEL | |
2703 | ||
2704 | ========================================================================== | |
2705 | */ | |
2706 | VOID MlmeCheckPsmChange( | |
2707 | IN PRTMP_ADAPTER pAd, | |
2708 | IN ULONG Now32) | |
2709 | { | |
2710 | ULONG PowerMode; | |
2711 | ||
2712 | // condition - | |
2713 | // 1. Psm maybe ON only happen in INFRASTRUCTURE mode | |
2714 | // 2. user wants either MAX_PSP or FAST_PSP | |
2715 | // 3. but current psm is not in PWR_SAVE | |
2716 | // 4. CNTL state machine is not doing SCANning | |
2717 | // 5. no TX SUCCESS event for the past 1-sec period | |
2718 | #ifdef NDIS51_MINIPORT | |
2719 | if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery) | |
2720 | PowerMode = pAd->StaCfg.WindowsBatteryPowerMode; | |
2721 | else | |
2722 | #endif | |
2723 | PowerMode = pAd->StaCfg.WindowsPowerMode; | |
2724 | ||
2725 | if (INFRA_ON(pAd) && | |
2726 | (PowerMode != Ndis802_11PowerModeCAM) && | |
2727 | (pAd->StaCfg.Psm == PWR_ACTIVE) && | |
ed291e80 | 2728 | RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)) |
91980990 GKH |
2729 | { |
2730 | NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); | |
2731 | pAd->RalinkCounters.RxCountSinceLastNULL = 0; | |
2732 | MlmeSetPsmBit(pAd, PWR_SAVE); | |
2733 | if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) | |
2734 | { | |
2735 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); | |
2736 | } | |
2737 | else | |
2738 | { | |
2739 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); | |
2740 | } | |
2741 | } | |
2742 | } | |
2743 | ||
2744 | // IRQL = PASSIVE_LEVEL | |
2745 | // IRQL = DISPATCH_LEVEL | |
2746 | VOID MlmeSetPsmBit( | |
2747 | IN PRTMP_ADAPTER pAd, | |
2748 | IN USHORT psm) | |
2749 | { | |
2750 | AUTO_RSP_CFG_STRUC csr4; | |
2751 | ||
2752 | pAd->StaCfg.Psm = psm; | |
2753 | RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); | |
2754 | csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0; | |
2755 | RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); | |
2756 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm)); | |
2757 | } | |
2758 | #endif // CONFIG_STA_SUPPORT // | |
2759 | ||
2760 | ||
2761 | // IRQL = DISPATCH_LEVEL | |
2762 | VOID MlmeSetTxPreamble( | |
2763 | IN PRTMP_ADAPTER pAd, | |
2764 | IN USHORT TxPreamble) | |
2765 | { | |
2766 | AUTO_RSP_CFG_STRUC csr4; | |
2767 | ||
2768 | // | |
2769 | // Always use Long preamble before verifiation short preamble functionality works well. | |
2770 | // Todo: remove the following line if short preamble functionality works | |
2771 | // | |
2772 | //TxPreamble = Rt802_11PreambleLong; | |
2773 | ||
2774 | RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); | |
2775 | if (TxPreamble == Rt802_11PreambleLong) | |
2776 | { | |
2777 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n")); | |
2778 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | |
2779 | csr4.field.AutoResponderPreamble = 0; | |
2780 | } | |
2781 | else | |
2782 | { | |
2783 | // NOTE: 1Mbps should always use long preamble | |
2784 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n")); | |
2785 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | |
2786 | csr4.field.AutoResponderPreamble = 1; | |
2787 | } | |
2788 | ||
2789 | RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); | |
2790 | } | |
2791 | ||
2792 | /* | |
2793 | ========================================================================== | |
2794 | Description: | |
2795 | Update basic rate bitmap | |
2796 | ========================================================================== | |
2797 | */ | |
2798 | ||
2799 | VOID UpdateBasicRateBitmap( | |
2800 | IN PRTMP_ADAPTER pAdapter) | |
2801 | { | |
2802 | INT i, j; | |
2803 | /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ | |
2804 | UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; | |
2805 | UCHAR *sup_p = pAdapter->CommonCfg.SupRate; | |
2806 | UCHAR *ext_p = pAdapter->CommonCfg.ExtRate; | |
2807 | ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap; | |
2808 | ||
2809 | ||
2810 | /* if A mode, always use fix BasicRateBitMap */ | |
2811 | //if (pAdapter->CommonCfg.Channel == PHY_11A) | |
2812 | if (pAdapter->CommonCfg.Channel > 14) | |
2813 | pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */ | |
2814 | /* End of if */ | |
2815 | ||
2816 | if (pAdapter->CommonCfg.BasicRateBitmap > 4095) | |
2817 | { | |
2818 | /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ | |
2819 | return; | |
2820 | } /* End of if */ | |
2821 | ||
2822 | for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) | |
2823 | { | |
2824 | sup_p[i] &= 0x7f; | |
2825 | ext_p[i] &= 0x7f; | |
2826 | } /* End of for */ | |
2827 | ||
2828 | for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) | |
2829 | { | |
2830 | if (bitmap & (1 << i)) | |
2831 | { | |
2832 | for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++) | |
2833 | { | |
2834 | if (sup_p[j] == rate[i]) | |
2835 | sup_p[j] |= 0x80; | |
2836 | /* End of if */ | |
2837 | } /* End of for */ | |
2838 | ||
2839 | for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++) | |
2840 | { | |
2841 | if (ext_p[j] == rate[i]) | |
2842 | ext_p[j] |= 0x80; | |
2843 | /* End of if */ | |
2844 | } /* End of for */ | |
2845 | } /* End of if */ | |
2846 | } /* End of for */ | |
2847 | } /* End of UpdateBasicRateBitmap */ | |
2848 | ||
2849 | // IRQL = PASSIVE_LEVEL | |
2850 | // IRQL = DISPATCH_LEVEL | |
2851 | // bLinkUp is to identify the inital link speed. | |
2852 | // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. | |
2853 | VOID MlmeUpdateTxRates( | |
2854 | IN PRTMP_ADAPTER pAd, | |
2855 | IN BOOLEAN bLinkUp, | |
2856 | IN UCHAR apidx) | |
2857 | { | |
2858 | int i, num; | |
2859 | UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1; | |
2860 | UCHAR MinSupport = RATE_54; | |
2861 | ULONG BasicRateBitmap = 0; | |
2862 | UCHAR CurrBasicRate = RATE_1; | |
2863 | UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen; | |
2864 | PHTTRANSMIT_SETTING pHtPhy = NULL; | |
2865 | PHTTRANSMIT_SETTING pMaxHtPhy = NULL; | |
2866 | PHTTRANSMIT_SETTING pMinHtPhy = NULL; | |
2867 | BOOLEAN *auto_rate_cur_p; | |
2868 | UCHAR HtMcs = MCS_AUTO; | |
2869 | ||
2870 | // find max desired rate | |
2871 | UpdateBasicRateBitmap(pAd); | |
2872 | ||
2873 | num = 0; | |
2874 | auto_rate_cur_p = NULL; | |
2875 | for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) | |
2876 | { | |
2877 | switch (pAd->CommonCfg.DesireRate[i] & 0x7f) | |
2878 | { | |
2879 | case 2: Rate = RATE_1; num++; break; | |
2880 | case 4: Rate = RATE_2; num++; break; | |
2881 | case 11: Rate = RATE_5_5; num++; break; | |
2882 | case 22: Rate = RATE_11; num++; break; | |
2883 | case 12: Rate = RATE_6; num++; break; | |
2884 | case 18: Rate = RATE_9; num++; break; | |
2885 | case 24: Rate = RATE_12; num++; break; | |
2886 | case 36: Rate = RATE_18; num++; break; | |
2887 | case 48: Rate = RATE_24; num++; break; | |
2888 | case 72: Rate = RATE_36; num++; break; | |
2889 | case 96: Rate = RATE_48; num++; break; | |
2890 | case 108: Rate = RATE_54; num++; break; | |
2891 | //default: Rate = RATE_1; break; | |
2892 | } | |
2893 | if (MaxDesire < Rate) MaxDesire = Rate; | |
2894 | } | |
2895 | ||
2896 | //=========================================================================== | |
2897 | //=========================================================================== | |
2898 | ||
2899 | #ifdef CONFIG_STA_SUPPORT | |
2900 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
2901 | { | |
2902 | pHtPhy = &pAd->StaCfg.HTPhyMode; | |
2903 | pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; | |
2904 | pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; | |
2905 | ||
2906 | auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; | |
2907 | HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; | |
2908 | ||
2909 | if ((pAd->StaCfg.BssType == BSS_ADHOC) && | |
2910 | (pAd->CommonCfg.PhyMode == PHY_11B) && | |
2911 | (MaxDesire > RATE_11)) | |
2912 | { | |
2913 | MaxDesire = RATE_11; | |
2914 | } | |
2915 | } | |
2916 | #endif // CONFIG_STA_SUPPORT // | |
2917 | ||
2918 | pAd->CommonCfg.MaxDesiredRate = MaxDesire; | |
2919 | pMinHtPhy->word = 0; | |
2920 | pMaxHtPhy->word = 0; | |
2921 | pHtPhy->word = 0; | |
2922 | ||
2923 | // Auto rate switching is enabled only if more than one DESIRED RATES are | |
2924 | // specified; otherwise disabled | |
2925 | if (num <= 1) | |
2926 | { | |
2927 | *auto_rate_cur_p = FALSE; | |
2928 | } | |
2929 | else | |
2930 | { | |
2931 | *auto_rate_cur_p = TRUE; | |
2932 | } | |
2933 | ||
2934 | #if 1 | |
2935 | if (HtMcs != MCS_AUTO) | |
2936 | { | |
2937 | *auto_rate_cur_p = FALSE; | |
2938 | } | |
2939 | else | |
2940 | { | |
2941 | *auto_rate_cur_p = TRUE; | |
2942 | } | |
2943 | #endif | |
2944 | ||
2945 | #ifdef CONFIG_STA_SUPPORT | |
2946 | if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) | |
2947 | { | |
2948 | pSupRate = &pAd->StaActive.SupRate[0]; | |
2949 | pExtRate = &pAd->StaActive.ExtRate[0]; | |
2950 | SupRateLen = pAd->StaActive.SupRateLen; | |
2951 | ExtRateLen = pAd->StaActive.ExtRateLen; | |
2952 | } | |
2953 | else | |
2954 | #endif // CONFIG_STA_SUPPORT // | |
2955 | { | |
2956 | pSupRate = &pAd->CommonCfg.SupRate[0]; | |
2957 | pExtRate = &pAd->CommonCfg.ExtRate[0]; | |
2958 | SupRateLen = pAd->CommonCfg.SupRateLen; | |
2959 | ExtRateLen = pAd->CommonCfg.ExtRateLen; | |
2960 | } | |
2961 | ||
2962 | // find max supported rate | |
2963 | for (i=0; i<SupRateLen; i++) | |
2964 | { | |
2965 | switch (pSupRate[i] & 0x7f) | |
2966 | { | |
2967 | case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break; | |
2968 | case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break; | |
2969 | case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break; | |
2970 | case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break; | |
2971 | case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break; | |
2972 | case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break; | |
2973 | case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break; | |
2974 | case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break; | |
2975 | case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break; | |
2976 | case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break; | |
2977 | case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break; | |
2978 | case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break; | |
2979 | default: Rate = RATE_1; break; | |
2980 | } | |
2981 | if (MaxSupport < Rate) MaxSupport = Rate; | |
2982 | ||
2983 | if (MinSupport > Rate) MinSupport = Rate; | |
2984 | } | |
2985 | ||
2986 | for (i=0; i<ExtRateLen; i++) | |
2987 | { | |
2988 | switch (pExtRate[i] & 0x7f) | |
2989 | { | |
2990 | case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break; | |
2991 | case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break; | |
2992 | case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break; | |
2993 | case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break; | |
2994 | case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break; | |
2995 | case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break; | |
2996 | case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break; | |
2997 | case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break; | |
2998 | case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break; | |
2999 | case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break; | |
3000 | case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break; | |
3001 | case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break; | |
3002 | default: Rate = RATE_1; break; | |
3003 | } | |
3004 | if (MaxSupport < Rate) MaxSupport = Rate; | |
3005 | ||
3006 | if (MinSupport > Rate) MinSupport = Rate; | |
3007 | } | |
3008 | ||
3009 | RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); | |
3010 | ||
3011 | // calculate the exptected ACK rate for each TX rate. This info is used to caculate | |
3012 | // the DURATION field of outgoing uniicast DATA/MGMT frame | |
3013 | for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++) | |
3014 | { | |
3015 | if (BasicRateBitmap & (0x01 << i)) | |
3016 | CurrBasicRate = (UCHAR)i; | |
3017 | pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate; | |
3018 | } | |
3019 | ||
3020 | DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); | |
3021 | // max tx rate = min {max desire rate, max supported rate} | |
3022 | if (MaxSupport < MaxDesire) | |
3023 | pAd->CommonCfg.MaxTxRate = MaxSupport; | |
3024 | else | |
3025 | pAd->CommonCfg.MaxTxRate = MaxDesire; | |
3026 | ||
3027 | pAd->CommonCfg.MinTxRate = MinSupport; | |
3028 | if (*auto_rate_cur_p) | |
3029 | { | |
3030 | short dbm = 0; | |
3031 | #ifdef CONFIG_STA_SUPPORT | |
3032 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
3033 | dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; | |
3034 | #endif // CONFIG_STA_SUPPORT // | |
3035 | if (bLinkUp == TRUE) | |
3036 | pAd->CommonCfg.TxRate = RATE_24; | |
3037 | else | |
3038 | pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; | |
3039 | ||
3040 | if (dbm < -75) | |
3041 | pAd->CommonCfg.TxRate = RATE_11; | |
3042 | else if (dbm < -70) | |
3043 | pAd->CommonCfg.TxRate = RATE_24; | |
3044 | ||
3045 | // should never exceed MaxTxRate (consider 11B-only mode) | |
3046 | if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) | |
3047 | pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; | |
3048 | ||
3049 | pAd->CommonCfg.TxRateIndex = 0; | |
3050 | } | |
3051 | else | |
3052 | { | |
3053 | pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; | |
3054 | pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate; | |
3055 | pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK; | |
3056 | ||
3057 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC; | |
3058 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI; | |
3059 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS; | |
3060 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE; | |
3061 | } | |
3062 | ||
3063 | if (pAd->CommonCfg.TxRate <= RATE_11) | |
3064 | { | |
3065 | pMaxHtPhy->field.MODE = MODE_CCK; | |
3066 | pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; | |
3067 | pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; | |
3068 | } | |
3069 | else | |
3070 | { | |
3071 | pMaxHtPhy->field.MODE = MODE_OFDM; | |
3072 | pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; | |
3073 | if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54)) | |
3074 | {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];} | |
3075 | else | |
3076 | {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;} | |
3077 | } | |
3078 | ||
3079 | pHtPhy->word = (pMaxHtPhy->word); | |
3080 | if (bLinkUp && (pAd->OpMode == OPMODE_STA)) | |
3081 | { | |
3082 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; | |
3083 | pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word; | |
3084 | pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word; | |
3085 | } | |
3086 | else | |
3087 | { | |
3088 | switch (pAd->CommonCfg.PhyMode) | |
3089 | { | |
3090 | case PHY_11BG_MIXED: | |
3091 | case PHY_11B: | |
3092 | #ifdef DOT11_N_SUPPORT | |
3093 | case PHY_11BGN_MIXED: | |
3094 | #endif // DOT11_N_SUPPORT // | |
3095 | pAd->CommonCfg.MlmeRate = RATE_1; | |
3096 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | |
3097 | pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; | |
3098 | pAd->CommonCfg.RtsRate = RATE_11; | |
3099 | break; | |
3100 | case PHY_11G: | |
3101 | case PHY_11A: | |
3102 | #ifdef DOT11_N_SUPPORT | |
3103 | case PHY_11AGN_MIXED: | |
3104 | case PHY_11GN_MIXED: | |
3105 | case PHY_11N_2_4G: | |
3106 | case PHY_11AN_MIXED: | |
3107 | case PHY_11N_5G: | |
3108 | #endif // DOT11_N_SUPPORT // | |
3109 | pAd->CommonCfg.MlmeRate = RATE_6; | |
3110 | pAd->CommonCfg.RtsRate = RATE_6; | |
3111 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | |
3112 | pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | |
3113 | break; | |
3114 | case PHY_11ABG_MIXED: | |
3115 | #ifdef DOT11_N_SUPPORT | |
3116 | case PHY_11ABGN_MIXED: | |
3117 | #endif // DOT11_N_SUPPORT // | |
3118 | if (pAd->CommonCfg.Channel <= 14) | |
3119 | { | |
3120 | pAd->CommonCfg.MlmeRate = RATE_1; | |
3121 | pAd->CommonCfg.RtsRate = RATE_1; | |
3122 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | |
3123 | pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; | |
3124 | } | |
3125 | else | |
3126 | { | |
3127 | pAd->CommonCfg.MlmeRate = RATE_6; | |
3128 | pAd->CommonCfg.RtsRate = RATE_6; | |
3129 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | |
3130 | pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | |
3131 | } | |
3132 | break; | |
3133 | default: // error | |
3134 | pAd->CommonCfg.MlmeRate = RATE_6; | |
3135 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | |
3136 | pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | |
3137 | pAd->CommonCfg.RtsRate = RATE_1; | |
3138 | break; | |
3139 | } | |
3140 | // | |
3141 | // Keep Basic Mlme Rate. | |
3142 | // | |
3143 | pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; | |
3144 | if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) | |
3145 | pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24]; | |
3146 | else | |
3147 | pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1; | |
3148 | pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; | |
3149 | } | |
3150 | ||
3151 | DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", | |
3152 | RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate], | |
3153 | /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p)); | |
3154 | DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", | |
3155 | RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); | |
3156 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", | |
3157 | pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word )); | |
3158 | } | |
3159 | ||
3160 | #ifdef DOT11_N_SUPPORT | |
3161 | /* | |
3162 | ========================================================================== | |
3163 | Description: | |
3164 | This function update HT Rate setting. | |
3165 | Input Wcid value is valid for 2 case : | |
3166 | 1. it's used for Station in infra mode that copy AP rate to Mactable. | |
3167 | 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. | |
3168 | ||
3169 | IRQL = DISPATCH_LEVEL | |
3170 | ||
3171 | ========================================================================== | |
3172 | */ | |
3173 | VOID MlmeUpdateHtTxRates( | |
3174 | IN PRTMP_ADAPTER pAd, | |
3175 | IN UCHAR apidx) | |
3176 | { | |
3177 | UCHAR StbcMcs; //j, StbcMcs, bitmask; | |
3178 | CHAR i; // 3*3 | |
3179 | RT_HT_CAPABILITY *pRtHtCap = NULL; | |
3180 | RT_HT_PHY_INFO *pActiveHtPhy = NULL; | |
3181 | ULONG BasicMCS; | |
3182 | UCHAR j, bitmask; | |
3183 | PRT_HT_PHY_INFO pDesireHtPhy = NULL; | |
3184 | PHTTRANSMIT_SETTING pHtPhy = NULL; | |
3185 | PHTTRANSMIT_SETTING pMaxHtPhy = NULL; | |
3186 | PHTTRANSMIT_SETTING pMinHtPhy = NULL; | |
3187 | BOOLEAN *auto_rate_cur_p; | |
3188 | ||
3189 | DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n")); | |
3190 | ||
3191 | auto_rate_cur_p = NULL; | |
3192 | ||
3193 | #ifdef CONFIG_STA_SUPPORT | |
3194 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
3195 | { | |
3196 | pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; | |
3197 | pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; | |
3198 | pHtPhy = &pAd->StaCfg.HTPhyMode; | |
3199 | pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; | |
3200 | pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; | |
3201 | ||
3202 | auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; | |
3203 | } | |
3204 | #endif // CONFIG_STA_SUPPORT // | |
3205 | ||
3206 | #ifdef CONFIG_STA_SUPPORT | |
3207 | if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) | |
3208 | { | |
3209 | if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) | |
3210 | return; | |
3211 | ||
3212 | pRtHtCap = &pAd->StaActive.SupportedHtPhy; | |
3213 | pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; | |
3214 | StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs; | |
3215 | BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16); | |
3216 | if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) | |
3217 | pMaxHtPhy->field.STBC = STBC_USE; | |
3218 | else | |
3219 | pMaxHtPhy->field.STBC = STBC_NONE; | |
3220 | } | |
3221 | else | |
3222 | #endif // CONFIG_STA_SUPPORT // | |
3223 | { | |
3224 | if (pDesireHtPhy->bHtEnable == FALSE) | |
3225 | return; | |
3226 | ||
3227 | pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; | |
3228 | StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; | |
3229 | BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16); | |
3230 | if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) | |
3231 | pMaxHtPhy->field.STBC = STBC_USE; | |
3232 | else | |
3233 | pMaxHtPhy->field.STBC = STBC_NONE; | |
3234 | } | |
3235 | ||
3236 | // Decide MAX ht rate. | |
3237 | if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) | |
3238 | pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; | |
3239 | else | |
3240 | pMaxHtPhy->field.MODE = MODE_HTMIX; | |
3241 | ||
3242 | if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth)) | |
3243 | pMaxHtPhy->field.BW = BW_40; | |
3244 | else | |
3245 | pMaxHtPhy->field.BW = BW_20; | |
3246 | ||
3247 | if (pMaxHtPhy->field.BW == BW_20) | |
3248 | pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20); | |
3249 | else | |
3250 | pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40); | |
3251 | ||
3252 | for (i=23; i>=0; i--) // 3*3 | |
3253 | { | |
3254 | j = i/8; | |
3255 | bitmask = (1<<(i-(j*8))); | |
3256 | ||
3257 | if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask)) | |
3258 | { | |
3259 | pMaxHtPhy->field.MCS = i; | |
3260 | break; | |
3261 | } | |
3262 | ||
3263 | if (i==0) | |
3264 | break; | |
3265 | } | |
3266 | ||
3267 | // Copy MIN ht rate. rt2860??? | |
3268 | pMinHtPhy->field.BW = BW_20; | |
3269 | pMinHtPhy->field.MCS = 0; | |
3270 | pMinHtPhy->field.STBC = 0; | |
3271 | pMinHtPhy->field.ShortGI = 0; | |
3272 | //If STA assigns fixed rate. update to fixed here. | |
3273 | #ifdef CONFIG_STA_SUPPORT | |
3274 | if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) | |
3275 | { | |
3276 | if (pDesireHtPhy->MCSSet[4] != 0) | |
3277 | { | |
3278 | pMaxHtPhy->field.MCS = 32; | |
3279 | pMinHtPhy->field.MCS = 32; | |
3280 | DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS)); | |
3281 | } | |
3282 | ||
3283 | for (i=23; (CHAR)i >= 0; i--) // 3*3 | |
3284 | { | |
3285 | j = i/8; | |
3286 | bitmask = (1<<(i-(j*8))); | |
3287 | if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask)) | |
3288 | { | |
3289 | pMaxHtPhy->field.MCS = i; | |
3290 | pMinHtPhy->field.MCS = i; | |
3291 | break; | |
3292 | } | |
3293 | if (i==0) | |
3294 | break; | |
3295 | } | |
3296 | } | |
3297 | #endif // CONFIG_STA_SUPPORT // | |
3298 | ||
3299 | ||
3300 | // Decide ht rate | |
3301 | pHtPhy->field.STBC = pMaxHtPhy->field.STBC; | |
3302 | pHtPhy->field.BW = pMaxHtPhy->field.BW; | |
3303 | pHtPhy->field.MODE = pMaxHtPhy->field.MODE; | |
3304 | pHtPhy->field.MCS = pMaxHtPhy->field.MCS; | |
3305 | pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; | |
3306 | ||
3307 | // use default now. rt2860 | |
3308 | if (pDesireHtPhy->MCSSet[0] != 0xff) | |
3309 | *auto_rate_cur_p = FALSE; | |
3310 | else | |
3311 | *auto_rate_cur_p = TRUE; | |
3312 | ||
3313 | DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize )); | |
3314 | DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS, | |
3315 | pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE)); | |
3316 | DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n")); | |
3317 | } | |
3318 | #endif // DOT11_N_SUPPORT // | |
3319 | ||
3320 | // IRQL = DISPATCH_LEVEL | |
3321 | VOID MlmeRadioOff( | |
3322 | IN PRTMP_ADAPTER pAd) | |
3323 | { | |
3324 | RT28XX_MLME_RADIO_OFF(pAd); | |
3325 | } | |
3326 | ||
3327 | // IRQL = DISPATCH_LEVEL | |
3328 | VOID MlmeRadioOn( | |
3329 | IN PRTMP_ADAPTER pAd) | |
3330 | { | |
3331 | RT28XX_MLME_RADIO_ON(pAd); | |
3332 | } | |
3333 | ||
3334 | // =========================================================================================== | |
3335 | // bss_table.c | |
3336 | // =========================================================================================== | |
3337 | ||
3338 | ||
3339 | /*! \brief initialize BSS table | |
3340 | * \param p_tab pointer to the table | |
3341 | * \return none | |
3342 | * \pre | |
3343 | * \post | |
3344 | ||
3345 | IRQL = PASSIVE_LEVEL | |
3346 | IRQL = DISPATCH_LEVEL | |
3347 | ||
3348 | */ | |
3349 | VOID BssTableInit( | |
3350 | IN BSS_TABLE *Tab) | |
3351 | { | |
3352 | int i; | |
3353 | ||
3354 | Tab->BssNr = 0; | |
3355 | Tab->BssOverlapNr = 0; | |
3356 | for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) | |
3357 | { | |
3358 | NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY)); | |
3359 | Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value | |
3360 | } | |
3361 | } | |
3362 | ||
3363 | #ifdef DOT11_N_SUPPORT | |
3364 | VOID BATableInit( | |
3365 | IN PRTMP_ADAPTER pAd, | |
3366 | IN BA_TABLE *Tab) | |
3367 | { | |
3368 | int i; | |
3369 | ||
3370 | Tab->numAsOriginator = 0; | |
3371 | Tab->numAsRecipient = 0; | |
3372 | NdisAllocateSpinLock(&pAd->BATabLock); | |
3373 | for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) | |
3374 | { | |
3375 | Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; | |
3376 | NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock)); | |
3377 | } | |
3378 | for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) | |
3379 | { | |
3380 | Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; | |
3381 | } | |
3382 | } | |
3383 | #endif // DOT11_N_SUPPORT // | |
3384 | ||
3385 | /*! \brief search the BSS table by SSID | |
3386 | * \param p_tab pointer to the bss table | |
3387 | * \param ssid SSID string | |
3388 | * \return index of the table, BSS_NOT_FOUND if not in the table | |
3389 | * \pre | |
3390 | * \post | |
3391 | * \note search by sequential search | |
3392 | ||
3393 | IRQL = DISPATCH_LEVEL | |
3394 | ||
3395 | */ | |
3396 | ULONG BssTableSearch( | |
3397 | IN BSS_TABLE *Tab, | |
3398 | IN PUCHAR pBssid, | |
3399 | IN UCHAR Channel) | |
3400 | { | |
3401 | UCHAR i; | |
3402 | ||
3403 | for (i = 0; i < Tab->BssNr; i++) | |
3404 | { | |
3405 | // | |
3406 | // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. | |
3407 | // We should distinguish this case. | |
3408 | // | |
3409 | if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || | |
3410 | ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && | |
3411 | MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) | |
3412 | { | |
3413 | return i; | |
3414 | } | |
3415 | } | |
3416 | return (ULONG)BSS_NOT_FOUND; | |
3417 | } | |
3418 | ||
3419 | ULONG BssSsidTableSearch( | |
3420 | IN BSS_TABLE *Tab, | |
3421 | IN PUCHAR pBssid, | |
3422 | IN PUCHAR pSsid, | |
3423 | IN UCHAR SsidLen, | |
3424 | IN UCHAR Channel) | |
3425 | { | |
3426 | UCHAR i; | |
3427 | ||
3428 | for (i = 0; i < Tab->BssNr; i++) | |
3429 | { | |
3430 | // | |
3431 | // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. | |
3432 | // We should distinguish this case. | |
3433 | // | |
3434 | if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || | |
3435 | ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && | |
3436 | MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && | |
3437 | SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) | |
3438 | { | |
3439 | return i; | |
3440 | } | |
3441 | } | |
3442 | return (ULONG)BSS_NOT_FOUND; | |
3443 | } | |
3444 | ||
3445 | ULONG BssTableSearchWithSSID( | |
3446 | IN BSS_TABLE *Tab, | |
3447 | IN PUCHAR Bssid, | |
3448 | IN PUCHAR pSsid, | |
3449 | IN UCHAR SsidLen, | |
3450 | IN UCHAR Channel) | |
3451 | { | |
3452 | UCHAR i; | |
3453 | ||
3454 | for (i = 0; i < Tab->BssNr; i++) | |
3455 | { | |
3456 | if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || | |
3457 | ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && | |
3458 | MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && | |
3459 | (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) || | |
3460 | (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || | |
3461 | (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen)))) | |
3462 | { | |
3463 | return i; | |
3464 | } | |
3465 | } | |
3466 | return (ULONG)BSS_NOT_FOUND; | |
3467 | } | |
3468 | ||
3469 | // IRQL = DISPATCH_LEVEL | |
3470 | VOID BssTableDeleteEntry( | |
3471 | IN OUT BSS_TABLE *Tab, | |
3472 | IN PUCHAR pBssid, | |
3473 | IN UCHAR Channel) | |
3474 | { | |
3475 | UCHAR i, j; | |
3476 | ||
3477 | for (i = 0; i < Tab->BssNr; i++) | |
3478 | { | |
3479 | if ((Tab->BssEntry[i].Channel == Channel) && | |
3480 | (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) | |
3481 | { | |
3482 | for (j = i; j < Tab->BssNr - 1; j++) | |
3483 | { | |
3484 | NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY)); | |
3485 | } | |
3486 | NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY)); | |
3487 | Tab->BssNr -= 1; | |
3488 | return; | |
3489 | } | |
3490 | } | |
3491 | } | |
3492 | ||
3493 | #ifdef DOT11_N_SUPPORT | |
3494 | /* | |
3495 | ======================================================================== | |
3496 | Routine Description: | |
3497 | Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed. | |
3498 | ||
3499 | Arguments: | |
3500 | // IRQL = DISPATCH_LEVEL | |
3501 | ======================================================================== | |
3502 | */ | |
3503 | VOID BATableDeleteORIEntry( | |
3504 | IN OUT PRTMP_ADAPTER pAd, | |
3505 | IN BA_ORI_ENTRY *pBAORIEntry) | |
3506 | { | |
3507 | ||
3508 | if (pBAORIEntry->ORI_BA_Status != Originator_NONE) | |
3509 | { | |
3510 | NdisAcquireSpinLock(&pAd->BATabLock); | |
3511 | if (pBAORIEntry->ORI_BA_Status == Originator_Done) | |
3512 | { | |
3513 | pAd->BATable.numAsOriginator -= 1; | |
3514 | DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); | |
3515 | // Erase Bitmap flag. | |
3516 | } | |
3517 | pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here | |
3518 | pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here | |
3519 | pBAORIEntry->ORI_BA_Status = Originator_NONE; | |
3520 | pBAORIEntry->Token = 1; | |
3521 | // Not clear Sequence here. | |
3522 | NdisReleaseSpinLock(&pAd->BATabLock); | |
3523 | } | |
3524 | } | |
3525 | #endif // DOT11_N_SUPPORT // | |
3526 | ||
3527 | /*! \brief | |
3528 | * \param | |
3529 | * \return | |
3530 | * \pre | |
3531 | * \post | |
3532 | ||
3533 | IRQL = DISPATCH_LEVEL | |
3534 | ||
3535 | */ | |
3536 | VOID BssEntrySet( | |
3537 | IN PRTMP_ADAPTER pAd, | |
3538 | OUT BSS_ENTRY *pBss, | |
3539 | IN PUCHAR pBssid, | |
3540 | IN CHAR Ssid[], | |
3541 | IN UCHAR SsidLen, | |
3542 | IN UCHAR BssType, | |
3543 | IN USHORT BeaconPeriod, | |
3544 | IN PCF_PARM pCfParm, | |
3545 | IN USHORT AtimWin, | |
3546 | IN USHORT CapabilityInfo, | |
3547 | IN UCHAR SupRate[], | |
3548 | IN UCHAR SupRateLen, | |
3549 | IN UCHAR ExtRate[], | |
3550 | IN UCHAR ExtRateLen, | |
3551 | IN HT_CAPABILITY_IE *pHtCapability, | |
3552 | IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE | |
3553 | IN UCHAR HtCapabilityLen, | |
3554 | IN UCHAR AddHtInfoLen, | |
3555 | IN UCHAR NewExtChanOffset, | |
3556 | IN UCHAR Channel, | |
3557 | IN CHAR Rssi, | |
3558 | IN LARGE_INTEGER TimeStamp, | |
3559 | IN UCHAR CkipFlag, | |
3560 | IN PEDCA_PARM pEdcaParm, | |
3561 | IN PQOS_CAPABILITY_PARM pQosCapability, | |
3562 | IN PQBSS_LOAD_PARM pQbssLoad, | |
3563 | IN USHORT LengthVIE, | |
3564 | IN PNDIS_802_11_VARIABLE_IEs pVIE) | |
3565 | { | |
3566 | COPY_MAC_ADDR(pBss->Bssid, pBssid); | |
3567 | // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID | |
3568 | pBss->Hidden = 1; | |
3569 | if (SsidLen > 0) | |
3570 | { | |
3571 | // For hidden SSID AP, it might send beacon with SSID len equal to 0 | |
3572 | // Or send beacon /probe response with SSID len matching real SSID length, | |
3573 | // but SSID is all zero. such as "00-00-00-00" with length 4. | |
3574 | // We have to prevent this case overwrite correct table | |
3575 | if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) | |
3576 | { | |
3577 | NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); | |
3578 | NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); | |
3579 | pBss->SsidLen = SsidLen; | |
3580 | pBss->Hidden = 0; | |
3581 | } | |
3582 | } | |
3583 | else | |
3584 | pBss->SsidLen = 0; | |
3585 | pBss->BssType = BssType; | |
3586 | pBss->BeaconPeriod = BeaconPeriod; | |
3587 | if (BssType == BSS_INFRA) | |
3588 | { | |
3589 | if (pCfParm->bValid) | |
3590 | { | |
3591 | pBss->CfpCount = pCfParm->CfpCount; | |
3592 | pBss->CfpPeriod = pCfParm->CfpPeriod; | |
3593 | pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; | |
3594 | pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; | |
3595 | } | |
3596 | } | |
3597 | else | |
3598 | { | |
3599 | pBss->AtimWin = AtimWin; | |
3600 | } | |
3601 | ||
3602 | pBss->CapabilityInfo = CapabilityInfo; | |
3603 | // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES | |
3604 | // Combine with AuthMode, they will decide the connection methods. | |
3605 | pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); | |
3606 | ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); | |
3607 | if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) | |
3608 | NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); | |
3609 | else | |
3610 | NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); | |
3611 | pBss->SupRateLen = SupRateLen; | |
3612 | ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); | |
3613 | NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); | |
3614 | NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); | |
3615 | NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); | |
3616 | pBss->NewExtChanOffset = NewExtChanOffset; | |
3617 | pBss->ExtRateLen = ExtRateLen; | |
3618 | pBss->Channel = Channel; | |
3619 | pBss->CentralChannel = Channel; | |
3620 | pBss->Rssi = Rssi; | |
3621 | // Update CkipFlag. if not exists, the value is 0x0 | |
3622 | pBss->CkipFlag = CkipFlag; | |
3623 | ||
3624 | // New for microsoft Fixed IEs | |
3625 | NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); | |
3626 | pBss->FixIEs.BeaconInterval = BeaconPeriod; | |
3627 | pBss->FixIEs.Capabilities = CapabilityInfo; | |
3628 | ||
3629 | // New for microsoft Variable IEs | |
3630 | if (LengthVIE != 0) | |
3631 | { | |
3632 | pBss->VarIELen = LengthVIE; | |
3633 | NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); | |
3634 | } | |
3635 | else | |
3636 | { | |
3637 | pBss->VarIELen = 0; | |
3638 | } | |
3639 | ||
3640 | pBss->AddHtInfoLen = 0; | |
3641 | pBss->HtCapabilityLen = 0; | |
3642 | #ifdef DOT11_N_SUPPORT | |
3643 | if (HtCapabilityLen> 0) | |
3644 | { | |
3645 | pBss->HtCapabilityLen = HtCapabilityLen; | |
3646 | NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); | |
3647 | if (AddHtInfoLen > 0) | |
3648 | { | |
3649 | pBss->AddHtInfoLen = AddHtInfoLen; | |
3650 | NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); | |
3651 | ||
3652 | if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) | |
3653 | { | |
3654 | pBss->CentralChannel = pAddHtInfo->ControlChan - 2; | |
3655 | } | |
3656 | else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) | |
3657 | { | |
3658 | pBss->CentralChannel = pAddHtInfo->ControlChan + 2; | |
3659 | } | |
3660 | } | |
3661 | } | |
3662 | #endif // DOT11_N_SUPPORT // | |
3663 | ||
3664 | BssCipherParse(pBss); | |
3665 | ||
3666 | // new for QOS | |
3667 | if (pEdcaParm) | |
3668 | NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM)); | |
3669 | else | |
3670 | pBss->EdcaParm.bValid = FALSE; | |
3671 | if (pQosCapability) | |
3672 | NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM)); | |
3673 | else | |
3674 | pBss->QosCapability.bValid = FALSE; | |
3675 | if (pQbssLoad) | |
3676 | NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM)); | |
3677 | else | |
3678 | pBss->QbssLoad.bValid = FALSE; | |
3679 | ||
3680 | #ifdef CONFIG_STA_SUPPORT | |
3681 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
3682 | { | |
3683 | PEID_STRUCT pEid; | |
3684 | USHORT Length = 0; | |
3685 | ||
3686 | ||
3687 | NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); | |
3688 | NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); | |
d439c378 | 3689 | |
91980990 | 3690 | pEid = (PEID_STRUCT) pVIE; |
d439c378 | 3691 | |
91980990 GKH |
3692 | while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) |
3693 | { | |
3694 | switch(pEid->Eid) | |
3695 | { | |
3696 | case IE_WPA: | |
3697 | if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) | |
3698 | { | |
3699 | if ((pEid->Len + 2) > MAX_CUSTOM_LEN) | |
3700 | { | |
3701 | pBss->WpaIE.IELen = 0; | |
3702 | break; | |
3703 | } | |
3704 | pBss->WpaIE.IELen = pEid->Len + 2; | |
3705 | NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen); | |
3706 | } | |
3707 | break; | |
3708 | case IE_RSN: | |
3709 | if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) | |
3710 | { | |
3711 | if ((pEid->Len + 2) > MAX_CUSTOM_LEN) | |
3712 | { | |
3713 | pBss->RsnIE.IELen = 0; | |
3714 | break; | |
3715 | } | |
3716 | pBss->RsnIE.IELen = pEid->Len + 2; | |
3717 | NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen); | |
3718 | } | |
3719 | break; | |
91980990 GKH |
3720 | } |
3721 | Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len] | |
3722 | pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); | |
3723 | } | |
3724 | } | |
3725 | #endif // CONFIG_STA_SUPPORT // | |
3726 | } | |
3727 | ||
3728 | /*! | |
3729 | * \brief insert an entry into the bss table | |
3730 | * \param p_tab The BSS table | |
3731 | * \param Bssid BSSID | |
3732 | * \param ssid SSID | |
3733 | * \param ssid_len Length of SSID | |
3734 | * \param bss_type | |
3735 | * \param beacon_period | |
3736 | * \param timestamp | |
3737 | * \param p_cf | |
3738 | * \param atim_win | |
3739 | * \param cap | |
3740 | * \param rates | |
3741 | * \param rates_len | |
3742 | * \param channel_idx | |
3743 | * \return none | |
3744 | * \pre | |
3745 | * \post | |
3746 | * \note If SSID is identical, the old entry will be replaced by the new one | |
3747 | ||
3748 | IRQL = DISPATCH_LEVEL | |
3749 | ||
3750 | */ | |
3751 | ULONG BssTableSetEntry( | |
3752 | IN PRTMP_ADAPTER pAd, | |
3753 | OUT BSS_TABLE *Tab, | |
3754 | IN PUCHAR pBssid, | |
3755 | IN CHAR Ssid[], | |
3756 | IN UCHAR SsidLen, | |
3757 | IN UCHAR BssType, | |
3758 | IN USHORT BeaconPeriod, | |
3759 | IN CF_PARM *CfParm, | |
3760 | IN USHORT AtimWin, | |
3761 | IN USHORT CapabilityInfo, | |
3762 | IN UCHAR SupRate[], | |
3763 | IN UCHAR SupRateLen, | |
3764 | IN UCHAR ExtRate[], | |
3765 | IN UCHAR ExtRateLen, | |
3766 | IN HT_CAPABILITY_IE *pHtCapability, | |
3767 | IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE | |
3768 | IN UCHAR HtCapabilityLen, | |
3769 | IN UCHAR AddHtInfoLen, | |
3770 | IN UCHAR NewExtChanOffset, | |
3771 | IN UCHAR ChannelNo, | |
3772 | IN CHAR Rssi, | |
3773 | IN LARGE_INTEGER TimeStamp, | |
3774 | IN UCHAR CkipFlag, | |
3775 | IN PEDCA_PARM pEdcaParm, | |
3776 | IN PQOS_CAPABILITY_PARM pQosCapability, | |
3777 | IN PQBSS_LOAD_PARM pQbssLoad, | |
3778 | IN USHORT LengthVIE, | |
3779 | IN PNDIS_802_11_VARIABLE_IEs pVIE) | |
3780 | { | |
3781 | ULONG Idx; | |
3782 | ||
3783 | Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo); | |
3784 | if (Idx == BSS_NOT_FOUND) | |
3785 | { | |
3786 | if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) | |
3787 | { | |
3788 | // | |
3789 | // It may happen when BSS Table was full. | |
3790 | // The desired AP will not be added into BSS Table | |
3791 | // In this case, if we found the desired AP then overwrite BSS Table. | |
3792 | // | |
3793 | if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
3794 | { | |
3795 | if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) || | |
3796 | SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen)) | |
3797 | { | |
3798 | Idx = Tab->BssOverlapNr; | |
3799 | BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, | |
3800 | CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, | |
3801 | NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); | |
3802 | Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE; | |
3803 | } | |
3804 | return Idx; | |
3805 | } | |
3806 | else | |
3807 | { | |
3808 | return BSS_NOT_FOUND; | |
3809 | } | |
3810 | } | |
3811 | Idx = Tab->BssNr; | |
3812 | BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, | |
3813 | CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, | |
3814 | NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); | |
3815 | Tab->BssNr++; | |
3816 | } | |
3817 | else | |
3818 | { | |
3819 | BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin, | |
3820 | CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, | |
3821 | NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); | |
3822 | } | |
3823 | ||
3824 | return Idx; | |
3825 | } | |
3826 | ||
3827 | #ifdef CONFIG_STA_SUPPORT | |
91980990 GKH |
3828 | // IRQL = DISPATCH_LEVEL |
3829 | VOID BssTableSsidSort( | |
3830 | IN PRTMP_ADAPTER pAd, | |
3831 | OUT BSS_TABLE *OutTab, | |
3832 | IN CHAR Ssid[], | |
3833 | IN UCHAR SsidLen) | |
3834 | { | |
3835 | INT i; | |
3836 | BssTableInit(OutTab); | |
3837 | ||
3838 | for (i = 0; i < pAd->ScanTab.BssNr; i++) | |
3839 | { | |
3840 | BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i]; | |
3841 | BOOLEAN bIsHiddenApIncluded = FALSE; | |
3842 | ||
3843 | if (((pAd->CommonCfg.bIEEE80211H == 1) && | |
3844 | (pAd->MlmeAux.Channel > 14) && | |
3845 | RadarChannelCheck(pAd, pInBss->Channel)) | |
91980990 GKH |
3846 | ) |
3847 | { | |
3848 | if (pInBss->Hidden) | |
3849 | bIsHiddenApIncluded = TRUE; | |
3850 | } | |
3851 | ||
3852 | if ((pInBss->BssType == pAd->StaCfg.BssType) && | |
3853 | (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded)) | |
3854 | { | |
3855 | BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; | |
91980990 GKH |
3856 | #ifdef DOT11_N_SUPPORT |
3857 | // 2.4G/5G N only mode | |
3858 | if ((pInBss->HtCapabilityLen == 0) && | |
3859 | ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) | |
3860 | { | |
3861 | DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); | |
3862 | continue; | |
3863 | } | |
3864 | #endif // DOT11_N_SUPPORT // | |
3865 | ||
3866 | // New for WPA2 | |
3867 | // Check the Authmode first | |
3868 | if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) | |
3869 | { | |
3870 | // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode | |
3871 | if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) | |
3872 | // None matched | |
3873 | continue; | |
3874 | ||
3875 | // Check cipher suite, AP must have more secured cipher than station setting | |
3876 | if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) | |
3877 | { | |
3878 | // If it's not mixed mode, we should only let BSS pass with the same encryption | |
3879 | if (pInBss->WPA.bMixMode == FALSE) | |
3880 | if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) | |
3881 | continue; | |
3882 | ||
3883 | // check group cipher | |
ed291e80 AM |
3884 | if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) && |
3885 | (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) && | |
3886 | (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled)) | |
91980990 GKH |
3887 | continue; |
3888 | ||
3889 | // check pairwise cipher, skip if none matched | |
3890 | // If profile set to AES, let it pass without question. | |
3891 | // If profile set to TKIP, we must find one mateched | |
3892 | if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && | |
3893 | (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && | |
3894 | (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) | |
3895 | continue; | |
3896 | } | |
3897 | else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) | |
3898 | { | |
3899 | // If it's not mixed mode, we should only let BSS pass with the same encryption | |
3900 | if (pInBss->WPA2.bMixMode == FALSE) | |
3901 | if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) | |
3902 | continue; | |
3903 | ||
3904 | // check group cipher | |
ed291e80 AM |
3905 | if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) && |
3906 | (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) && | |
3907 | (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled)) | |
91980990 GKH |
3908 | continue; |
3909 | ||
3910 | // check pairwise cipher, skip if none matched | |
3911 | // If profile set to AES, let it pass without question. | |
3912 | // If profile set to TKIP, we must find one mateched | |
3913 | if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && | |
3914 | (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && | |
3915 | (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) | |
3916 | continue; | |
3917 | } | |
3918 | } | |
3919 | // Bss Type matched, SSID matched. | |
3920 | // We will check wepstatus for qualification Bss | |
3921 | else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) | |
3922 | { | |
3923 | DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus)); | |
3924 | // | |
3925 | // For the SESv2 case, we will not qualify WepStatus. | |
3926 | // | |
3927 | if (!pInBss->bSES) | |
3928 | continue; | |
3929 | } | |
3930 | ||
3931 | // Since the AP is using hidden SSID, and we are trying to connect to ANY | |
3932 | // It definitely will fail. So, skip it. | |
3933 | // CCX also require not even try to connect it!! | |
3934 | if (SsidLen == 0) | |
3935 | continue; | |
3936 | ||
3937 | #ifdef DOT11_N_SUPPORT | |
3938 | // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region | |
3939 | // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, | |
3940 | if ((pInBss->CentralChannel != pInBss->Channel) && | |
3941 | (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) | |
3942 | { | |
3943 | if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) | |
3944 | { | |
3945 | pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; | |
3946 | SetCommonHT(pAd); | |
3947 | pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; | |
3948 | } | |
3949 | else | |
3950 | { | |
3951 | if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20) | |
3952 | { | |
3953 | SetCommonHT(pAd); | |
3954 | } | |
3955 | } | |
3956 | } | |
3957 | #endif // DOT11_N_SUPPORT // | |
3958 | ||
3959 | // copy matching BSS from InTab to OutTab | |
3960 | NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); | |
3961 | ||
3962 | OutTab->BssNr++; | |
3963 | } | |
3964 | else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0)) | |
3965 | { | |
3966 | BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; | |
3967 | ||
3968 | ||
3969 | #ifdef DOT11_N_SUPPORT | |
3970 | // 2.4G/5G N only mode | |
3971 | if ((pInBss->HtCapabilityLen == 0) && | |
3972 | ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) | |
3973 | { | |
3974 | DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); | |
3975 | continue; | |
3976 | } | |
3977 | #endif // DOT11_N_SUPPORT // | |
3978 | ||
3979 | // New for WPA2 | |
3980 | // Check the Authmode first | |
3981 | if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) | |
3982 | { | |
3983 | // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode | |
3984 | if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) | |
3985 | // None matched | |
3986 | continue; | |
3987 | ||
3988 | // Check cipher suite, AP must have more secured cipher than station setting | |
3989 | if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) | |
3990 | { | |
3991 | // If it's not mixed mode, we should only let BSS pass with the same encryption | |
3992 | if (pInBss->WPA.bMixMode == FALSE) | |
3993 | if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) | |
3994 | continue; | |
3995 | ||
3996 | // check group cipher | |
3997 | if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) | |
3998 | continue; | |
3999 | ||
4000 | // check pairwise cipher, skip if none matched | |
4001 | // If profile set to AES, let it pass without question. | |
4002 | // If profile set to TKIP, we must find one mateched | |
4003 | if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && | |
4004 | (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && | |
4005 | (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) | |
4006 | continue; | |
4007 | } | |
4008 | else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) | |
4009 | { | |
4010 | // If it's not mixed mode, we should only let BSS pass with the same encryption | |
4011 | if (pInBss->WPA2.bMixMode == FALSE) | |
4012 | if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) | |
4013 | continue; | |
4014 | ||
4015 | // check group cipher | |
4016 | if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) | |
4017 | continue; | |
4018 | ||
4019 | // check pairwise cipher, skip if none matched | |
4020 | // If profile set to AES, let it pass without question. | |
4021 | // If profile set to TKIP, we must find one mateched | |
4022 | if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && | |
4023 | (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && | |
4024 | (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) | |
4025 | continue; | |
4026 | } | |
4027 | } | |
4028 | // Bss Type matched, SSID matched. | |
4029 | // We will check wepstatus for qualification Bss | |
4030 | else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) | |
4031 | continue; | |
4032 | ||
4033 | #ifdef DOT11_N_SUPPORT | |
4034 | // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region | |
4035 | // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, | |
4036 | if ((pInBss->CentralChannel != pInBss->Channel) && | |
4037 | (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) | |
4038 | { | |
4039 | if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) | |
4040 | { | |
4041 | pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; | |
4042 | SetCommonHT(pAd); | |
4043 | pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; | |
4044 | } | |
4045 | } | |
4046 | #endif // DOT11_N_SUPPORT // | |
4047 | ||
4048 | // copy matching BSS from InTab to OutTab | |
4049 | NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); | |
4050 | ||
4051 | OutTab->BssNr++; | |
4052 | } | |
4053 | ||
4054 | if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) | |
4055 | break; | |
4056 | } | |
4057 | ||
4058 | BssTableSortByRssi(OutTab); | |
4059 | } | |
4060 | ||
4061 | ||
4062 | // IRQL = DISPATCH_LEVEL | |
4063 | VOID BssTableSortByRssi( | |
4064 | IN OUT BSS_TABLE *OutTab) | |
4065 | { | |
4066 | INT i, j; | |
4067 | BSS_ENTRY TmpBss; | |
4068 | ||
4069 | for (i = 0; i < OutTab->BssNr - 1; i++) | |
4070 | { | |
4071 | for (j = i+1; j < OutTab->BssNr; j++) | |
4072 | { | |
4073 | if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) | |
4074 | { | |
4075 | NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY)); | |
4076 | NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY)); | |
4077 | NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY)); | |
4078 | } | |
4079 | } | |
4080 | } | |
4081 | } | |
4082 | #endif // CONFIG_STA_SUPPORT // | |
4083 | ||
4084 | ||
4085 | VOID BssCipherParse( | |
4086 | IN OUT PBSS_ENTRY pBss) | |
4087 | { | |
4088 | PEID_STRUCT pEid; | |
4089 | PUCHAR pTmp; | |
4090 | PRSN_IE_HEADER_STRUCT pRsnHeader; | |
4091 | PCIPHER_SUITE_STRUCT pCipher; | |
4092 | PAKM_SUITE_STRUCT pAKM; | |
4093 | USHORT Count; | |
4094 | INT Length; | |
4095 | NDIS_802_11_ENCRYPTION_STATUS TmpCipher; | |
4096 | ||
4097 | // | |
4098 | // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. | |
4099 | // | |
4100 | if (pBss->Privacy) | |
4101 | { | |
4102 | pBss->WepStatus = Ndis802_11WEPEnabled; | |
4103 | } | |
4104 | else | |
4105 | { | |
4106 | pBss->WepStatus = Ndis802_11WEPDisabled; | |
4107 | } | |
4108 | // Set default to disable & open authentication before parsing variable IE | |
4109 | pBss->AuthMode = Ndis802_11AuthModeOpen; | |
4110 | pBss->AuthModeAux = Ndis802_11AuthModeOpen; | |
4111 | ||
4112 | // Init WPA setting | |
4113 | pBss->WPA.PairCipher = Ndis802_11WEPDisabled; | |
4114 | pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; | |
4115 | pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; | |
4116 | pBss->WPA.RsnCapability = 0; | |
4117 | pBss->WPA.bMixMode = FALSE; | |
4118 | ||
4119 | // Init WPA2 setting | |
4120 | pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; | |
4121 | pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; | |
4122 | pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; | |
4123 | pBss->WPA2.RsnCapability = 0; | |
4124 | pBss->WPA2.bMixMode = FALSE; | |
4125 | ||
4126 | ||
4127 | Length = (INT) pBss->VarIELen; | |
4128 | ||
4129 | while (Length > 0) | |
4130 | { | |
4131 | // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently | |
4132 | pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length; | |
4133 | pEid = (PEID_STRUCT) pTmp; | |
4134 | switch (pEid->Eid) | |
4135 | { | |
4136 | case IE_WPA: | |
4137 | //Parse Cisco IE_WPA (LEAP, CCKM, etc.) | |
4138 | if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3)) | |
4139 | { | |
4140 | pTmp += 11; | |
4141 | switch (*pTmp) | |
4142 | { | |
4143 | case 1: | |
4144 | case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway | |
4145 | pBss->WepStatus = Ndis802_11Encryption1Enabled; | |
4146 | pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; | |
4147 | pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; | |
4148 | break; | |
4149 | case 2: | |
4150 | pBss->WepStatus = Ndis802_11Encryption2Enabled; | |
4151 | pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; | |
4152 | pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; | |
4153 | break; | |
4154 | case 4: | |
4155 | pBss->WepStatus = Ndis802_11Encryption3Enabled; | |
4156 | pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; | |
4157 | pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; | |
4158 | break; | |
4159 | default: | |
4160 | break; | |
4161 | } | |
4162 | ||
4163 | // if Cisco IE_WPA, break | |
4164 | break; | |
4165 | } | |
4166 | else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7)) | |
4167 | { | |
4168 | pBss->bSES = TRUE; | |
4169 | break; | |
4170 | } | |
4171 | else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) | |
4172 | { | |
4173 | // if unsupported vendor specific IE | |
4174 | break; | |
4175 | } | |
4176 | // Skip OUI, version, and multicast suite | |
4177 | // This part should be improved in the future when AP supported multiple cipher suite. | |
4178 | // For now, it's OK since almost all APs have fixed cipher suite supported. | |
4179 | // pTmp = (PUCHAR) pEid->Octet; | |
4180 | pTmp += 11; | |
4181 | ||
4182 | // Cipher Suite Selectors from Spec P802.11i/D3.2 P26. | |
4183 | // Value Meaning | |
4184 | // 0 None | |
4185 | // 1 WEP-40 | |
4186 | // 2 Tkip | |
4187 | // 3 WRAP | |
4188 | // 4 AES | |
4189 | // 5 WEP-104 | |
4190 | // Parse group cipher | |
4191 | switch (*pTmp) | |
4192 | { | |
4193 | case 1: | |
ed291e80 AM |
4194 | pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled; |
4195 | break; | |
4196 | case 5: | |
4197 | pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled; | |
91980990 GKH |
4198 | break; |
4199 | case 2: | |
4200 | pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled; | |
4201 | break; | |
4202 | case 4: | |
4203 | pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled; | |
4204 | break; | |
4205 | default: | |
4206 | break; | |
4207 | } | |
4208 | // number of unicast suite | |
4209 | pTmp += 1; | |
4210 | ||
4211 | // skip all unicast cipher suites | |
4212 | //Count = *(PUSHORT) pTmp; | |
4213 | Count = (pTmp[1]<<8) + pTmp[0]; | |
4214 | pTmp += sizeof(USHORT); | |
4215 | ||
4216 | // Parsing all unicast cipher suite | |
4217 | while (Count > 0) | |
4218 | { | |
4219 | // Skip OUI | |
4220 | pTmp += 3; | |
4221 | TmpCipher = Ndis802_11WEPDisabled; | |
4222 | switch (*pTmp) | |
4223 | { | |
4224 | case 1: | |
4225 | case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway | |
4226 | TmpCipher = Ndis802_11Encryption1Enabled; | |
4227 | break; | |
4228 | case 2: | |
4229 | TmpCipher = Ndis802_11Encryption2Enabled; | |
4230 | break; | |
4231 | case 4: | |
4232 | TmpCipher = Ndis802_11Encryption3Enabled; | |
4233 | break; | |
4234 | default: | |
4235 | break; | |
4236 | } | |
4237 | if (TmpCipher > pBss->WPA.PairCipher) | |
4238 | { | |
4239 | // Move the lower cipher suite to PairCipherAux | |
4240 | pBss->WPA.PairCipherAux = pBss->WPA.PairCipher; | |
4241 | pBss->WPA.PairCipher = TmpCipher; | |
4242 | } | |
4243 | else | |
4244 | { | |
4245 | pBss->WPA.PairCipherAux = TmpCipher; | |
4246 | } | |
4247 | pTmp++; | |
4248 | Count--; | |
4249 | } | |
4250 | ||
4251 | // 4. get AKM suite counts | |
4252 | //Count = *(PUSHORT) pTmp; | |
4253 | Count = (pTmp[1]<<8) + pTmp[0]; | |
4254 | pTmp += sizeof(USHORT); | |
4255 | pTmp += 3; | |
4256 | ||
4257 | switch (*pTmp) | |
4258 | { | |
4259 | case 1: | |
4260 | // Set AP support WPA mode | |
4261 | if (pBss->AuthMode == Ndis802_11AuthModeOpen) | |
4262 | pBss->AuthMode = Ndis802_11AuthModeWPA; | |
4263 | else | |
4264 | pBss->AuthModeAux = Ndis802_11AuthModeWPA; | |
4265 | break; | |
4266 | case 2: | |
4267 | // Set AP support WPA mode | |
4268 | if (pBss->AuthMode == Ndis802_11AuthModeOpen) | |
4269 | pBss->AuthMode = Ndis802_11AuthModeWPAPSK; | |
4270 | else | |
4271 | pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK; | |
4272 | break; | |
4273 | default: | |
4274 | break; | |
4275 | } | |
4276 | pTmp += 1; | |
4277 | ||
4278 | // Fixed for WPA-None | |
4279 | if (pBss->BssType == BSS_ADHOC) | |
4280 | { | |
4281 | pBss->AuthMode = Ndis802_11AuthModeWPANone; | |
4282 | pBss->AuthModeAux = Ndis802_11AuthModeWPANone; | |
4283 | pBss->WepStatus = pBss->WPA.GroupCipher; | |
4284 | // Patched bugs for old driver | |
4285 | if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) | |
4286 | pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; | |
4287 | } | |
4288 | else | |
4289 | pBss->WepStatus = pBss->WPA.PairCipher; | |
4290 | ||
4291 | // Check the Pair & Group, if different, turn on mixed mode flag | |
4292 | if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) | |
4293 | pBss->WPA.bMixMode = TRUE; | |
4294 | ||
4295 | break; | |
4296 | ||
4297 | case IE_RSN: | |
4298 | pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; | |
4299 | ||
4300 | // 0. Version must be 1 | |
4301 | if (le2cpu16(pRsnHeader->Version) != 1) | |
4302 | break; | |
4303 | pTmp += sizeof(RSN_IE_HEADER_STRUCT); | |
4304 | ||
4305 | // 1. Check group cipher | |
4306 | pCipher = (PCIPHER_SUITE_STRUCT) pTmp; | |
4307 | if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) | |
4308 | break; | |
4309 | ||
4310 | // Parse group cipher | |
4311 | switch (pCipher->Type) | |
4312 | { | |
4313 | case 1: | |
ed291e80 AM |
4314 | pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled; |
4315 | break; | |
4316 | case 5: | |
4317 | pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled; | |
91980990 GKH |
4318 | break; |
4319 | case 2: | |
4320 | pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled; | |
4321 | break; | |
4322 | case 4: | |
4323 | pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled; | |
4324 | break; | |
4325 | default: | |
4326 | break; | |
4327 | } | |
4328 | // set to correct offset for next parsing | |
4329 | pTmp += sizeof(CIPHER_SUITE_STRUCT); | |
4330 | ||
4331 | // 2. Get pairwise cipher counts | |
4332 | //Count = *(PUSHORT) pTmp; | |
4333 | Count = (pTmp[1]<<8) + pTmp[0]; | |
4334 | pTmp += sizeof(USHORT); | |
4335 | ||
4336 | // 3. Get pairwise cipher | |
4337 | // Parsing all unicast cipher suite | |
4338 | while (Count > 0) | |
4339 | { | |
4340 | // Skip OUI | |
4341 | pCipher = (PCIPHER_SUITE_STRUCT) pTmp; | |
4342 | TmpCipher = Ndis802_11WEPDisabled; | |
4343 | switch (pCipher->Type) | |
4344 | { | |
4345 | case 1: | |
4346 | case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway | |
4347 | TmpCipher = Ndis802_11Encryption1Enabled; | |
4348 | break; | |
4349 | case 2: | |
4350 | TmpCipher = Ndis802_11Encryption2Enabled; | |
4351 | break; | |
4352 | case 4: | |
4353 | TmpCipher = Ndis802_11Encryption3Enabled; | |
4354 | break; | |
4355 | default: | |
4356 | break; | |
4357 | } | |
4358 | if (TmpCipher > pBss->WPA2.PairCipher) | |
4359 | { | |
4360 | // Move the lower cipher suite to PairCipherAux | |
4361 | pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher; | |
4362 | pBss->WPA2.PairCipher = TmpCipher; | |
4363 | } | |
4364 | else | |
4365 | { | |
4366 | pBss->WPA2.PairCipherAux = TmpCipher; | |
4367 | } | |
4368 | pTmp += sizeof(CIPHER_SUITE_STRUCT); | |
4369 | Count--; | |
4370 | } | |
4371 | ||
4372 | // 4. get AKM suite counts | |
4373 | //Count = *(PUSHORT) pTmp; | |
4374 | Count = (pTmp[1]<<8) + pTmp[0]; | |
4375 | pTmp += sizeof(USHORT); | |
4376 | ||
4377 | // 5. Get AKM ciphers | |
4378 | pAKM = (PAKM_SUITE_STRUCT) pTmp; | |
4379 | if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) | |
4380 | break; | |
4381 | ||
4382 | switch (pAKM->Type) | |
4383 | { | |
4384 | case 1: | |
4385 | // Set AP support WPA mode | |
4386 | if (pBss->AuthMode == Ndis802_11AuthModeOpen) | |
4387 | pBss->AuthMode = Ndis802_11AuthModeWPA2; | |
4388 | else | |
4389 | pBss->AuthModeAux = Ndis802_11AuthModeWPA2; | |
4390 | break; | |
4391 | case 2: | |
4392 | // Set AP support WPA mode | |
4393 | if (pBss->AuthMode == Ndis802_11AuthModeOpen) | |
4394 | pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; | |
4395 | else | |
4396 | pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; | |
4397 | break; | |
4398 | default: | |
4399 | break; | |
4400 | } | |
4401 | pTmp += (Count * sizeof(AKM_SUITE_STRUCT)); | |
4402 | ||
4403 | // Fixed for WPA-None | |
4404 | if (pBss->BssType == BSS_ADHOC) | |
4405 | { | |
4406 | pBss->AuthMode = Ndis802_11AuthModeWPANone; | |
4407 | pBss->AuthModeAux = Ndis802_11AuthModeWPANone; | |
4408 | pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux; | |
4409 | pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; | |
4410 | pBss->WepStatus = pBss->WPA.GroupCipher; | |
4411 | // Patched bugs for old driver | |
4412 | if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) | |
4413 | pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; | |
4414 | } | |
4415 | pBss->WepStatus = pBss->WPA2.PairCipher; | |
4416 | ||
4417 | // 6. Get RSN capability | |
4418 | //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp; | |
4419 | pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0]; | |
4420 | pTmp += sizeof(USHORT); | |
4421 | ||
4422 | // Check the Pair & Group, if different, turn on mixed mode flag | |
4423 | if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) | |
4424 | pBss->WPA2.bMixMode = TRUE; | |
4425 | ||
4426 | break; | |
4427 | default: | |
4428 | break; | |
4429 | } | |
4430 | Length -= (pEid->Len + 2); | |
4431 | } | |
4432 | } | |
4433 | ||
4434 | // =========================================================================================== | |
4435 | // mac_table.c | |
4436 | // =========================================================================================== | |
4437 | ||
4438 | /*! \brief generates a random mac address value for IBSS BSSID | |
4439 | * \param Addr the bssid location | |
4440 | * \return none | |
4441 | * \pre | |
4442 | * \post | |
4443 | */ | |
4444 | VOID MacAddrRandomBssid( | |
4445 | IN PRTMP_ADAPTER pAd, | |
4446 | OUT PUCHAR pAddr) | |
4447 | { | |
4448 | INT i; | |
4449 | ||
4450 | for (i = 0; i < MAC_ADDR_LEN; i++) | |
4451 | { | |
4452 | pAddr[i] = RandomByte(pAd); | |
4453 | } | |
4454 | ||
4455 | pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx | |
4456 | } | |
4457 | ||
4458 | /*! \brief init the management mac frame header | |
4459 | * \param p_hdr mac header | |
4460 | * \param subtype subtype of the frame | |
4461 | * \param p_ds destination address, don't care if it is a broadcast address | |
4462 | * \return none | |
4463 | * \pre the station has the following information in the pAd->StaCfg | |
4464 | * - bssid | |
4465 | * - station address | |
4466 | * \post | |
4467 | * \note this function initializes the following field | |
4468 | ||
4469 | IRQL = PASSIVE_LEVEL | |
4470 | IRQL = DISPATCH_LEVEL | |
4471 | ||
4472 | */ | |
4473 | VOID MgtMacHeaderInit( | |
4474 | IN PRTMP_ADAPTER pAd, | |
4475 | IN OUT PHEADER_802_11 pHdr80211, | |
4476 | IN UCHAR SubType, | |
4477 | IN UCHAR ToDs, | |
4478 | IN PUCHAR pDA, | |
4479 | IN PUCHAR pBssid) | |
4480 | { | |
4481 | NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); | |
4482 | ||
4483 | pHdr80211->FC.Type = BTYPE_MGMT; | |
4484 | pHdr80211->FC.SubType = SubType; | |
4485 | pHdr80211->FC.ToDs = ToDs; | |
4486 | COPY_MAC_ADDR(pHdr80211->Addr1, pDA); | |
4487 | #ifdef CONFIG_STA_SUPPORT | |
4488 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
4489 | COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); | |
4490 | #endif // CONFIG_STA_SUPPORT // | |
4491 | COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); | |
4492 | } | |
4493 | ||
4494 | // =========================================================================================== | |
4495 | // mem_mgmt.c | |
4496 | // =========================================================================================== | |
4497 | ||
4498 | /*!*************************************************************************** | |
4499 | * This routine build an outgoing frame, and fill all information specified | |
4500 | * in argument list to the frame body. The actual frame size is the summation | |
4501 | * of all arguments. | |
4502 | * input params: | |
4503 | * Buffer - pointer to a pre-allocated memory segment | |
4504 | * args - a list of <int arg_size, arg> pairs. | |
4505 | * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this | |
4506 | * function will FAIL!!! | |
4507 | * return: | |
4508 | * Size of the buffer | |
4509 | * usage: | |
4510 | * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); | |
4511 | ||
4512 | IRQL = PASSIVE_LEVEL | |
4513 | IRQL = DISPATCH_LEVEL | |
4514 | ||
4515 | ****************************************************************************/ | |
4516 | ULONG MakeOutgoingFrame( | |
4517 | OUT CHAR *Buffer, | |
4518 | OUT ULONG *FrameLen, ...) | |
4519 | { | |
4520 | CHAR *p; | |
4521 | int leng; | |
4522 | ULONG TotLeng; | |
4523 | va_list Args; | |
4524 | ||
4525 | // calculates the total length | |
4526 | TotLeng = 0; | |
4527 | va_start(Args, FrameLen); | |
4528 | do | |
4529 | { | |
4530 | leng = va_arg(Args, int); | |
4531 | if (leng == END_OF_ARGS) | |
4532 | { | |
4533 | break; | |
4534 | } | |
4535 | p = va_arg(Args, PVOID); | |
4536 | NdisMoveMemory(&Buffer[TotLeng], p, leng); | |
4537 | TotLeng = TotLeng + leng; | |
4538 | } while(TRUE); | |
4539 | ||
4540 | va_end(Args); /* clean up */ | |
4541 | *FrameLen = TotLeng; | |
4542 | return TotLeng; | |
4543 | } | |
4544 | ||
4545 | // =========================================================================================== | |
4546 | // mlme_queue.c | |
4547 | // =========================================================================================== | |
4548 | ||
4549 | /*! \brief Initialize The MLME Queue, used by MLME Functions | |
4550 | * \param *Queue The MLME Queue | |
4551 | * \return Always Return NDIS_STATE_SUCCESS in this implementation | |
4552 | * \pre | |
4553 | * \post | |
4554 | * \note Because this is done only once (at the init stage), no need to be locked | |
4555 | ||
4556 | IRQL = PASSIVE_LEVEL | |
4557 | ||
4558 | */ | |
4559 | NDIS_STATUS MlmeQueueInit( | |
4560 | IN MLME_QUEUE *Queue) | |
4561 | { | |
4562 | INT i; | |
4563 | ||
4564 | NdisAllocateSpinLock(&Queue->Lock); | |
4565 | ||
4566 | Queue->Num = 0; | |
4567 | Queue->Head = 0; | |
4568 | Queue->Tail = 0; | |
4569 | ||
4570 | for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) | |
4571 | { | |
4572 | Queue->Entry[i].Occupied = FALSE; | |
4573 | Queue->Entry[i].MsgLen = 0; | |
4574 | NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); | |
4575 | } | |
4576 | ||
4577 | return NDIS_STATUS_SUCCESS; | |
4578 | } | |
4579 | ||
4580 | /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread | |
4581 | * \param *Queue The MLME Queue | |
4582 | * \param Machine The State Machine Id | |
4583 | * \param MsgType The Message Type | |
4584 | * \param MsgLen The Message length | |
4585 | * \param *Msg The message pointer | |
4586 | * \return TRUE if enqueue is successful, FALSE if the queue is full | |
4587 | * \pre | |
4588 | * \post | |
4589 | * \note The message has to be initialized | |
4590 | ||
4591 | IRQL = PASSIVE_LEVEL | |
4592 | IRQL = DISPATCH_LEVEL | |
4593 | ||
4594 | */ | |
4595 | BOOLEAN MlmeEnqueue( | |
4596 | IN PRTMP_ADAPTER pAd, | |
4597 | IN ULONG Machine, | |
4598 | IN ULONG MsgType, | |
4599 | IN ULONG MsgLen, | |
4600 | IN VOID *Msg) | |
4601 | { | |
4602 | INT Tail; | |
4603 | MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; | |
4604 | ||
4605 | // Do nothing if the driver is starting halt state. | |
4606 | // This might happen when timer already been fired before cancel timer with mlmehalt | |
4607 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) | |
4608 | return FALSE; | |
4609 | ||
4610 | // First check the size, it MUST not exceed the mlme queue size | |
4611 | if (MsgLen > MGMT_DMA_BUFFER_SIZE) | |
4612 | { | |
4613 | DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); | |
4614 | return FALSE; | |
4615 | } | |
4616 | ||
4617 | if (MlmeQueueFull(Queue)) | |
4618 | { | |
4619 | return FALSE; | |
4620 | } | |
4621 | ||
4622 | NdisAcquireSpinLock(&(Queue->Lock)); | |
4623 | Tail = Queue->Tail; | |
4624 | Queue->Tail++; | |
4625 | Queue->Num++; | |
4626 | if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) | |
4627 | { | |
4628 | Queue->Tail = 0; | |
4629 | } | |
4630 | ||
4631 | Queue->Entry[Tail].Wcid = RESERVED_WCID; | |
4632 | Queue->Entry[Tail].Occupied = TRUE; | |
4633 | Queue->Entry[Tail].Machine = Machine; | |
4634 | Queue->Entry[Tail].MsgType = MsgType; | |
4635 | Queue->Entry[Tail].MsgLen = MsgLen; | |
4636 | ||
4637 | if (Msg != NULL) | |
4638 | { | |
4639 | NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); | |
4640 | } | |
4641 | ||
4642 | NdisReleaseSpinLock(&(Queue->Lock)); | |
4643 | return TRUE; | |
4644 | } | |
4645 | ||
4646 | /*! \brief This function is used when Recv gets a MLME message | |
4647 | * \param *Queue The MLME Queue | |
4648 | * \param TimeStampHigh The upper 32 bit of timestamp | |
4649 | * \param TimeStampLow The lower 32 bit of timestamp | |
4650 | * \param Rssi The receiving RSSI strength | |
4651 | * \param MsgLen The length of the message | |
4652 | * \param *Msg The message pointer | |
4653 | * \return TRUE if everything ok, FALSE otherwise (like Queue Full) | |
4654 | * \pre | |
4655 | * \post | |
4656 | ||
4657 | IRQL = DISPATCH_LEVEL | |
4658 | ||
4659 | */ | |
4660 | BOOLEAN MlmeEnqueueForRecv( | |
4661 | IN PRTMP_ADAPTER pAd, | |
4662 | IN ULONG Wcid, | |
4663 | IN ULONG TimeStampHigh, | |
4664 | IN ULONG TimeStampLow, | |
4665 | IN UCHAR Rssi0, | |
4666 | IN UCHAR Rssi1, | |
4667 | IN UCHAR Rssi2, | |
4668 | IN ULONG MsgLen, | |
4669 | IN VOID *Msg, | |
4670 | IN UCHAR Signal) | |
4671 | { | |
4672 | INT Tail, Machine; | |
4673 | PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; | |
4674 | INT MsgType; | |
4675 | MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; | |
4676 | ||
91980990 GKH |
4677 | // Do nothing if the driver is starting halt state. |
4678 | // This might happen when timer already been fired before cancel timer with mlmehalt | |
4679 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) | |
4680 | { | |
4681 | DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n")); | |
4682 | return FALSE; | |
4683 | } | |
4684 | ||
4685 | // First check the size, it MUST not exceed the mlme queue size | |
4686 | if (MsgLen > MGMT_DMA_BUFFER_SIZE) | |
4687 | { | |
4688 | DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); | |
4689 | return FALSE; | |
4690 | } | |
4691 | ||
4692 | if (MlmeQueueFull(Queue)) | |
4693 | { | |
4694 | return FALSE; | |
4695 | } | |
4696 | ||
4697 | #ifdef CONFIG_STA_SUPPORT | |
4698 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
4699 | { | |
4700 | if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) | |
4701 | { | |
4702 | DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType)); | |
4703 | return FALSE; | |
4704 | } | |
4705 | } | |
4706 | #endif // CONFIG_STA_SUPPORT // | |
4707 | ||
4708 | // OK, we got all the informations, it is time to put things into queue | |
4709 | NdisAcquireSpinLock(&(Queue->Lock)); | |
4710 | Tail = Queue->Tail; | |
4711 | Queue->Tail++; | |
4712 | Queue->Num++; | |
4713 | if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) | |
4714 | { | |
4715 | Queue->Tail = 0; | |
4716 | } | |
4717 | Queue->Entry[Tail].Occupied = TRUE; | |
4718 | Queue->Entry[Tail].Machine = Machine; | |
4719 | Queue->Entry[Tail].MsgType = MsgType; | |
4720 | Queue->Entry[Tail].MsgLen = MsgLen; | |
4721 | Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; | |
4722 | Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; | |
4723 | Queue->Entry[Tail].Rssi0 = Rssi0; | |
4724 | Queue->Entry[Tail].Rssi1 = Rssi1; | |
4725 | Queue->Entry[Tail].Rssi2 = Rssi2; | |
4726 | Queue->Entry[Tail].Signal = Signal; | |
4727 | Queue->Entry[Tail].Wcid = (UCHAR)Wcid; | |
4728 | ||
4729 | Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; | |
4730 | ||
4731 | if (Msg != NULL) | |
4732 | { | |
4733 | NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); | |
4734 | } | |
4735 | ||
4736 | NdisReleaseSpinLock(&(Queue->Lock)); | |
4737 | ||
4738 | RT28XX_MLME_HANDLER(pAd); | |
4739 | ||
4740 | return TRUE; | |
4741 | } | |
4742 | ||
4743 | ||
4744 | /*! \brief Dequeue a message from the MLME Queue | |
4745 | * \param *Queue The MLME Queue | |
4746 | * \param *Elem The message dequeued from MLME Queue | |
4747 | * \return TRUE if the Elem contains something, FALSE otherwise | |
4748 | * \pre | |
4749 | * \post | |
4750 | ||
4751 | IRQL = DISPATCH_LEVEL | |
4752 | ||
4753 | */ | |
4754 | BOOLEAN MlmeDequeue( | |
4755 | IN MLME_QUEUE *Queue, | |
4756 | OUT MLME_QUEUE_ELEM **Elem) | |
4757 | { | |
4758 | NdisAcquireSpinLock(&(Queue->Lock)); | |
4759 | *Elem = &(Queue->Entry[Queue->Head]); | |
4760 | Queue->Num--; | |
4761 | Queue->Head++; | |
4762 | if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) | |
4763 | { | |
4764 | Queue->Head = 0; | |
4765 | } | |
4766 | NdisReleaseSpinLock(&(Queue->Lock)); | |
4767 | return TRUE; | |
4768 | } | |
4769 | ||
4770 | // IRQL = DISPATCH_LEVEL | |
4771 | VOID MlmeRestartStateMachine( | |
4772 | IN PRTMP_ADAPTER pAd) | |
4773 | { | |
91980990 | 4774 | MLME_QUEUE_ELEM *Elem = NULL; |
91980990 GKH |
4775 | #ifdef CONFIG_STA_SUPPORT |
4776 | BOOLEAN Cancelled; | |
4777 | #endif // CONFIG_STA_SUPPORT // | |
4778 | ||
4779 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); | |
4780 | ||
91980990 GKH |
4781 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); |
4782 | if(pAd->Mlme.bRunning) | |
4783 | { | |
4784 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | |
4785 | return; | |
4786 | } | |
4787 | else | |
4788 | { | |
4789 | pAd->Mlme.bRunning = TRUE; | |
4790 | } | |
4791 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | |
4792 | ||
4793 | // Remove all Mlme queues elements | |
4794 | while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) | |
4795 | { | |
4796 | //From message type, determine which state machine I should drive | |
4797 | if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) | |
4798 | { | |
4799 | // free MLME element | |
4800 | Elem->Occupied = FALSE; | |
4801 | Elem->MsgLen = 0; | |
4802 | ||
4803 | } | |
4804 | else { | |
4805 | DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); | |
4806 | } | |
4807 | } | |
91980990 GKH |
4808 | |
4809 | #ifdef CONFIG_STA_SUPPORT | |
4810 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
4811 | { | |
91980990 GKH |
4812 | // Cancel all timer events |
4813 | // Be careful to cancel new added timer | |
4814 | RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); | |
4815 | RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); | |
4816 | RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); | |
4817 | RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); | |
4818 | RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); | |
4819 | RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); | |
91980990 GKH |
4820 | } |
4821 | #endif // CONFIG_STA_SUPPORT // | |
4822 | ||
4823 | // Change back to original channel in case of doing scan | |
4824 | AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); | |
4825 | AsicLockChannel(pAd, pAd->CommonCfg.Channel); | |
4826 | ||
4827 | // Resume MSDU which is turned off durning scan | |
4828 | RTMPResumeMsduTransmission(pAd); | |
4829 | ||
4830 | #ifdef CONFIG_STA_SUPPORT | |
4831 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
4832 | { | |
4833 | // Set all state machines back IDLE | |
4834 | pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; | |
4835 | pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; | |
4836 | pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; | |
4837 | pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; | |
4838 | pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; | |
4839 | pAd->Mlme.ActMachine.CurrState = ACT_IDLE; | |
91980990 GKH |
4840 | } |
4841 | #endif // CONFIG_STA_SUPPORT // | |
4842 | ||
91980990 GKH |
4843 | // Remove running state |
4844 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); | |
4845 | pAd->Mlme.bRunning = FALSE; | |
4846 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | |
91980990 GKH |
4847 | } |
4848 | ||
4849 | /*! \brief test if the MLME Queue is empty | |
4850 | * \param *Queue The MLME Queue | |
4851 | * \return TRUE if the Queue is empty, FALSE otherwise | |
4852 | * \pre | |
4853 | * \post | |
4854 | ||
4855 | IRQL = DISPATCH_LEVEL | |
4856 | ||
4857 | */ | |
4858 | BOOLEAN MlmeQueueEmpty( | |
4859 | IN MLME_QUEUE *Queue) | |
4860 | { | |
4861 | BOOLEAN Ans; | |
4862 | ||
4863 | NdisAcquireSpinLock(&(Queue->Lock)); | |
4864 | Ans = (Queue->Num == 0); | |
4865 | NdisReleaseSpinLock(&(Queue->Lock)); | |
4866 | ||
4867 | return Ans; | |
4868 | } | |
4869 | ||
4870 | /*! \brief test if the MLME Queue is full | |
4871 | * \param *Queue The MLME Queue | |
4872 | * \return TRUE if the Queue is empty, FALSE otherwise | |
4873 | * \pre | |
4874 | * \post | |
4875 | ||
4876 | IRQL = PASSIVE_LEVEL | |
4877 | IRQL = DISPATCH_LEVEL | |
4878 | ||
4879 | */ | |
4880 | BOOLEAN MlmeQueueFull( | |
4881 | IN MLME_QUEUE *Queue) | |
4882 | { | |
4883 | BOOLEAN Ans; | |
4884 | ||
4885 | NdisAcquireSpinLock(&(Queue->Lock)); | |
4886 | Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied); | |
4887 | NdisReleaseSpinLock(&(Queue->Lock)); | |
4888 | ||
4889 | return Ans; | |
4890 | } | |
4891 | ||
4892 | /*! \brief The destructor of MLME Queue | |
4893 | * \param | |
4894 | * \return | |
4895 | * \pre | |
4896 | * \post | |
4897 | * \note Clear Mlme Queue, Set Queue->Num to Zero. | |
4898 | ||
4899 | IRQL = PASSIVE_LEVEL | |
4900 | ||
4901 | */ | |
4902 | VOID MlmeQueueDestroy( | |
4903 | IN MLME_QUEUE *pQueue) | |
4904 | { | |
4905 | NdisAcquireSpinLock(&(pQueue->Lock)); | |
4906 | pQueue->Num = 0; | |
4907 | pQueue->Head = 0; | |
4908 | pQueue->Tail = 0; | |
4909 | NdisReleaseSpinLock(&(pQueue->Lock)); | |
4910 | NdisFreeSpinLock(&(pQueue->Lock)); | |
4911 | } | |
4912 | ||
4913 | /*! \brief To substitute the message type if the message is coming from external | |
4914 | * \param pFrame The frame received | |
4915 | * \param *Machine The state machine | |
4916 | * \param *MsgType the message type for the state machine | |
4917 | * \return TRUE if the substitution is successful, FALSE otherwise | |
4918 | * \pre | |
4919 | * \post | |
4920 | ||
4921 | IRQL = DISPATCH_LEVEL | |
4922 | ||
4923 | */ | |
4924 | #ifdef CONFIG_STA_SUPPORT | |
4925 | BOOLEAN MsgTypeSubst( | |
4926 | IN PRTMP_ADAPTER pAd, | |
4927 | IN PFRAME_802_11 pFrame, | |
4928 | OUT INT *Machine, | |
4929 | OUT INT *MsgType) | |
4930 | { | |
4931 | USHORT Seq; | |
4932 | UCHAR EAPType; | |
4933 | PUCHAR pData; | |
4934 | ||
4935 | // Pointer to start of data frames including SNAP header | |
4936 | pData = (PUCHAR) pFrame + LENGTH_802_11; | |
4937 | ||
4938 | // The only data type will pass to this function is EAPOL frame | |
4939 | if (pFrame->Hdr.FC.Type == BTYPE_DATA) | |
4940 | { | |
4941 | if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H)) | |
4942 | { | |
4943 | // Cisco Aironet SNAP header | |
4944 | *Machine = AIRONET_STATE_MACHINE; | |
4945 | *MsgType = MT2_AIRONET_MSG; | |
4946 | return (TRUE); | |
4947 | } | |
91980990 GKH |
4948 | { |
4949 | *Machine = WPA_PSK_STATE_MACHINE; | |
4950 | EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); | |
4951 | return(WpaMsgTypeSubst(EAPType, MsgType)); | |
4952 | } | |
4953 | } | |
4954 | ||
4955 | switch (pFrame->Hdr.FC.SubType) | |
4956 | { | |
4957 | case SUBTYPE_ASSOC_REQ: | |
4958 | *Machine = ASSOC_STATE_MACHINE; | |
4959 | *MsgType = MT2_PEER_ASSOC_REQ; | |
4960 | break; | |
4961 | case SUBTYPE_ASSOC_RSP: | |
4962 | *Machine = ASSOC_STATE_MACHINE; | |
4963 | *MsgType = MT2_PEER_ASSOC_RSP; | |
4964 | break; | |
4965 | case SUBTYPE_REASSOC_REQ: | |
4966 | *Machine = ASSOC_STATE_MACHINE; | |
4967 | *MsgType = MT2_PEER_REASSOC_REQ; | |
4968 | break; | |
4969 | case SUBTYPE_REASSOC_RSP: | |
4970 | *Machine = ASSOC_STATE_MACHINE; | |
4971 | *MsgType = MT2_PEER_REASSOC_RSP; | |
4972 | break; | |
4973 | case SUBTYPE_PROBE_REQ: | |
4974 | *Machine = SYNC_STATE_MACHINE; | |
4975 | *MsgType = MT2_PEER_PROBE_REQ; | |
4976 | break; | |
4977 | case SUBTYPE_PROBE_RSP: | |
4978 | *Machine = SYNC_STATE_MACHINE; | |
4979 | *MsgType = MT2_PEER_PROBE_RSP; | |
4980 | break; | |
4981 | case SUBTYPE_BEACON: | |
4982 | *Machine = SYNC_STATE_MACHINE; | |
4983 | *MsgType = MT2_PEER_BEACON; | |
4984 | break; | |
4985 | case SUBTYPE_ATIM: | |
4986 | *Machine = SYNC_STATE_MACHINE; | |
4987 | *MsgType = MT2_PEER_ATIM; | |
4988 | break; | |
4989 | case SUBTYPE_DISASSOC: | |
4990 | *Machine = ASSOC_STATE_MACHINE; | |
4991 | *MsgType = MT2_PEER_DISASSOC_REQ; | |
4992 | break; | |
4993 | case SUBTYPE_AUTH: | |
4994 | // get the sequence number from payload 24 Mac Header + 2 bytes algorithm | |
4995 | NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); | |
4996 | if (Seq == 1 || Seq == 3) | |
4997 | { | |
4998 | *Machine = AUTH_RSP_STATE_MACHINE; | |
4999 | *MsgType = MT2_PEER_AUTH_ODD; | |
5000 | } | |
5001 | else if (Seq == 2 || Seq == 4) | |
5002 | { | |
5003 | *Machine = AUTH_STATE_MACHINE; | |
5004 | *MsgType = MT2_PEER_AUTH_EVEN; | |
5005 | } | |
5006 | else | |
5007 | { | |
5008 | return FALSE; | |
5009 | } | |
5010 | break; | |
5011 | case SUBTYPE_DEAUTH: | |
5012 | *Machine = AUTH_RSP_STATE_MACHINE; | |
5013 | *MsgType = MT2_PEER_DEAUTH; | |
5014 | break; | |
5015 | case SUBTYPE_ACTION: | |
5016 | *Machine = ACTION_STATE_MACHINE; | |
5017 | // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support | |
5018 | if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) | |
5019 | { | |
5020 | *MsgType = MT2_ACT_INVALID; | |
5021 | } | |
5022 | else | |
5023 | { | |
5024 | *MsgType = (pFrame->Octet[0]&0x7F); | |
5025 | } | |
5026 | break; | |
5027 | default: | |
5028 | return FALSE; | |
5029 | break; | |
5030 | } | |
5031 | ||
5032 | return TRUE; | |
5033 | } | |
5034 | #endif // CONFIG_STA_SUPPORT // | |
5035 | ||
5036 | // =========================================================================================== | |
5037 | // state_machine.c | |
5038 | // =========================================================================================== | |
5039 | ||
5040 | /*! \brief Initialize the state machine. | |
5041 | * \param *S pointer to the state machine | |
5042 | * \param Trans State machine transition function | |
5043 | * \param StNr number of states | |
5044 | * \param MsgNr number of messages | |
5045 | * \param DefFunc default function, when there is invalid state/message combination | |
5046 | * \param InitState initial state of the state machine | |
5047 | * \param Base StateMachine base, internal use only | |
5048 | * \pre p_sm should be a legal pointer | |
5049 | * \post | |
5050 | ||
5051 | IRQL = PASSIVE_LEVEL | |
5052 | ||
5053 | */ | |
5054 | VOID StateMachineInit( | |
5055 | IN STATE_MACHINE *S, | |
5056 | IN STATE_MACHINE_FUNC Trans[], | |
5057 | IN ULONG StNr, | |
5058 | IN ULONG MsgNr, | |
5059 | IN STATE_MACHINE_FUNC DefFunc, | |
5060 | IN ULONG InitState, | |
5061 | IN ULONG Base) | |
5062 | { | |
5063 | ULONG i, j; | |
5064 | ||
5065 | // set number of states and messages | |
5066 | S->NrState = StNr; | |
5067 | S->NrMsg = MsgNr; | |
5068 | S->Base = Base; | |
5069 | ||
5070 | S->TransFunc = Trans; | |
5071 | ||
5072 | // init all state transition to default function | |
5073 | for (i = 0; i < StNr; i++) | |
5074 | { | |
5075 | for (j = 0; j < MsgNr; j++) | |
5076 | { | |
5077 | S->TransFunc[i * MsgNr + j] = DefFunc; | |
5078 | } | |
5079 | } | |
5080 | ||
5081 | // set the starting state | |
5082 | S->CurrState = InitState; | |
5083 | } | |
5084 | ||
5085 | /*! \brief This function fills in the function pointer into the cell in the state machine | |
5086 | * \param *S pointer to the state machine | |
5087 | * \param St state | |
5088 | * \param Msg incoming message | |
5089 | * \param f the function to be executed when (state, message) combination occurs at the state machine | |
5090 | * \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 | |
5091 | * \post | |
5092 | ||
5093 | IRQL = PASSIVE_LEVEL | |
5094 | ||
5095 | */ | |
5096 | VOID StateMachineSetAction( | |
5097 | IN STATE_MACHINE *S, | |
5098 | IN ULONG St, | |
5099 | IN ULONG Msg, | |
5100 | IN STATE_MACHINE_FUNC Func) | |
5101 | { | |
5102 | ULONG MsgIdx; | |
5103 | ||
5104 | MsgIdx = Msg - S->Base; | |
5105 | ||
5106 | if (St < S->NrState && MsgIdx < S->NrMsg) | |
5107 | { | |
5108 | // boundary checking before setting the action | |
5109 | S->TransFunc[St * S->NrMsg + MsgIdx] = Func; | |
5110 | } | |
5111 | } | |
5112 | ||
5113 | /*! \brief This function does the state transition | |
5114 | * \param *Adapter the NIC adapter pointer | |
5115 | * \param *S the state machine | |
5116 | * \param *Elem the message to be executed | |
5117 | * \return None | |
5118 | ||
5119 | IRQL = DISPATCH_LEVEL | |
5120 | ||
5121 | */ | |
5122 | VOID StateMachinePerformAction( | |
5123 | IN PRTMP_ADAPTER pAd, | |
5124 | IN STATE_MACHINE *S, | |
5125 | IN MLME_QUEUE_ELEM *Elem) | |
5126 | { | |
5127 | (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem); | |
5128 | } | |
5129 | ||
5130 | /* | |
5131 | ========================================================================== | |
5132 | Description: | |
5133 | The drop function, when machine executes this, the message is simply | |
5134 | ignored. This function does nothing, the message is freed in | |
5135 | StateMachinePerformAction() | |
5136 | ========================================================================== | |
5137 | */ | |
5138 | VOID Drop( | |
5139 | IN PRTMP_ADAPTER pAd, | |
5140 | IN MLME_QUEUE_ELEM *Elem) | |
5141 | { | |
5142 | } | |
5143 | ||
5144 | // =========================================================================================== | |
5145 | // lfsr.c | |
5146 | // =========================================================================================== | |
5147 | ||
5148 | /* | |
5149 | ========================================================================== | |
5150 | Description: | |
5151 | ||
5152 | IRQL = PASSIVE_LEVEL | |
5153 | ||
5154 | ========================================================================== | |
5155 | */ | |
5156 | VOID LfsrInit( | |
5157 | IN PRTMP_ADAPTER pAd, | |
5158 | IN ULONG Seed) | |
5159 | { | |
5160 | if (Seed == 0) | |
5161 | pAd->Mlme.ShiftReg = 1; | |
5162 | else | |
5163 | pAd->Mlme.ShiftReg = Seed; | |
5164 | } | |
5165 | ||
5166 | /* | |
5167 | ========================================================================== | |
5168 | Description: | |
5169 | ========================================================================== | |
5170 | */ | |
5171 | UCHAR RandomByte( | |
5172 | IN PRTMP_ADAPTER pAd) | |
5173 | { | |
5174 | ULONG i; | |
5175 | UCHAR R, Result; | |
5176 | ||
5177 | R = 0; | |
5178 | ||
5179 | if (pAd->Mlme.ShiftReg == 0) | |
5180 | NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg); | |
5181 | ||
5182 | for (i = 0; i < 8; i++) | |
5183 | { | |
5184 | if (pAd->Mlme.ShiftReg & 0x00000001) | |
5185 | { | |
5186 | pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; | |
5187 | Result = 1; | |
5188 | } | |
5189 | else | |
5190 | { | |
5191 | pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; | |
5192 | Result = 0; | |
5193 | } | |
5194 | R = (R << 1) | Result; | |
5195 | } | |
5196 | ||
5197 | return R; | |
5198 | } | |
5199 | ||
5200 | VOID AsicUpdateAutoFallBackTable( | |
5201 | IN PRTMP_ADAPTER pAd, | |
5202 | IN PUCHAR pRateTable) | |
5203 | { | |
5204 | UCHAR i; | |
5205 | HT_FBK_CFG0_STRUC HtCfg0; | |
5206 | HT_FBK_CFG1_STRUC HtCfg1; | |
5207 | LG_FBK_CFG0_STRUC LgCfg0; | |
5208 | LG_FBK_CFG1_STRUC LgCfg1; | |
5209 | PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate; | |
5210 | ||
5211 | // set to initial value | |
5212 | HtCfg0.word = 0x65432100; | |
5213 | HtCfg1.word = 0xedcba988; | |
5214 | LgCfg0.word = 0xedcba988; | |
5215 | LgCfg1.word = 0x00002100; | |
5216 | ||
5217 | pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1; | |
5218 | for (i = 1; i < *((PUCHAR) pRateTable); i++) | |
5219 | { | |
5220 | pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i; | |
5221 | switch (pCurrTxRate->Mode) | |
5222 | { | |
5223 | case 0: //CCK | |
5224 | break; | |
5225 | case 1: //OFDM | |
5226 | { | |
5227 | switch(pCurrTxRate->CurrMCS) | |
5228 | { | |
5229 | case 0: | |
5230 | LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5231 | break; | |
5232 | case 1: | |
5233 | LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5234 | break; | |
5235 | case 2: | |
5236 | LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5237 | break; | |
5238 | case 3: | |
5239 | LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5240 | break; | |
5241 | case 4: | |
5242 | LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5243 | break; | |
5244 | case 5: | |
5245 | LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5246 | break; | |
5247 | case 6: | |
5248 | LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5249 | break; | |
5250 | case 7: | |
5251 | LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; | |
5252 | break; | |
5253 | } | |
5254 | } | |
5255 | break; | |
5256 | #ifdef DOT11_N_SUPPORT | |
5257 | case 2: //HT-MIX | |
5258 | case 3: //HT-GF | |
5259 | { | |
5260 | if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS)) | |
5261 | { | |
5262 | switch(pCurrTxRate->CurrMCS) | |
5263 | { | |
5264 | case 0: | |
5265 | HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS; | |
5266 | break; | |
5267 | case 1: | |
5268 | HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS; | |
5269 | break; | |
5270 | case 2: | |
5271 | HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS; | |
5272 | break; | |
5273 | case 3: | |
5274 | HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS; | |
5275 | break; | |
5276 | case 4: | |
5277 | HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS; | |
5278 | break; | |
5279 | case 5: | |
5280 | HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS; | |
5281 | break; | |
5282 | case 6: | |
5283 | HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS; | |
5284 | break; | |
5285 | case 7: | |
5286 | HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS; | |
5287 | break; | |
5288 | case 8: | |
5289 | HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS; | |
5290 | break; | |
5291 | case 9: | |
5292 | HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS; | |
5293 | break; | |
5294 | case 10: | |
5295 | HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS; | |
5296 | break; | |
5297 | case 11: | |
5298 | HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS; | |
5299 | break; | |
5300 | case 12: | |
5301 | HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS; | |
5302 | break; | |
5303 | case 13: | |
5304 | HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS; | |
5305 | break; | |
5306 | case 14: | |
5307 | HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS; | |
5308 | break; | |
5309 | case 15: | |
5310 | HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS; | |
5311 | break; | |
5312 | default: | |
5313 | DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS)); | |
5314 | } | |
5315 | } | |
5316 | } | |
5317 | break; | |
5318 | #endif // DOT11_N_SUPPORT // | |
5319 | } | |
5320 | ||
5321 | pNextTxRate = pCurrTxRate; | |
5322 | } | |
5323 | ||
5324 | RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); | |
5325 | RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); | |
5326 | RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); | |
5327 | RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); | |
5328 | } | |
5329 | ||
5330 | /* | |
5331 | ======================================================================== | |
5332 | ||
5333 | Routine Description: | |
5334 | Set MAC register value according operation mode. | |
5335 | OperationMode AND bNonGFExist are for MM and GF Proteciton. | |
5336 | If MM or GF mask is not set, those passing argument doesn't not take effect. | |
5337 | ||
5338 | Operation mode meaning: | |
5339 | = 0 : Pure HT, no preotection. | |
5340 | = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. | |
5341 | = 0x10: No Transmission in 40M is protected. | |
5342 | = 0x11: Transmission in both 40M and 20M shall be protected | |
5343 | if (bNonGFExist) | |
5344 | we should choose not to use GF. But still set correct ASIC registers. | |
5345 | ======================================================================== | |
5346 | */ | |
5347 | VOID AsicUpdateProtect( | |
5348 | IN PRTMP_ADAPTER pAd, | |
5349 | IN USHORT OperationMode, | |
5350 | IN UCHAR SetMask, | |
5351 | IN BOOLEAN bDisableBGProtect, | |
5352 | IN BOOLEAN bNonGFExist) | |
5353 | { | |
5354 | PROT_CFG_STRUC ProtCfg, ProtCfg4; | |
5355 | UINT32 Protect[6]; | |
5356 | USHORT offset; | |
5357 | UCHAR i; | |
5358 | UINT32 MacReg = 0; | |
5359 | ||
91980990 GKH |
5360 | #ifdef DOT11_N_SUPPORT |
5361 | if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) | |
5362 | { | |
5363 | return; | |
5364 | } | |
5365 | ||
5366 | if (pAd->BATable.numAsOriginator) | |
5367 | { | |
5368 | // | |
5369 | // enable the RTS/CTS to avoid channel collision | |
5370 | // | |
5371 | SetMask = ALLN_SETPROTECT; | |
5372 | OperationMode = 8; | |
5373 | } | |
5374 | #endif // DOT11_N_SUPPORT // | |
5375 | ||
5376 | // Config ASIC RTS threshold register | |
5377 | RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); | |
5378 | MacReg &= 0xFF0000FF; | |
5379 | #if 0 | |
5380 | MacReg |= (pAd->CommonCfg.RtsThreshold << 8); | |
5381 | #else | |
4b512d26 | 5382 | // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 |
91980990 GKH |
5383 | if (( |
5384 | #ifdef DOT11_N_SUPPORT | |
5385 | (pAd->CommonCfg.BACapability.field.AmsduEnable) || | |
5386 | #endif // DOT11_N_SUPPORT // | |
5387 | (pAd->CommonCfg.bAggregationCapable == TRUE)) | |
5388 | && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) | |
5389 | { | |
5390 | MacReg |= (0x1000 << 8); | |
5391 | } | |
5392 | else | |
5393 | { | |
5394 | MacReg |= (pAd->CommonCfg.RtsThreshold << 8); | |
5395 | } | |
5396 | #endif | |
5397 | ||
5398 | RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); | |
5399 | ||
5400 | // Initial common protection settings | |
5401 | RTMPZeroMemory(Protect, sizeof(Protect)); | |
5402 | ProtCfg4.word = 0; | |
5403 | ProtCfg.word = 0; | |
5404 | ProtCfg.field.TxopAllowGF40 = 1; | |
5405 | ProtCfg.field.TxopAllowGF20 = 1; | |
5406 | ProtCfg.field.TxopAllowMM40 = 1; | |
5407 | ProtCfg.field.TxopAllowMM20 = 1; | |
5408 | ProtCfg.field.TxopAllowOfdm = 1; | |
5409 | ProtCfg.field.TxopAllowCck = 1; | |
5410 | ProtCfg.field.RTSThEn = 1; | |
5411 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | |
5412 | ||
5413 | // update PHY mode and rate | |
5414 | if (pAd->CommonCfg.Channel > 14) | |
5415 | ProtCfg.field.ProtectRate = 0x4000; | |
5416 | ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; | |
5417 | ||
5418 | // Handle legacy(B/G) protection | |
5419 | if (bDisableBGProtect) | |
5420 | { | |
5421 | //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; | |
5422 | ProtCfg.field.ProtectCtrl = 0; | |
5423 | Protect[0] = ProtCfg.word; | |
5424 | Protect[1] = ProtCfg.word; | |
5425 | } | |
5426 | else | |
5427 | { | |
5428 | //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; | |
5429 | ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected | |
5430 | Protect[0] = ProtCfg.word; | |
5431 | ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect | |
5432 | Protect[1] = ProtCfg.word; | |
5433 | } | |
5434 | ||
5435 | #ifdef DOT11_N_SUPPORT | |
5436 | // Decide HT frame protection. | |
5437 | if ((SetMask & ALLN_SETPROTECT) != 0) | |
5438 | { | |
5439 | switch(OperationMode) | |
5440 | { | |
5441 | case 0x0: | |
5442 | // NO PROTECT | |
5443 | // 1.All STAs in the BSS are 20/40 MHz HT | |
5444 | // 2. in ai 20/40MHz BSS | |
5445 | // 3. all STAs are 20MHz in a 20MHz BSS | |
5446 | // Pure HT. no protection. | |
5447 | ||
5448 | // MM20_PROT_CFG | |
5449 | // Reserved (31:27) | |
5450 | // PROT_TXOP(25:20) -- 010111 | |
5451 | // PROT_NAV(19:18) -- 01 (Short NAV protection) | |
5452 | // PROT_CTRL(17:16) -- 00 (None) | |
5453 | // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) | |
5454 | Protect[2] = 0x01744004; | |
5455 | ||
5456 | // MM40_PROT_CFG | |
5457 | // Reserved (31:27) | |
5458 | // PROT_TXOP(25:20) -- 111111 | |
5459 | // PROT_NAV(19:18) -- 01 (Short NAV protection) | |
5460 | // PROT_CTRL(17:16) -- 00 (None) | |
5461 | // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) | |
5462 | Protect[3] = 0x03f44084; | |
5463 | ||
5464 | // CF20_PROT_CFG | |
5465 | // Reserved (31:27) | |
5466 | // PROT_TXOP(25:20) -- 010111 | |
5467 | // PROT_NAV(19:18) -- 01 (Short NAV protection) | |
5468 | // PROT_CTRL(17:16) -- 00 (None) | |
5469 | // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) | |
5470 | Protect[4] = 0x01744004; | |
5471 | ||
5472 | // CF40_PROT_CFG | |
5473 | // Reserved (31:27) | |
5474 | // PROT_TXOP(25:20) -- 111111 | |
5475 | // PROT_NAV(19:18) -- 01 (Short NAV protection) | |
5476 | // PROT_CTRL(17:16) -- 00 (None) | |
5477 | // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) | |
5478 | Protect[5] = 0x03f44084; | |
5479 | ||
5480 | if (bNonGFExist) | |
5481 | { | |
5482 | // PROT_NAV(19:18) -- 01 (Short NAV protectiion) | |
5483 | // PROT_CTRL(17:16) -- 01 (RTS/CTS) | |
5484 | Protect[4] = 0x01754004; | |
5485 | Protect[5] = 0x03f54084; | |
5486 | } | |
5487 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; | |
5488 | break; | |
5489 | ||
5490 | case 1: | |
5491 | // This is "HT non-member protection mode." | |
5492 | // If there may be non-HT STAs my BSS | |
5493 | ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) | |
5494 | ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. | |
5495 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) | |
5496 | { | |
5497 | ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. | |
5498 | ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083; | |
5499 | } | |
5500 | //Assign Protection method for 20&40 MHz packets | |
5501 | ProtCfg.field.ProtectCtrl = ASIC_RTS; | |
5502 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | |
5503 | ProtCfg4.field.ProtectCtrl = ASIC_RTS; | |
5504 | ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; | |
5505 | Protect[2] = ProtCfg.word; | |
5506 | Protect[3] = ProtCfg4.word; | |
5507 | Protect[4] = ProtCfg.word; | |
5508 | Protect[5] = ProtCfg4.word; | |
5509 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; | |
5510 | break; | |
5511 | ||
5512 | case 2: | |
5513 | // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets | |
5514 | ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) | |
5515 | ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. | |
5516 | ||
5517 | //Assign Protection method for 40MHz packets | |
5518 | ProtCfg4.field.ProtectCtrl = ASIC_RTS; | |
5519 | ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; | |
5520 | Protect[2] = ProtCfg.word; | |
5521 | Protect[3] = ProtCfg4.word; | |
5522 | if (bNonGFExist) | |
5523 | { | |
5524 | ProtCfg.field.ProtectCtrl = ASIC_RTS; | |
5525 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | |
5526 | } | |
5527 | Protect[4] = ProtCfg.word; | |
5528 | Protect[5] = ProtCfg4.word; | |
5529 | ||
5530 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; | |
5531 | break; | |
5532 | ||
5533 | case 3: | |
5534 | // HT mixed mode. PROTECT ALL! | |
5535 | // Assign Rate | |
5536 | ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1. | |
5537 | ProtCfg4.word = 0x03f44084; | |
5538 | // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the | |
5539 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) | |
5540 | { | |
5541 | ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. | |
5542 | ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083 | |
5543 | } | |
5544 | //Assign Protection method for 20&40 MHz packets | |
5545 | ProtCfg.field.ProtectCtrl = ASIC_RTS; | |
5546 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | |
5547 | ProtCfg4.field.ProtectCtrl = ASIC_RTS; | |
5548 | ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; | |
5549 | Protect[2] = ProtCfg.word; | |
5550 | Protect[3] = ProtCfg4.word; | |
5551 | Protect[4] = ProtCfg.word; | |
5552 | Protect[5] = ProtCfg4.word; | |
5553 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; | |
5554 | break; | |
5555 | ||
5556 | case 8: | |
5557 | // Special on for Atheros problem n chip. | |
5558 | Protect[2] = 0x01754004; | |
5559 | Protect[3] = 0x03f54084; | |
5560 | Protect[4] = 0x01754004; | |
5561 | Protect[5] = 0x03f54084; | |
5562 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; | |
5563 | break; | |
5564 | } | |
5565 | } | |
5566 | #endif // DOT11_N_SUPPORT // | |
5567 | ||
5568 | offset = CCK_PROT_CFG; | |
5569 | for (i = 0;i < 6;i++) | |
5570 | { | |
5571 | if ((SetMask & (1<< i))) | |
5572 | { | |
5573 | RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); | |
5574 | } | |
5575 | } | |
5576 | } | |
5577 | ||
5578 | /* | |
5579 | ========================================================================== | |
5580 | Description: | |
5581 | ||
5582 | IRQL = PASSIVE_LEVEL | |
5583 | IRQL = DISPATCH_LEVEL | |
5584 | ||
5585 | ========================================================================== | |
5586 | */ | |
5587 | VOID AsicSwitchChannel( | |
5588 | IN PRTMP_ADAPTER pAd, | |
5589 | IN UCHAR Channel, | |
5590 | IN BOOLEAN bScan) | |
5591 | { | |
5592 | ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; | |
5593 | CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; | |
5594 | UCHAR index; | |
5595 | UINT32 Value = 0; //BbpReg, Value; | |
5596 | RTMP_RF_REGS *RFRegTable; | |
5597 | ||
5598 | // Search Tx power value | |
5599 | for (index = 0; index < pAd->ChannelListNum; index++) | |
5600 | { | |
5601 | if (Channel == pAd->ChannelList[index].Channel) | |
5602 | { | |
5603 | TxPwer = pAd->ChannelList[index].Power; | |
5604 | TxPwer2 = pAd->ChannelList[index].Power2; | |
5605 | break; | |
5606 | } | |
5607 | } | |
5608 | ||
5609 | if (index == MAX_NUM_OF_CHANNELS) | |
5610 | { | |
5611 | DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel)); | |
5612 | } | |
5613 | ||
5614 | { | |
5615 | RFRegTable = RF2850RegTable; | |
5616 | ||
5617 | switch (pAd->RfIcType) | |
5618 | { | |
5619 | case RFIC_2820: | |
5620 | case RFIC_2850: | |
5621 | case RFIC_2720: | |
5622 | case RFIC_2750: | |
5623 | ||
5624 | for (index = 0; index < NUM_OF_2850_CHNL; index++) | |
5625 | { | |
5626 | if (Channel == RFRegTable[index].Channel) | |
5627 | { | |
5628 | R2 = RFRegTable[index].R2; | |
5629 | if (pAd->Antenna.field.TxPath == 1) | |
5630 | { | |
5631 | R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; | |
5632 | } | |
5633 | ||
5634 | if (pAd->Antenna.field.RxPath == 2) | |
5635 | { | |
5636 | R2 |= 0x40; // write 1 to off Rxpath. | |
5637 | } | |
5638 | else if (pAd->Antenna.field.RxPath == 1) | |
5639 | { | |
5640 | R2 |= 0x20040; // write 1 to off RxPath | |
5641 | } | |
5642 | ||
5643 | if (Channel > 14) | |
5644 | { | |
5645 | // initialize R3, R4 | |
5646 | R3 = (RFRegTable[index].R3 & 0xffffc1ff); | |
5647 | R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15); | |
5648 | ||
5649 | // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB | |
5650 | // R3 | |
5651 | if ((TxPwer >= -7) && (TxPwer < 0)) | |
5652 | { | |
5653 | TxPwer = (7+TxPwer); | |
5654 | TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); | |
5655 | R3 |= (TxPwer << 10); | |
5656 | DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer)); | |
5657 | } | |
5658 | else | |
5659 | { | |
5660 | TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); | |
5661 | R3 |= (TxPwer << 10) | (1 << 9); | |
5662 | } | |
5663 | ||
5664 | // R4 | |
5665 | if ((TxPwer2 >= -7) && (TxPwer2 < 0)) | |
5666 | { | |
5667 | TxPwer2 = (7+TxPwer2); | |
5668 | TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); | |
5669 | R4 |= (TxPwer2 << 7); | |
5670 | DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); | |
5671 | } | |
5672 | else | |
5673 | { | |
5674 | TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); | |
5675 | R4 |= (TxPwer2 << 7) | (1 << 6); | |
5676 | } | |
5677 | } | |
5678 | else | |
5679 | { | |
5680 | R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 | |
5681 | R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1 | |
5682 | } | |
5683 | ||
5684 | // Based on BBP current mode before changing RF channel. | |
5685 | if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) | |
5686 | { | |
5687 | R4 |=0x200000; | |
5688 | } | |
5689 | ||
5690 | // Update variables | |
5691 | pAd->LatchRfRegs.Channel = Channel; | |
5692 | pAd->LatchRfRegs.R1 = RFRegTable[index].R1; | |
5693 | pAd->LatchRfRegs.R2 = R2; | |
5694 | pAd->LatchRfRegs.R3 = R3; | |
5695 | pAd->LatchRfRegs.R4 = R4; | |
5696 | ||
5697 | // Set RF value 1's set R3[bit2] = [0] | |
5698 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); | |
5699 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); | |
5700 | RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); | |
5701 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); | |
5702 | ||
5703 | RTMPusecDelay(200); | |
5704 | ||
5705 | // Set RF value 2's set R3[bit2] = [1] | |
5706 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); | |
5707 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); | |
5708 | RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); | |
5709 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); | |
5710 | ||
5711 | RTMPusecDelay(200); | |
5712 | ||
5713 | // Set RF value 3's set R3[bit2] = [0] | |
5714 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); | |
5715 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); | |
5716 | RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); | |
5717 | RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); | |
5718 | ||
5719 | break; | |
5720 | } | |
5721 | } | |
5722 | break; | |
5723 | ||
5724 | default: | |
5725 | break; | |
5726 | } | |
5727 | } | |
5728 | ||
5729 | // Change BBP setting during siwtch from a->g, g->a | |
5730 | if (Channel <= 14) | |
5731 | { | |
5732 | ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A | |
5733 | ||
5734 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); | |
5735 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); | |
5736 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); | |
5737 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. | |
5738 | //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); | |
5739 | ||
5740 | // Rx High power VGA offset for LNA select | |
5741 | if (pAd->NicConfig2.field.ExternalLNAForG) | |
5742 | { | |
5743 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); | |
5744 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); | |
5745 | } | |
5746 | else | |
5747 | { | |
5748 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); | |
5749 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); | |
5750 | } | |
5751 | ||
5752 | // 5G band selection PIN, bit1 and bit2 are complement | |
5753 | RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); | |
5754 | Value &= (~0x6); | |
5755 | Value |= (0x04); | |
5756 | RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); | |
5757 | ||
5758 | // Turn off unused PA or LNA when only 1T or 1R | |
5759 | if (pAd->Antenna.field.TxPath == 1) | |
5760 | { | |
5761 | TxPinCfg &= 0xFFFFFFF3; | |
5762 | } | |
5763 | if (pAd->Antenna.field.RxPath == 1) | |
5764 | { | |
5765 | TxPinCfg &= 0xFFFFF3FF; | |
5766 | } | |
5767 | ||
5768 | RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); | |
5769 | } | |
5770 | else | |
5771 | { | |
5772 | ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 | |
5773 | ||
5774 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); | |
5775 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); | |
5776 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); | |
5777 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. | |
5778 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); | |
5779 | ||
5780 | // Rx High power VGA offset for LNA select | |
5781 | if (pAd->NicConfig2.field.ExternalLNAForA) | |
5782 | { | |
5783 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); | |
5784 | } | |
5785 | else | |
5786 | { | |
5787 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); | |
5788 | } | |
5789 | ||
5790 | // 5G band selection PIN, bit1 and bit2 are complement | |
5791 | RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); | |
5792 | Value &= (~0x6); | |
5793 | Value |= (0x02); | |
5794 | RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); | |
5795 | ||
5796 | // Turn off unused PA or LNA when only 1T or 1R | |
5797 | if (pAd->Antenna.field.TxPath == 1) | |
5798 | { | |
5799 | TxPinCfg &= 0xFFFFFFF3; | |
5800 | } | |
5801 | if (pAd->Antenna.field.RxPath == 1) | |
5802 | { | |
5803 | TxPinCfg &= 0xFFFFF3FF; | |
5804 | } | |
5805 | ||
5806 | RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); | |
5807 | } | |
5808 | ||
5809 | // R66 should be set according to Channel and use 20MHz when scanning | |
5810 | //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); | |
5811 | if (bScan) | |
5812 | RTMPSetAGCInitValue(pAd, BW_20); | |
5813 | else | |
5814 | RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); | |
5815 | ||
5816 | // | |
5817 | // On 11A, We should delay and wait RF/BBP to be stable | |
5818 | // and the appropriate time should be 1000 micro seconds | |
5819 | // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. | |
5820 | // | |
5821 | RTMPusecDelay(1000); | |
5822 | ||
5823 | DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", | |
5824 | Channel, | |
5825 | pAd->RfIcType, | |
5826 | (R3 & 0x00003e00) >> 9, | |
5827 | (R4 & 0x000007c0) >> 6, | |
5828 | pAd->Antenna.field.TxPath, | |
5829 | pAd->LatchRfRegs.R1, | |
5830 | pAd->LatchRfRegs.R2, | |
5831 | pAd->LatchRfRegs.R3, | |
5832 | pAd->LatchRfRegs.R4)); | |
5833 | } | |
5834 | ||
5835 | /* | |
5836 | ========================================================================== | |
5837 | Description: | |
5838 | This function is required for 2421 only, and should not be used during | |
5839 | site survey. It's only required after NIC decided to stay at a channel | |
5840 | for a longer period. | |
5841 | When this function is called, it's always after AsicSwitchChannel(). | |
5842 | ||
5843 | IRQL = PASSIVE_LEVEL | |
5844 | IRQL = DISPATCH_LEVEL | |
5845 | ||
5846 | ========================================================================== | |
5847 | */ | |
5848 | VOID AsicLockChannel( | |
5849 | IN PRTMP_ADAPTER pAd, | |
5850 | IN UCHAR Channel) | |
5851 | { | |
5852 | } | |
5853 | ||
5854 | /* | |
5855 | ========================================================================== | |
5856 | Description: | |
5857 | ||
5858 | IRQL = PASSIVE_LEVEL | |
5859 | IRQL = DISPATCH_LEVEL | |
5860 | ||
5861 | ========================================================================== | |
5862 | */ | |
5863 | VOID AsicAntennaSelect( | |
5864 | IN PRTMP_ADAPTER pAd, | |
5865 | IN UCHAR Channel) | |
5866 | { | |
5867 | } | |
5868 | ||
5869 | /* | |
5870 | ======================================================================== | |
5871 | ||
5872 | Routine Description: | |
5873 | Antenna miscellaneous setting. | |
5874 | ||
5875 | Arguments: | |
5876 | pAd Pointer to our adapter | |
5877 | BandState Indicate current Band State. | |
5878 | ||
5879 | Return Value: | |
5880 | None | |
5881 | ||
5882 | IRQL <= DISPATCH_LEVEL | |
5883 | ||
5884 | Note: | |
5885 | 1.) Frame End type control | |
5886 | only valid for G only (RF_2527 & RF_2529) | |
5887 | 0: means DPDT, set BBP R4 bit 5 to 1 | |
5888 | 1: means SPDT, set BBP R4 bit 5 to 0 | |
5889 | ||
5890 | ||
5891 | ======================================================================== | |
5892 | */ | |
5893 | VOID AsicAntennaSetting( | |
5894 | IN PRTMP_ADAPTER pAd, | |
5895 | IN ABGBAND_STATE BandState) | |
5896 | { | |
5897 | } | |
5898 | ||
5899 | VOID AsicRfTuningExec( | |
5900 | IN PVOID SystemSpecific1, | |
5901 | IN PVOID FunctionContext, | |
5902 | IN PVOID SystemSpecific2, | |
5903 | IN PVOID SystemSpecific3) | |
5904 | { | |
5905 | } | |
5906 | ||
5907 | /* | |
5908 | ========================================================================== | |
5909 | Description: | |
5910 | Gives CCK TX rate 2 more dB TX power. | |
5911 | This routine works only in LINK UP in INFRASTRUCTURE mode. | |
5912 | ||
5913 | calculate desired Tx power in RF R3.Tx0~5, should consider - | |
5914 | 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) | |
5915 | 1. TxPowerPercentage | |
5916 | 2. auto calibration based on TSSI feedback | |
5917 | 3. extra 2 db for CCK | |
5918 | 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP | |
5919 | ||
5920 | NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), | |
5921 | it should be called AFTER MlmeDynamicTxRatSwitching() | |
5922 | ========================================================================== | |
5923 | */ | |
5924 | VOID AsicAdjustTxPower( | |
5925 | IN PRTMP_ADAPTER pAd) | |
5926 | { | |
5927 | INT i, j; | |
5928 | CHAR DeltaPwr = 0; | |
5929 | BOOLEAN bAutoTxAgc = FALSE; | |
5930 | UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; | |
5931 | UCHAR BbpR1 = 0, BbpR49 = 0, idx; | |
5932 | PCHAR pTxAgcCompensate; | |
5933 | ULONG TxPwr[5]; | |
5934 | CHAR Value; | |
5935 | ||
ed291e80 AM |
5936 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) |
5937 | || (pAd->bPCIclkOff == TRUE) | |
5938 | || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) | |
5939 | || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | |
5940 | return; | |
5941 | ||
91980990 GKH |
5942 | if (pAd->CommonCfg.BBPCurrentBW == BW_40) |
5943 | { | |
5944 | if (pAd->CommonCfg.CentralChannel > 14) | |
5945 | { | |
5946 | TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; | |
5947 | TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; | |
5948 | TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; | |
5949 | TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; | |
5950 | TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; | |
5951 | } | |
5952 | else | |
5953 | { | |
5954 | TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; | |
5955 | TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; | |
5956 | TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; | |
5957 | TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; | |
5958 | TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; | |
5959 | } | |
5960 | } | |
5961 | else | |
5962 | { | |
5963 | if (pAd->CommonCfg.Channel > 14) | |
5964 | { | |
5965 | TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; | |
5966 | TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; | |
5967 | TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; | |
5968 | TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; | |
5969 | TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; | |
5970 | } | |
5971 | else | |
5972 | { | |
5973 | TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; | |
5974 | TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; | |
5975 | TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; | |
5976 | TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; | |
5977 | TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; | |
5978 | } | |
5979 | } | |
5980 | ||
5981 | // TX power compensation for temperature variation based on TSSI. try every 4 second | |
5982 | if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) | |
5983 | { | |
5984 | if (pAd->CommonCfg.Channel <= 14) | |
5985 | { | |
5986 | /* bg channel */ | |
5987 | bAutoTxAgc = pAd->bAutoTxAgcG; | |
5988 | TssiRef = pAd->TssiRefG; | |
5989 | pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; | |
5990 | pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; | |
5991 | TxAgcStep = pAd->TxAgcStepG; | |
5992 | pTxAgcCompensate = &pAd->TxAgcCompensateG; | |
5993 | } | |
5994 | else | |
5995 | { | |
5996 | /* a channel */ | |
5997 | bAutoTxAgc = pAd->bAutoTxAgcA; | |
5998 | TssiRef = pAd->TssiRefA; | |
5999 | pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; | |
6000 | pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; | |
6001 | TxAgcStep = pAd->TxAgcStepA; | |
6002 | pTxAgcCompensate = &pAd->TxAgcCompensateA; | |
6003 | } | |
6004 | ||
6005 | if (bAutoTxAgc) | |
6006 | { | |
6007 | /* BbpR1 is unsigned char */ | |
6008 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); | |
6009 | ||
6010 | /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ | |
6011 | /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ | |
6012 | /* step value is defined in pAd->TxAgcStepG for tx power value */ | |
6013 | ||
6014 | /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ | |
6015 | /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 | |
6016 | above value are examined in mass factory production */ | |
6017 | /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ | |
6018 | ||
6019 | /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ | |
6020 | /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ | |
6021 | /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ | |
6022 | ||
6023 | if (BbpR49 > pTssiMinusBoundary[1]) | |
6024 | { | |
6025 | // Reading is larger than the reference value | |
6026 | // check for how large we need to decrease the Tx power | |
6027 | for (idx = 1; idx < 5; idx++) | |
6028 | { | |
6029 | if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range | |
6030 | break; | |
6031 | } | |
6032 | // The index is the step we should decrease, idx = 0 means there is nothing to compensate | |
6033 | *pTxAgcCompensate = -(TxAgcStep * (idx-1)); | |
6034 | ||
6035 | DeltaPwr += (*pTxAgcCompensate); | |
6036 | DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", | |
6037 | BbpR49, TssiRef, TxAgcStep, idx-1)); | |
6038 | } | |
6039 | else if (BbpR49 < pTssiPlusBoundary[1]) | |
6040 | { | |
6041 | // Reading is smaller than the reference value | |
6042 | // check for how large we need to increase the Tx power | |
6043 | for (idx = 1; idx < 5; idx++) | |
6044 | { | |
6045 | if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range | |
6046 | break; | |
6047 | } | |
6048 | // The index is the step we should increase, idx = 0 means there is nothing to compensate | |
6049 | *pTxAgcCompensate = TxAgcStep * (idx-1); | |
6050 | DeltaPwr += (*pTxAgcCompensate); | |
6051 | DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", | |
6052 | BbpR49, TssiRef, TxAgcStep, idx-1)); | |
6053 | } | |
6054 | else | |
6055 | { | |
6056 | *pTxAgcCompensate = 0; | |
6057 | DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", | |
6058 | BbpR49, TssiRef, TxAgcStep, 0)); | |
6059 | } | |
6060 | } | |
6061 | } | |
6062 | else | |
6063 | { | |
6064 | if (pAd->CommonCfg.Channel <= 14) | |
6065 | { | |
6066 | bAutoTxAgc = pAd->bAutoTxAgcG; | |
6067 | pTxAgcCompensate = &pAd->TxAgcCompensateG; | |
6068 | } | |
6069 | else | |
6070 | { | |
6071 | bAutoTxAgc = pAd->bAutoTxAgcA; | |
6072 | pTxAgcCompensate = &pAd->TxAgcCompensateA; | |
6073 | } | |
6074 | ||
6075 | if (bAutoTxAgc) | |
6076 | DeltaPwr += (*pTxAgcCompensate); | |
6077 | } | |
6078 | ||
6079 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); | |
6080 | BbpR1 &= 0xFC; | |
6081 | ||
91980990 GKH |
6082 | /* calculate delta power based on the percentage specified from UI */ |
6083 | // E2PROM setting is calibrated for maximum TX power (i.e. 100%) | |
6084 | // We lower TX power here according to the percentage specified from UI | |
6085 | if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control | |
6086 | ; | |
6087 | else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW | |
6088 | ; | |
6089 | else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; | |
6090 | { | |
6091 | DeltaPwr -= 1; | |
6092 | } | |
6093 | else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; | |
6094 | { | |
6095 | DeltaPwr -= 3; | |
6096 | } | |
6097 | else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; | |
6098 | { | |
6099 | BbpR1 |= 0x01; | |
6100 | } | |
6101 | else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; | |
6102 | { | |
6103 | BbpR1 |= 0x01; | |
6104 | DeltaPwr -= 3; | |
6105 | } | |
6106 | else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; | |
6107 | { | |
6108 | BbpR1 |= 0x02; | |
6109 | } | |
6110 | ||
6111 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); | |
6112 | ||
6113 | /* reset different new tx power for different TX rate */ | |
6114 | for(i=0; i<5; i++) | |
6115 | { | |
6116 | if (TxPwr[i] != 0xffffffff) | |
6117 | { | |
6118 | for (j=0; j<8; j++) | |
6119 | { | |
6120 | Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ | |
6121 | ||
6122 | if ((Value + DeltaPwr) < 0) | |
6123 | { | |
6124 | Value = 0; /* min */ | |
6125 | } | |
6126 | else if ((Value + DeltaPwr) > 0xF) | |
6127 | { | |
6128 | Value = 0xF; /* max */ | |
6129 | } | |
6130 | else | |
6131 | { | |
6132 | Value += DeltaPwr; /* temperature compensation */ | |
6133 | } | |
6134 | ||
6135 | /* fill new value to CSR offset */ | |
6136 | TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); | |
6137 | } | |
6138 | ||
6139 | /* write tx power value to CSR */ | |
6140 | /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M | |
6141 | TX power for OFDM 6M/9M | |
6142 | TX power for CCK5.5M/11M | |
6143 | TX power for CCK1M/2M */ | |
6144 | /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ | |
6145 | RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); | |
6146 | } | |
6147 | } | |
6148 | ||
6149 | } | |
6150 | ||
6151 | #ifdef CONFIG_STA_SUPPORT | |
6152 | /* | |
6153 | ========================================================================== | |
6154 | Description: | |
6155 | put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup | |
6156 | automatically. Instead, MCU will issue a TwakeUpInterrupt to host after | |
6157 | the wakeup timer timeout. Driver has to issue a separate command to wake | |
6158 | PHY up. | |
6159 | ||
6160 | IRQL = DISPATCH_LEVEL | |
6161 | ||
6162 | ========================================================================== | |
6163 | */ | |
6164 | VOID AsicSleepThenAutoWakeup( | |
6165 | IN PRTMP_ADAPTER pAd, | |
6166 | IN USHORT TbttNumToNextWakeUp) | |
6167 | { | |
6168 | RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); | |
6169 | } | |
6170 | ||
6171 | /* | |
6172 | ========================================================================== | |
6173 | Description: | |
6174 | AsicForceWakeup() is used whenever manual wakeup is required | |
6175 | AsicForceSleep() should only be used when not in INFRA BSS. When | |
6176 | in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. | |
6177 | ========================================================================== | |
6178 | */ | |
6179 | VOID AsicForceSleep( | |
6180 | IN PRTMP_ADAPTER pAd) | |
6181 | { | |
6182 | ||
6183 | } | |
6184 | ||
6185 | /* | |
6186 | ========================================================================== | |
6187 | Description: | |
6188 | AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) | |
6189 | expired. | |
6190 | ||
6191 | IRQL = PASSIVE_LEVEL | |
6192 | IRQL = DISPATCH_LEVEL | |
6193 | ========================================================================== | |
6194 | */ | |
6195 | VOID AsicForceWakeup( | |
6196 | IN PRTMP_ADAPTER pAd, | |
ed291e80 | 6197 | IN UCHAR Level) |
91980990 GKH |
6198 | { |
6199 | DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n")); | |
ed291e80 | 6200 | RT28XX_STA_FORCE_WAKEUP(pAd, Level); |
91980990 GKH |
6201 | } |
6202 | #endif // CONFIG_STA_SUPPORT // | |
6203 | /* | |
6204 | ========================================================================== | |
6205 | Description: | |
6206 | Set My BSSID | |
6207 | ||
6208 | IRQL = DISPATCH_LEVEL | |
6209 | ||
6210 | ========================================================================== | |
6211 | */ | |
6212 | VOID AsicSetBssid( | |
6213 | IN PRTMP_ADAPTER pAd, | |
6214 | IN PUCHAR pBssid) | |
6215 | { | |
6216 | ULONG Addr4; | |
6217 | DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", | |
6218 | pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5])); | |
6219 | ||
6220 | Addr4 = (ULONG)(pBssid[0]) | | |
6221 | (ULONG)(pBssid[1] << 8) | | |
6222 | (ULONG)(pBssid[2] << 16) | | |
6223 | (ULONG)(pBssid[3] << 24); | |
6224 | RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); | |
6225 | ||
6226 | Addr4 = 0; | |
6227 | // always one BSSID in STA mode | |
6228 | Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); | |
6229 | ||
6230 | RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); | |
6231 | } | |
6232 | ||
6233 | VOID AsicSetMcastWC( | |
6234 | IN PRTMP_ADAPTER pAd) | |
6235 | { | |
6236 | MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; | |
6237 | USHORT offset; | |
6238 | ||
6239 | pEntry->Sst = SST_ASSOC; | |
6240 | pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index | |
6241 | pEntry->PsMode = PWR_ACTIVE; | |
6242 | pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; | |
6243 | offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; | |
6244 | } | |
6245 | ||
6246 | /* | |
6247 | ========================================================================== | |
6248 | Description: | |
6249 | ||
6250 | IRQL = DISPATCH_LEVEL | |
6251 | ||
6252 | ========================================================================== | |
6253 | */ | |
6254 | VOID AsicDelWcidTab( | |
6255 | IN PRTMP_ADAPTER pAd, | |
6256 | IN UCHAR Wcid) | |
6257 | { | |
6258 | ULONG Addr0 = 0x0, Addr1 = 0x0; | |
6259 | ULONG offset; | |
6260 | ||
6261 | DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid)); | |
6262 | offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; | |
6263 | RTMP_IO_WRITE32(pAd, offset, Addr0); | |
6264 | offset += 4; | |
6265 | RTMP_IO_WRITE32(pAd, offset, Addr1); | |
6266 | } | |
6267 | ||
6268 | /* | |
6269 | ========================================================================== | |
6270 | Description: | |
6271 | ||
6272 | IRQL = DISPATCH_LEVEL | |
6273 | ||
6274 | ========================================================================== | |
6275 | */ | |
6276 | VOID AsicEnableRDG( | |
6277 | IN PRTMP_ADAPTER pAd) | |
6278 | { | |
6279 | TX_LINK_CFG_STRUC TxLinkCfg; | |
6280 | UINT32 Data = 0; | |
6281 | ||
6282 | RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); | |
6283 | TxLinkCfg.field.TxRDGEn = 1; | |
6284 | RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); | |
6285 | ||
6286 | RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); | |
6287 | Data &= 0xFFFFFF00; | |
6288 | Data |= 0x80; | |
6289 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); | |
6290 | ||
6291 | //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); | |
6292 | } | |
6293 | ||
6294 | /* | |
6295 | ========================================================================== | |
6296 | Description: | |
6297 | ||
6298 | IRQL = DISPATCH_LEVEL | |
6299 | ||
6300 | ========================================================================== | |
6301 | */ | |
6302 | VOID AsicDisableRDG( | |
6303 | IN PRTMP_ADAPTER pAd) | |
6304 | { | |
6305 | TX_LINK_CFG_STRUC TxLinkCfg; | |
6306 | UINT32 Data = 0; | |
6307 | ||
6308 | ||
6309 | RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); | |
6310 | TxLinkCfg.field.TxRDGEn = 0; | |
6311 | RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); | |
6312 | ||
6313 | RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); | |
6314 | ||
6315 | Data &= 0xFFFFFF00; | |
6316 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) | |
6317 | #ifdef DOT11_N_SUPPORT | |
6318 | && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) | |
6319 | #endif // DOT11_N_SUPPORT // | |
6320 | ) | |
6321 | { | |
6322 | // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode | |
6323 | if (pAd->CommonCfg.bEnableTxBurst) | |
6324 | Data |= 0x20; | |
6325 | } | |
6326 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); | |
6327 | } | |
6328 | ||
6329 | /* | |
6330 | ========================================================================== | |
6331 | Description: | |
6332 | ||
6333 | IRQL = PASSIVE_LEVEL | |
6334 | IRQL = DISPATCH_LEVEL | |
6335 | ||
6336 | ========================================================================== | |
6337 | */ | |
6338 | VOID AsicDisableSync( | |
6339 | IN PRTMP_ADAPTER pAd) | |
6340 | { | |
6341 | BCN_TIME_CFG_STRUC csr; | |
6342 | ||
6343 | DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); | |
6344 | ||
6345 | // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect | |
6346 | // that NIC will never wakes up because TSF stops and no more | |
6347 | // TBTT interrupts | |
6348 | pAd->TbttTickCount = 0; | |
6349 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
6350 | csr.field.bBeaconGen = 0; | |
6351 | csr.field.bTBTTEnable = 0; | |
6352 | csr.field.TsfSyncMode = 0; | |
6353 | csr.field.bTsfTicking = 0; | |
6354 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | |
6355 | ||
6356 | } | |
6357 | ||
6358 | /* | |
6359 | ========================================================================== | |
6360 | Description: | |
6361 | ||
6362 | IRQL = DISPATCH_LEVEL | |
6363 | ||
6364 | ========================================================================== | |
6365 | */ | |
6366 | VOID AsicEnableBssSync( | |
6367 | IN PRTMP_ADAPTER pAd) | |
6368 | { | |
6369 | BCN_TIME_CFG_STRUC csr; | |
6370 | ||
6371 | DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); | |
6372 | ||
6373 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | |
6374 | #ifdef CONFIG_STA_SUPPORT | |
6375 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
6376 | { | |
6377 | csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU | |
6378 | csr.field.bTsfTicking = 1; | |
6379 | csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode | |
6380 | csr.field.bBeaconGen = 0; // do NOT generate BEACON | |
6381 | csr.field.bTBTTEnable = 1; | |
6382 | } | |
6383 | #endif // CONFIG_STA_SUPPORT // | |
6384 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | |
6385 | } | |
6386 | ||
6387 | /* | |
6388 | ========================================================================== | |
6389 | Description: | |
6390 | Note: | |
6391 | BEACON frame in shared memory should be built ok before this routine | |
6392 | can be called. Otherwise, a garbage frame maybe transmitted out every | |
6393 | Beacon period. | |
6394 | ||
6395 | IRQL = DISPATCH_LEVEL | |
6396 | ||
6397 | ========================================================================== | |
6398 | */ | |
6399 | VOID AsicEnableIbssSync( | |
6400 | IN PRTMP_ADAPTER pAd) | |
6401 | { | |
6402 | BCN_TIME_CFG_STRUC csr9; | |
6403 | PUCHAR ptr; | |
6404 | UINT i; | |
6405 | ||
6406 | DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount)); | |
6407 | ||
6408 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); | |
6409 | csr9.field.bBeaconGen = 0; | |
6410 | csr9.field.bTBTTEnable = 0; | |
6411 | csr9.field.bTsfTicking = 0; | |
6412 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); | |
6413 | ||
91980990 GKH |
6414 | // move BEACON TXD and frame content to on-chip memory |
6415 | ptr = (PUCHAR)&pAd->BeaconTxWI; | |
6416 | for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field | |
6417 | { | |
6418 | UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); | |
6419 | RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); | |
6420 | ptr += 4; | |
6421 | } | |
6422 | ||
6423 | // start right after the 16-byte TXWI field | |
6424 | ptr = pAd->BeaconBuf; | |
6425 | for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4) | |
6426 | { | |
6427 | UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); | |
6428 | RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); | |
6429 | ptr +=4; | |
6430 | } | |
91980990 GKH |
6431 | |
6432 | // start sending BEACON | |
6433 | csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU | |
6434 | csr9.field.bTsfTicking = 1; | |
6435 | csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode | |
6436 | csr9.field.bTBTTEnable = 1; | |
6437 | csr9.field.bBeaconGen = 1; | |
6438 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); | |
6439 | } | |
6440 | ||
6441 | /* | |
6442 | ========================================================================== | |
6443 | Description: | |
6444 | ||
6445 | IRQL = PASSIVE_LEVEL | |
6446 | IRQL = DISPATCH_LEVEL | |
6447 | ||
6448 | ========================================================================== | |
6449 | */ | |
6450 | VOID AsicSetEdcaParm( | |
6451 | IN PRTMP_ADAPTER pAd, | |
6452 | IN PEDCA_PARM pEdcaParm) | |
6453 | { | |
6454 | EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; | |
6455 | AC_TXOP_CSR0_STRUC csr0; | |
6456 | AC_TXOP_CSR1_STRUC csr1; | |
6457 | AIFSN_CSR_STRUC AifsnCsr; | |
6458 | CWMIN_CSR_STRUC CwminCsr; | |
6459 | CWMAX_CSR_STRUC CwmaxCsr; | |
6460 | int i; | |
6461 | ||
6462 | Ac0Cfg.word = 0; | |
6463 | Ac1Cfg.word = 0; | |
6464 | Ac2Cfg.word = 0; | |
6465 | Ac3Cfg.word = 0; | |
6466 | if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) | |
6467 | { | |
6468 | DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); | |
6469 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); | |
6470 | for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++) | |
6471 | { | |
6472 | if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli) | |
6473 | CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); | |
6474 | } | |
6475 | ||
6476 | //======================================================== | |
6477 | // MAC Register has a copy . | |
6478 | //======================================================== | |
6479 | if( pAd->CommonCfg.bEnableTxBurst ) | |
6480 | { | |
6481 | // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode | |
6482 | Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode | |
6483 | } | |
6484 | else | |
6485 | Ac0Cfg.field.AcTxop = 0; // QID_AC_BE | |
6486 | Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; | |
6487 | Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; | |
6488 | Ac0Cfg.field.Aifsn = 2; | |
6489 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); | |
6490 | ||
6491 | Ac1Cfg.field.AcTxop = 0; // QID_AC_BK | |
6492 | Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; | |
6493 | Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; | |
6494 | Ac1Cfg.field.Aifsn = 2; | |
6495 | RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); | |
6496 | ||
6497 | if (pAd->CommonCfg.PhyMode == PHY_11B) | |
6498 | { | |
6499 | Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms | |
6500 | Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms | |
6501 | } | |
6502 | else | |
6503 | { | |
6504 | Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms | |
6505 | Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms | |
6506 | } | |
6507 | Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; | |
6508 | Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; | |
6509 | Ac2Cfg.field.Aifsn = 2; | |
6510 | RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); | |
6511 | Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; | |
6512 | Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; | |
6513 | Ac3Cfg.field.Aifsn = 2; | |
6514 | RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); | |
6515 | ||
6516 | //======================================================== | |
6517 | // DMA Register has a copy too. | |
6518 | //======================================================== | |
6519 | csr0.field.Ac0Txop = 0; // QID_AC_BE | |
6520 | csr0.field.Ac1Txop = 0; // QID_AC_BK | |
6521 | RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); | |
6522 | if (pAd->CommonCfg.PhyMode == PHY_11B) | |
6523 | { | |
6524 | csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms | |
6525 | csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms | |
6526 | } | |
6527 | else | |
6528 | { | |
6529 | csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms | |
6530 | csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms | |
6531 | } | |
6532 | RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); | |
6533 | ||
6534 | CwminCsr.word = 0; | |
6535 | CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; | |
6536 | CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; | |
6537 | CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; | |
6538 | CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; | |
6539 | RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); | |
6540 | ||
6541 | CwmaxCsr.word = 0; | |
6542 | CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; | |
6543 | CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; | |
6544 | CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; | |
6545 | CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; | |
6546 | RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); | |
6547 | ||
6548 | RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); | |
6549 | ||
6550 | NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); | |
6551 | } | |
6552 | else | |
6553 | { | |
6554 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); | |
6555 | //======================================================== | |
6556 | // MAC Register has a copy. | |
6557 | //======================================================== | |
6558 | // | |
6559 | // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 | |
6560 | // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. | |
6561 | // | |
6562 | //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this | |
6563 | ||
6564 | Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; | |
6565 | Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE]; | |
6566 | Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; | |
6567 | Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1; | |
6568 | ||
6569 | Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; | |
6570 | Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2; | |
6571 | Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; | |
6572 | Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1; | |
6573 | ||
6574 | Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; | |
6575 | Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; | |
6576 | Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; | |
6577 | Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI]; | |
6578 | #ifdef CONFIG_STA_SUPPORT | |
6579 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
6580 | { | |
6581 | // Tuning for Wi-Fi WMM S06 | |
6582 | if (pAd->CommonCfg.bWiFiTest && | |
6583 | pEdcaParm->Aifsn[QID_AC_VI] == 10) | |
6584 | Ac2Cfg.field.Aifsn -= 1; | |
6585 | ||
6586 | // Tuning for TGn Wi-Fi 5.2.32 | |
6587 | // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta | |
6588 | if (STA_TGN_WIFI_ON(pAd) && | |
6589 | pEdcaParm->Aifsn[QID_AC_VI] == 10) | |
6590 | { | |
6591 | Ac0Cfg.field.Aifsn = 3; | |
6592 | Ac2Cfg.field.AcTxop = 5; | |
6593 | } | |
6594 | } | |
6595 | #endif // CONFIG_STA_SUPPORT // | |
6596 | ||
6597 | Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; | |
6598 | Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; | |
6599 | Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; | |
6600 | Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; | |
6601 | ||
6602 | //#ifdef WIFI_TEST | |
6603 | if (pAd->CommonCfg.bWiFiTest) | |
6604 | { | |
6605 | if (Ac3Cfg.field.AcTxop == 102) | |
6606 | { | |
6607 | Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10; | |
6608 | Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */ | |
6609 | Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; | |
6610 | Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; | |
6611 | Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI]; | |
6612 | } /* End of if */ | |
6613 | } | |
6614 | //#endif // WIFI_TEST // | |
6615 | ||
6616 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); | |
6617 | RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); | |
6618 | RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); | |
6619 | RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); | |
6620 | ||
6621 | ||
6622 | //======================================================== | |
6623 | // DMA Register has a copy too. | |
6624 | //======================================================== | |
6625 | csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; | |
6626 | csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; | |
6627 | RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); | |
6628 | ||
6629 | csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; | |
6630 | csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; | |
6631 | RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); | |
6632 | ||
6633 | CwminCsr.word = 0; | |
6634 | CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; | |
6635 | CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; | |
6636 | CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; | |
6637 | #ifdef CONFIG_STA_SUPPORT | |
6638 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
6639 | CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test | |
6640 | #endif // CONFIG_STA_SUPPORT // | |
6641 | RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); | |
6642 | ||
6643 | CwmaxCsr.word = 0; | |
6644 | CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; | |
6645 | CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; | |
6646 | CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; | |
6647 | CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; | |
6648 | RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); | |
6649 | ||
6650 | AifsnCsr.word = 0; | |
6651 | AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE]; | |
6652 | AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK]; | |
6653 | AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI]; | |
6654 | #ifdef CONFIG_STA_SUPPORT | |
6655 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
6656 | { | |
6657 | // Tuning for Wi-Fi WMM S06 | |
6658 | if (pAd->CommonCfg.bWiFiTest && | |
6659 | pEdcaParm->Aifsn[QID_AC_VI] == 10) | |
6660 | AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; | |
6661 | ||
6662 | // Tuning for TGn Wi-Fi 5.2.32 | |
6663 | // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta | |
6664 | if (STA_TGN_WIFI_ON(pAd) && | |
6665 | pEdcaParm->Aifsn[QID_AC_VI] == 10) | |
6666 | { | |
6667 | AifsnCsr.field.Aifsn0 = 3; | |
6668 | AifsnCsr.field.Aifsn2 = 7; | |
6669 | } | |
6670 | } | |
6671 | #endif // CONFIG_STA_SUPPORT // | |
6672 | ||
6673 | #ifdef CONFIG_STA_SUPPORT | |
6674 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
6675 | AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test | |
6676 | #endif // CONFIG_STA_SUPPORT // | |
6677 | RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); | |
6678 | ||
6679 | NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); | |
6680 | if (!ADHOC_ON(pAd)) | |
6681 | { | |
6682 | DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount)); | |
6683 | DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n", | |
6684 | pEdcaParm->Aifsn[0], | |
6685 | pEdcaParm->Cwmin[0], | |
6686 | pEdcaParm->Cwmax[0], | |
6687 | pEdcaParm->Txop[0]<<5, | |
6688 | pEdcaParm->bACM[0])); | |
6689 | DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n", | |
6690 | pEdcaParm->Aifsn[1], | |
6691 | pEdcaParm->Cwmin[1], | |
6692 | pEdcaParm->Cwmax[1], | |
6693 | pEdcaParm->Txop[1]<<5, | |
6694 | pEdcaParm->bACM[1])); | |
6695 | DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n", | |
6696 | pEdcaParm->Aifsn[2], | |
6697 | pEdcaParm->Cwmin[2], | |
6698 | pEdcaParm->Cwmax[2], | |
6699 | pEdcaParm->Txop[2]<<5, | |
6700 | pEdcaParm->bACM[2])); | |
6701 | DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n", | |
6702 | pEdcaParm->Aifsn[3], | |
6703 | pEdcaParm->Cwmin[3], | |
6704 | pEdcaParm->Cwmax[3], | |
6705 | pEdcaParm->Txop[3]<<5, | |
6706 | pEdcaParm->bACM[3])); | |
6707 | } | |
6708 | } | |
6709 | } | |
6710 | ||
6711 | /* | |
6712 | ========================================================================== | |
6713 | Description: | |
6714 | ||
6715 | IRQL = PASSIVE_LEVEL | |
6716 | IRQL = DISPATCH_LEVEL | |
6717 | ||
6718 | ========================================================================== | |
6719 | */ | |
6720 | VOID AsicSetSlotTime( | |
6721 | IN PRTMP_ADAPTER pAd, | |
6722 | IN BOOLEAN bUseShortSlotTime) | |
6723 | { | |
6724 | ULONG SlotTime; | |
6725 | UINT32 RegValue = 0; | |
6726 | ||
6727 | #ifdef CONFIG_STA_SUPPORT | |
6728 | if (pAd->CommonCfg.Channel > 14) | |
6729 | bUseShortSlotTime = TRUE; | |
6730 | #endif // CONFIG_STA_SUPPORT // | |
6731 | ||
6732 | if (bUseShortSlotTime) | |
6733 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); | |
6734 | else | |
6735 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); | |
6736 | ||
6737 | SlotTime = (bUseShortSlotTime)? 9 : 20; | |
6738 | ||
6739 | #ifdef CONFIG_STA_SUPPORT | |
6740 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
6741 | { | |
6742 | // force using short SLOT time for FAE to demo performance when TxBurst is ON | |
6743 | if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) | |
6744 | #ifdef DOT11_N_SUPPORT | |
6745 | || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)) | |
6746 | #endif // DOT11_N_SUPPORT // | |
6747 | ) | |
6748 | { | |
6749 | // In this case, we will think it is doing Wi-Fi test | |
6750 | // And we will not set to short slot when bEnableTxBurst is TRUE. | |
6751 | } | |
6752 | else if (pAd->CommonCfg.bEnableTxBurst) | |
6753 | SlotTime = 9; | |
6754 | } | |
6755 | #endif // CONFIG_STA_SUPPORT // | |
6756 | ||
6757 | // | |
6758 | // For some reasons, always set it to short slot time. | |
6759 | // | |
6760 | // ToDo: Should consider capability with 11B | |
6761 | // | |
6762 | #ifdef CONFIG_STA_SUPPORT | |
6763 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
6764 | { | |
6765 | if (pAd->StaCfg.BssType == BSS_ADHOC) | |
6766 | SlotTime = 20; | |
6767 | } | |
6768 | #endif // CONFIG_STA_SUPPORT // | |
6769 | ||
6770 | RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); | |
6771 | RegValue = RegValue & 0xFFFFFF00; | |
6772 | ||
6773 | RegValue |= SlotTime; | |
6774 | ||
6775 | RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); | |
6776 | } | |
6777 | ||
6778 | /* | |
6779 | ======================================================================== | |
6780 | Description: | |
6781 | Add Shared key information into ASIC. | |
6782 | Update shared key, TxMic and RxMic to Asic Shared key table | |
6783 | Update its cipherAlg to Asic Shared key Mode. | |
6784 | ||
6785 | Return: | |
6786 | ======================================================================== | |
6787 | */ | |
6788 | VOID AsicAddSharedKeyEntry( | |
6789 | IN PRTMP_ADAPTER pAd, | |
6790 | IN UCHAR BssIndex, | |
6791 | IN UCHAR KeyIdx, | |
6792 | IN UCHAR CipherAlg, | |
6793 | IN PUCHAR pKey, | |
6794 | IN PUCHAR pTxMic, | |
6795 | IN PUCHAR pRxMic) | |
6796 | { | |
6797 | ULONG offset; //, csr0; | |
6798 | SHAREDKEY_MODE_STRUC csr1; | |
91980990 | 6799 | INT i; |
91980990 GKH |
6800 | |
6801 | DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); | |
6802 | //============================================================================================ | |
6803 | ||
6804 | DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx)); | |
6805 | DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | |
6806 | pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); | |
6807 | if (pRxMic) | |
6808 | { | |
6809 | DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | |
6810 | pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); | |
6811 | } | |
6812 | if (pTxMic) | |
6813 | { | |
6814 | DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | |
6815 | pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); | |
6816 | } | |
6817 | //============================================================================================ | |
6818 | // | |
6819 | // fill key material - key + TX MIC + RX MIC | |
6820 | // | |
91980990 GKH |
6821 | offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE; |
6822 | for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++) | |
6823 | { | |
6824 | RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); | |
6825 | } | |
6826 | ||
6827 | offset += MAX_LEN_OF_SHARE_KEY; | |
6828 | if (pTxMic) | |
6829 | { | |
6830 | for (i=0; i<8; i++) | |
6831 | { | |
6832 | RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); | |
6833 | } | |
6834 | } | |
6835 | ||
6836 | offset += 8; | |
6837 | if (pRxMic) | |
6838 | { | |
6839 | for (i=0; i<8; i++) | |
6840 | { | |
6841 | RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); | |
6842 | } | |
6843 | } | |
91980990 GKH |
6844 | |
6845 | ||
6846 | // | |
6847 | // Update cipher algorithm. WSTA always use BSS0 | |
6848 | // | |
6849 | RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); | |
6850 | DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word)); | |
6851 | if ((BssIndex%2) == 0) | |
6852 | { | |
6853 | if (KeyIdx == 0) | |
6854 | csr1.field.Bss0Key0CipherAlg = CipherAlg; | |
6855 | else if (KeyIdx == 1) | |
6856 | csr1.field.Bss0Key1CipherAlg = CipherAlg; | |
6857 | else if (KeyIdx == 2) | |
6858 | csr1.field.Bss0Key2CipherAlg = CipherAlg; | |
6859 | else | |
6860 | csr1.field.Bss0Key3CipherAlg = CipherAlg; | |
6861 | } | |
6862 | else | |
6863 | { | |
6864 | if (KeyIdx == 0) | |
6865 | csr1.field.Bss1Key0CipherAlg = CipherAlg; | |
6866 | else if (KeyIdx == 1) | |
6867 | csr1.field.Bss1Key1CipherAlg = CipherAlg; | |
6868 | else if (KeyIdx == 2) | |
6869 | csr1.field.Bss1Key2CipherAlg = CipherAlg; | |
6870 | else | |
6871 | csr1.field.Bss1Key3CipherAlg = CipherAlg; | |
6872 | } | |
6873 | DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); | |
6874 | RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); | |
6875 | ||
6876 | } | |
6877 | ||
6878 | // IRQL = DISPATCH_LEVEL | |
6879 | VOID AsicRemoveSharedKeyEntry( | |
6880 | IN PRTMP_ADAPTER pAd, | |
6881 | IN UCHAR BssIndex, | |
6882 | IN UCHAR KeyIdx) | |
6883 | { | |
6884 | //ULONG SecCsr0; | |
6885 | SHAREDKEY_MODE_STRUC csr1; | |
6886 | ||
6887 | DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx)); | |
6888 | ||
6889 | RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); | |
6890 | if ((BssIndex%2) == 0) | |
6891 | { | |
6892 | if (KeyIdx == 0) | |
6893 | csr1.field.Bss0Key0CipherAlg = 0; | |
6894 | else if (KeyIdx == 1) | |
6895 | csr1.field.Bss0Key1CipherAlg = 0; | |
6896 | else if (KeyIdx == 2) | |
6897 | csr1.field.Bss0Key2CipherAlg = 0; | |
6898 | else | |
6899 | csr1.field.Bss0Key3CipherAlg = 0; | |
6900 | } | |
6901 | else | |
6902 | { | |
6903 | if (KeyIdx == 0) | |
6904 | csr1.field.Bss1Key0CipherAlg = 0; | |
6905 | else if (KeyIdx == 1) | |
6906 | csr1.field.Bss1Key1CipherAlg = 0; | |
6907 | else if (KeyIdx == 2) | |
6908 | csr1.field.Bss1Key2CipherAlg = 0; | |
6909 | else | |
6910 | csr1.field.Bss1Key3CipherAlg = 0; | |
6911 | } | |
6912 | DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); | |
6913 | RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); | |
6914 | ASSERT(BssIndex < 4); | |
6915 | ASSERT(KeyIdx < 4); | |
6916 | ||
6917 | } | |
6918 | ||
6919 | ||
6920 | VOID AsicUpdateWCIDAttribute( | |
6921 | IN PRTMP_ADAPTER pAd, | |
6922 | IN USHORT WCID, | |
6923 | IN UCHAR BssIndex, | |
6924 | IN UCHAR CipherAlg, | |
6925 | IN BOOLEAN bUsePairewiseKeyTable) | |
6926 | { | |
6927 | ULONG WCIDAttri = 0, offset; | |
6928 | ||
6929 | // | |
6930 | // Update WCID attribute. | |
6931 | // Only TxKey could update WCID attribute. | |
6932 | // | |
6933 | offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE); | |
6934 | WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable); | |
6935 | RTMP_IO_WRITE32(pAd, offset, WCIDAttri); | |
6936 | } | |
6937 | ||
6938 | VOID AsicUpdateWCIDIVEIV( | |
6939 | IN PRTMP_ADAPTER pAd, | |
6940 | IN USHORT WCID, | |
6941 | IN ULONG uIV, | |
6942 | IN ULONG uEIV) | |
6943 | { | |
6944 | ULONG offset; | |
6945 | ||
6946 | offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); | |
6947 | ||
6948 | RTMP_IO_WRITE32(pAd, offset, uIV); | |
6949 | RTMP_IO_WRITE32(pAd, offset + 4, uEIV); | |
6950 | } | |
6951 | ||
6952 | VOID AsicUpdateRxWCIDTable( | |
6953 | IN PRTMP_ADAPTER pAd, | |
6954 | IN USHORT WCID, | |
6955 | IN PUCHAR pAddr) | |
6956 | { | |
6957 | ULONG offset; | |
6958 | ULONG Addr; | |
6959 | ||
6960 | offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); | |
6961 | Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); | |
6962 | RTMP_IO_WRITE32(pAd, offset, Addr); | |
6963 | Addr = pAddr[4] + (pAddr[5] << 8); | |
6964 | RTMP_IO_WRITE32(pAd, offset + 4, Addr); | |
6965 | } | |
6966 | ||
6967 | ||
6968 | /* | |
6969 | ======================================================================== | |
6970 | ||
6971 | Routine Description: | |
6972 | Set Cipher Key, Cipher algorithm, IV/EIV to Asic | |
6973 | ||
6974 | Arguments: | |
6975 | pAd Pointer to our adapter | |
6976 | WCID WCID Entry number. | |
6977 | BssIndex BSSID index, station or none multiple BSSID support | |
6978 | this value should be 0. | |
6979 | KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled | |
6980 | pCipherKey Pointer to Cipher Key. | |
6981 | bUsePairewiseKeyTable TRUE means saved the key in SharedKey table, | |
6982 | otherwise PairewiseKey table | |
6983 | bTxKey This is the transmit key if enabled. | |
6984 | ||
6985 | Return Value: | |
6986 | None | |
6987 | ||
6988 | Note: | |
6989 | This routine will set the relative key stuff to Asic including WCID attribute, | |
6990 | Cipher Key, Cipher algorithm and IV/EIV. | |
6991 | ||
6992 | IV/EIV will be update if this CipherKey is the transmission key because | |
6993 | ASIC will base on IV's KeyID value to select Cipher Key. | |
6994 | ||
6995 | If bTxKey sets to FALSE, this is not the TX key, but it could be | |
6996 | RX key | |
6997 | ||
6998 | For AP mode bTxKey must be always set to TRUE. | |
6999 | ======================================================================== | |
7000 | */ | |
7001 | VOID AsicAddKeyEntry( | |
7002 | IN PRTMP_ADAPTER pAd, | |
7003 | IN USHORT WCID, | |
7004 | IN UCHAR BssIndex, | |
7005 | IN UCHAR KeyIdx, | |
7006 | IN PCIPHER_KEY pCipherKey, | |
7007 | IN BOOLEAN bUsePairewiseKeyTable, | |
7008 | IN BOOLEAN bTxKey) | |
7009 | { | |
7010 | ULONG offset; | |
7011 | UCHAR IV4 = 0; | |
7012 | PUCHAR pKey = pCipherKey->Key; | |
7013 | PUCHAR pTxMic = pCipherKey->TxMic; | |
7014 | PUCHAR pRxMic = pCipherKey->RxMic; | |
7015 | PUCHAR pTxtsc = pCipherKey->TxTsc; | |
7016 | UCHAR CipherAlg = pCipherKey->CipherAlg; | |
7017 | SHAREDKEY_MODE_STRUC csr1; | |
91980990 | 7018 | UCHAR i; |
91980990 GKH |
7019 | |
7020 | DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); | |
7021 | // | |
7022 | // 1.) decide key table offset | |
7023 | // | |
7024 | if (bUsePairewiseKeyTable) | |
7025 | offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); | |
7026 | else | |
7027 | offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; | |
7028 | ||
7029 | // | |
7030 | // 2.) Set Key to Asic | |
7031 | // | |
7032 | //for (i = 0; i < KeyLen; i++) | |
91980990 GKH |
7033 | for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) |
7034 | { | |
7035 | RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); | |
7036 | } | |
7037 | offset += MAX_LEN_OF_PEER_KEY; | |
7038 | ||
7039 | // | |
7040 | // 3.) Set MIC key if available | |
7041 | // | |
7042 | if (pTxMic) | |
7043 | { | |
7044 | for (i = 0; i < 8; i++) | |
7045 | { | |
7046 | RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); | |
7047 | } | |
7048 | } | |
7049 | offset += LEN_TKIP_TXMICK; | |
7050 | ||
7051 | if (pRxMic) | |
7052 | { | |
7053 | for (i = 0; i < 8; i++) | |
7054 | { | |
7055 | RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); | |
7056 | } | |
7057 | } | |
91980990 GKH |
7058 | |
7059 | ||
7060 | // | |
7061 | // 4.) Modify IV/EIV if needs | |
7062 | // This will force Asic to use this key ID by setting IV. | |
7063 | // | |
7064 | if (bTxKey) | |
7065 | { | |
91980990 GKH |
7066 | offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); |
7067 | // | |
7068 | // Write IV | |
7069 | // | |
7070 | RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]); | |
7071 | RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f)); | |
7072 | RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]); | |
7073 | ||
7074 | IV4 = (KeyIdx << 6); | |
7075 | if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES)) | |
7076 | IV4 |= 0x20; // turn on extension bit means EIV existence | |
7077 | ||
7078 | RTMP_IO_WRITE8(pAd, offset + 3, IV4); | |
7079 | ||
7080 | // | |
7081 | // Write EIV | |
7082 | // | |
7083 | offset += 4; | |
7084 | for (i = 0; i < 4; i++) | |
7085 | { | |
7086 | RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); | |
7087 | } | |
91980990 GKH |
7088 | |
7089 | AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable); | |
7090 | } | |
7091 | ||
7092 | if (!bUsePairewiseKeyTable) | |
7093 | { | |
7094 | // | |
7095 | // Only update the shared key security mode | |
7096 | // | |
7097 | RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word); | |
7098 | if ((BssIndex % 2) == 0) | |
7099 | { | |
7100 | if (KeyIdx == 0) | |
7101 | csr1.field.Bss0Key0CipherAlg = CipherAlg; | |
7102 | else if (KeyIdx == 1) | |
7103 | csr1.field.Bss0Key1CipherAlg = CipherAlg; | |
7104 | else if (KeyIdx == 2) | |
7105 | csr1.field.Bss0Key2CipherAlg = CipherAlg; | |
7106 | else | |
7107 | csr1.field.Bss0Key3CipherAlg = CipherAlg; | |
7108 | } | |
7109 | else | |
7110 | { | |
7111 | if (KeyIdx == 0) | |
7112 | csr1.field.Bss1Key0CipherAlg = CipherAlg; | |
7113 | else if (KeyIdx == 1) | |
7114 | csr1.field.Bss1Key1CipherAlg = CipherAlg; | |
7115 | else if (KeyIdx == 2) | |
7116 | csr1.field.Bss1Key2CipherAlg = CipherAlg; | |
7117 | else | |
7118 | csr1.field.Bss1Key3CipherAlg = CipherAlg; | |
7119 | } | |
7120 | RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word); | |
7121 | } | |
7122 | ||
7123 | DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); | |
7124 | } | |
7125 | ||
7126 | ||
7127 | /* | |
7128 | ======================================================================== | |
7129 | Description: | |
7130 | Add Pair-wise key material into ASIC. | |
7131 | Update pairwise key, TxMic and RxMic to Asic Pair-wise key table | |
7132 | ||
7133 | Return: | |
7134 | ======================================================================== | |
7135 | */ | |
7136 | VOID AsicAddPairwiseKeyEntry( | |
7137 | IN PRTMP_ADAPTER pAd, | |
7138 | IN PUCHAR pAddr, | |
7139 | IN UCHAR WCID, | |
7140 | IN CIPHER_KEY *pCipherKey) | |
7141 | { | |
7142 | INT i; | |
7143 | ULONG offset; | |
7144 | PUCHAR pKey = pCipherKey->Key; | |
7145 | PUCHAR pTxMic = pCipherKey->TxMic; | |
7146 | PUCHAR pRxMic = pCipherKey->RxMic; | |
7147 | #ifdef DBG | |
7148 | UCHAR CipherAlg = pCipherKey->CipherAlg; | |
7149 | #endif // DBG // | |
7150 | ||
7151 | // EKEY | |
7152 | offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); | |
91980990 GKH |
7153 | for (i=0; i<MAX_LEN_OF_PEER_KEY; i++) |
7154 | { | |
7155 | RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); | |
7156 | } | |
91980990 GKH |
7157 | for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4) |
7158 | { | |
7159 | UINT32 Value; | |
7160 | RTMP_IO_READ32(pAd, offset + i, &Value); | |
7161 | } | |
7162 | ||
7163 | offset += MAX_LEN_OF_PEER_KEY; | |
7164 | ||
7165 | // MIC KEY | |
7166 | if (pTxMic) | |
7167 | { | |
91980990 GKH |
7168 | for (i=0; i<8; i++) |
7169 | { | |
7170 | RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]); | |
7171 | } | |
91980990 GKH |
7172 | } |
7173 | offset += 8; | |
7174 | if (pRxMic) | |
7175 | { | |
91980990 GKH |
7176 | for (i=0; i<8; i++) |
7177 | { | |
7178 | RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]); | |
7179 | } | |
91980990 GKH |
7180 | } |
7181 | ||
7182 | DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg])); | |
7183 | DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | |
7184 | pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); | |
7185 | if (pRxMic) | |
7186 | { | |
7187 | DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | |
7188 | pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); | |
7189 | } | |
7190 | if (pTxMic) | |
7191 | { | |
7192 | DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | |
7193 | pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); | |
7194 | } | |
7195 | } | |
7196 | /* | |
7197 | ======================================================================== | |
7198 | Description: | |
7199 | Remove Pair-wise key material from ASIC. | |
7200 | ||
7201 | Return: | |
7202 | ======================================================================== | |
7203 | */ | |
7204 | VOID AsicRemovePairwiseKeyEntry( | |
7205 | IN PRTMP_ADAPTER pAd, | |
7206 | IN UCHAR BssIdx, | |
7207 | IN UCHAR Wcid) | |
7208 | { | |
7209 | ULONG WCIDAttri; | |
7210 | USHORT offset; | |
7211 | ||
7212 | // re-set the entry's WCID attribute as OPEN-NONE. | |
7213 | offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); | |
7214 | WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE; | |
7215 | RTMP_IO_WRITE32(pAd, offset, WCIDAttri); | |
7216 | } | |
7217 | ||
7218 | BOOLEAN AsicSendCommandToMcu( | |
7219 | IN PRTMP_ADAPTER pAd, | |
7220 | IN UCHAR Command, | |
7221 | IN UCHAR Token, | |
7222 | IN UCHAR Arg0, | |
7223 | IN UCHAR Arg1) | |
7224 | { | |
7225 | HOST_CMD_CSR_STRUC H2MCmd; | |
7226 | H2M_MAILBOX_STRUC H2MMailbox; | |
7227 | ULONG i = 0; | |
063f22af | 7228 | |
91980990 GKH |
7229 | do |
7230 | { | |
7231 | RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); | |
7232 | if (H2MMailbox.field.Owner == 0) | |
7233 | break; | |
7234 | ||
7235 | RTMPusecDelay(2); | |
7236 | } while(i++ < 100); | |
7237 | ||
7238 | if (i >= 100) | |
7239 | { | |
91980990 | 7240 | { |
ed291e80 AM |
7241 | UINT32 Data; |
7242 | ||
7243 | // Reset DMA | |
7244 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); | |
7245 | Data |= 0x2; | |
7246 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
7247 | ||
7248 | // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too. | |
7249 | // Reset DMA/CPU ring index | |
7250 | RTMPRingCleanUp(pAd, QID_AC_BK); | |
7251 | RTMPRingCleanUp(pAd, QID_AC_BE); | |
7252 | RTMPRingCleanUp(pAd, QID_AC_VI); | |
7253 | RTMPRingCleanUp(pAd, QID_AC_VO); | |
7254 | RTMPRingCleanUp(pAd, QID_HCCA); | |
7255 | RTMPRingCleanUp(pAd, QID_MGMT); | |
7256 | RTMPRingCleanUp(pAd, QID_RX); | |
7257 | ||
7258 | // Clear Reset | |
7259 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); | |
7260 | Data &= 0xfffffffd; | |
7261 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
91980990 GKH |
7262 | DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); |
7263 | } | |
ed291e80 | 7264 | //return FALSE; |
91980990 GKH |
7265 | } |
7266 | ||
91980990 GKH |
7267 | H2MMailbox.field.Owner = 1; // pass ownership to MCU |
7268 | H2MMailbox.field.CmdToken = Token; | |
7269 | H2MMailbox.field.HighByte = Arg1; | |
7270 | H2MMailbox.field.LowByte = Arg0; | |
7271 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); | |
7272 | ||
7273 | H2MCmd.word = 0; | |
7274 | H2MCmd.field.HostCommand = Command; | |
7275 | RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); | |
7276 | ||
7277 | if (Command != 0x80) | |
7278 | { | |
7279 | } | |
7280 | ||
7281 | return TRUE; | |
7282 | } | |
7283 | ||
91980990 GKH |
7284 | BOOLEAN AsicCheckCommanOk( |
7285 | IN PRTMP_ADAPTER pAd, | |
7286 | IN UCHAR Command) | |
7287 | { | |
7288 | UINT32 CmdStatus = 0, CID = 0, i; | |
7289 | UINT32 ThisCIDMask = 0; | |
7290 | ||
7291 | i = 0; | |
7292 | do | |
7293 | { | |
7294 | RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); | |
7295 | // Find where the command is. Because this is randomly specified by firmware. | |
7296 | if ((CID & CID0MASK) == Command) | |
7297 | { | |
7298 | ThisCIDMask = CID0MASK; | |
7299 | break; | |
7300 | } | |
7301 | else if ((((CID & CID1MASK)>>8) & 0xff) == Command) | |
7302 | { | |
7303 | ThisCIDMask = CID1MASK; | |
7304 | break; | |
7305 | } | |
7306 | else if ((((CID & CID2MASK)>>16) & 0xff) == Command) | |
7307 | { | |
7308 | ThisCIDMask = CID2MASK; | |
7309 | break; | |
7310 | } | |
7311 | else if ((((CID & CID3MASK)>>24) & 0xff) == Command) | |
7312 | { | |
7313 | ThisCIDMask = CID3MASK; | |
7314 | break; | |
7315 | } | |
7316 | ||
7317 | RTMPusecDelay(100); | |
7318 | i++; | |
7319 | }while (i < 200); | |
7320 | ||
7321 | // Get CommandStatus Value | |
7322 | RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); | |
7323 | ||
7324 | // This command's status is at the same position as command. So AND command position's bitmask to read status. | |
7325 | if (i < 200) | |
7326 | { | |
7327 | // If Status is 1, the comamnd is success. | |
7328 | if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100) | |
7329 | || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000)) | |
7330 | { | |
7331 | DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); | |
7332 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); | |
7333 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); | |
7334 | return TRUE; | |
7335 | } | |
7336 | DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus)); | |
7337 | } | |
7338 | else | |
7339 | { | |
7340 | DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus)); | |
7341 | } | |
7342 | // Clear Command and Status. | |
7343 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); | |
7344 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); | |
7345 | ||
7346 | return FALSE; | |
7347 | } | |
91980990 GKH |
7348 | |
7349 | /* | |
7350 | ======================================================================== | |
7351 | ||
7352 | Routine Description: | |
7353 | Verify the support rate for different PHY type | |
7354 | ||
7355 | Arguments: | |
7356 | pAd Pointer to our adapter | |
7357 | ||
7358 | Return Value: | |
7359 | None | |
7360 | ||
7361 | IRQL = PASSIVE_LEVEL | |
7362 | ||
7363 | ======================================================================== | |
7364 | */ | |
7365 | VOID RTMPCheckRates( | |
7366 | IN PRTMP_ADAPTER pAd, | |
7367 | IN OUT UCHAR SupRate[], | |
7368 | IN OUT UCHAR *SupRateLen) | |
7369 | { | |
7370 | UCHAR RateIdx, i, j; | |
7371 | UCHAR NewRate[12], NewRateLen; | |
7372 | ||
7373 | NewRateLen = 0; | |
7374 | ||
7375 | if (pAd->CommonCfg.PhyMode == PHY_11B) | |
7376 | RateIdx = 4; | |
7377 | else | |
7378 | RateIdx = 12; | |
7379 | ||
7380 | // Check for support rates exclude basic rate bit | |
7381 | for (i = 0; i < *SupRateLen; i++) | |
7382 | for (j = 0; j < RateIdx; j++) | |
7383 | if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) | |
7384 | NewRate[NewRateLen++] = SupRate[i]; | |
7385 | ||
7386 | *SupRateLen = NewRateLen; | |
7387 | NdisMoveMemory(SupRate, NewRate, NewRateLen); | |
7388 | } | |
7389 | ||
7390 | #ifdef CONFIG_STA_SUPPORT | |
7391 | #ifdef DOT11_N_SUPPORT | |
7392 | BOOLEAN RTMPCheckChannel( | |
7393 | IN PRTMP_ADAPTER pAd, | |
7394 | IN UCHAR CentralChannel, | |
7395 | IN UCHAR Channel) | |
7396 | { | |
7397 | UCHAR k; | |
7398 | UCHAR UpperChannel = 0, LowerChannel = 0; | |
7399 | UCHAR NoEffectChannelinList = 0; | |
7400 | ||
7401 | // Find upper and lower channel according to 40MHz current operation. | |
7402 | if (CentralChannel < Channel) | |
7403 | { | |
7404 | UpperChannel = Channel; | |
7405 | if (CentralChannel > 2) | |
7406 | LowerChannel = CentralChannel - 2; | |
7407 | else | |
7408 | return FALSE; | |
7409 | } | |
7410 | else if (CentralChannel > Channel) | |
7411 | { | |
7412 | UpperChannel = CentralChannel + 2; | |
7413 | LowerChannel = Channel; | |
7414 | } | |
7415 | ||
7416 | for (k = 0;k < pAd->ChannelListNum;k++) | |
7417 | { | |
7418 | if (pAd->ChannelList[k].Channel == UpperChannel) | |
7419 | { | |
7420 | NoEffectChannelinList ++; | |
7421 | } | |
7422 | if (pAd->ChannelList[k].Channel == LowerChannel) | |
7423 | { | |
7424 | NoEffectChannelinList ++; | |
7425 | } | |
7426 | } | |
7427 | ||
7428 | DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList)); | |
7429 | if (NoEffectChannelinList == 2) | |
7430 | return TRUE; | |
7431 | else | |
7432 | return FALSE; | |
7433 | } | |
7434 | ||
7435 | /* | |
7436 | ======================================================================== | |
7437 | ||
7438 | Routine Description: | |
7439 | Verify the support rate for HT phy type | |
7440 | ||
7441 | Arguments: | |
7442 | pAd Pointer to our adapter | |
7443 | ||
7444 | Return Value: | |
7445 | FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) | |
7446 | ||
7447 | IRQL = PASSIVE_LEVEL | |
7448 | ||
7449 | ======================================================================== | |
7450 | */ | |
7451 | BOOLEAN RTMPCheckHt( | |
7452 | IN PRTMP_ADAPTER pAd, | |
7453 | IN UCHAR Wcid, | |
7454 | IN HT_CAPABILITY_IE *pHtCapability, | |
7455 | IN ADD_HT_INFO_IE *pAddHtInfo) | |
7456 | { | |
7457 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) | |
7458 | return FALSE; | |
7459 | ||
7460 | // If use AMSDU, set flag. | |
7461 | if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) | |
7462 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED); | |
7463 | // Save Peer Capability | |
7464 | if (pHtCapability->HtCapInfo.ShortGIfor20) | |
7465 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE); | |
7466 | if (pHtCapability->HtCapInfo.ShortGIfor40) | |
7467 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE); | |
7468 | if (pHtCapability->HtCapInfo.TxSTBC) | |
7469 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE); | |
7470 | if (pHtCapability->HtCapInfo.RxSTBC) | |
7471 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE); | |
7472 | if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) | |
7473 | { | |
7474 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE); | |
7475 | } | |
7476 | ||
7477 | if (Wcid < MAX_LEN_OF_MAC_TABLE) | |
7478 | { | |
7479 | pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity; | |
7480 | } | |
7481 | ||
7482 | // Will check ChannelWidth for MCSSet[4] below | |
7483 | pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; | |
7484 | switch (pAd->CommonCfg.RxStream) | |
7485 | { | |
7486 | case 1: | |
7487 | pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; | |
7488 | pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; | |
7489 | pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; | |
7490 | pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; | |
7491 | break; | |
7492 | case 2: | |
7493 | pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; | |
7494 | pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; | |
7495 | pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; | |
7496 | pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; | |
7497 | break; | |
7498 | case 3: | |
7499 | pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; | |
7500 | pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; | |
7501 | pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; | |
7502 | pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; | |
7503 | break; | |
7504 | } | |
7505 | ||
7506 | pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; | |
7507 | ||
7508 | DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", | |
7509 | pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth, | |
7510 | pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode)); | |
7511 | ||
7512 | pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; | |
7513 | ||
7514 | // Send Assoc Req with my HT capability. | |
7515 | pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; | |
7516 | pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs; | |
7517 | pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); | |
7518 | pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); | |
7519 | pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); | |
7520 | pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); | |
7521 | pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; | |
7522 | pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; | |
7523 | pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; | |
7524 | pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; | |
7525 | if (pAd->CommonCfg.bRdg) | |
7526 | { | |
7527 | pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; | |
7528 | pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; | |
7529 | } | |
7530 | ||
7531 | if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) | |
7532 | pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32 | |
7533 | ||
7534 | COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); | |
7535 | return TRUE; | |
7536 | } | |
7537 | #endif // DOT11_N_SUPPORT // | |
7538 | #endif // CONFIG_STA_SUPPORT // | |
7539 | ||
7540 | /* | |
7541 | ======================================================================== | |
7542 | ||
7543 | Routine Description: | |
7544 | Verify the support rate for different PHY type | |
7545 | ||
7546 | Arguments: | |
7547 | pAd Pointer to our adapter | |
7548 | ||
7549 | Return Value: | |
7550 | None | |
7551 | ||
7552 | IRQL = PASSIVE_LEVEL | |
7553 | ||
7554 | ======================================================================== | |
7555 | */ | |
7556 | VOID RTMPUpdateMlmeRate( | |
7557 | IN PRTMP_ADAPTER pAd) | |
7558 | { | |
7559 | UCHAR MinimumRate; | |
7560 | UCHAR ProperMlmeRate; //= RATE_54; | |
7561 | UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 | |
7562 | BOOLEAN bMatch = FALSE; | |
7563 | ||
7564 | switch (pAd->CommonCfg.PhyMode) | |
7565 | { | |
7566 | case PHY_11B: | |
7567 | ProperMlmeRate = RATE_11; | |
7568 | MinimumRate = RATE_1; | |
7569 | break; | |
7570 | case PHY_11BG_MIXED: | |
7571 | #ifdef DOT11_N_SUPPORT | |
7572 | case PHY_11ABGN_MIXED: | |
7573 | case PHY_11BGN_MIXED: | |
7574 | #endif // DOT11_N_SUPPORT // | |
7575 | if ((pAd->MlmeAux.SupRateLen == 4) && | |
7576 | (pAd->MlmeAux.ExtRateLen == 0)) | |
7577 | // B only AP | |
7578 | ProperMlmeRate = RATE_11; | |
7579 | else | |
7580 | ProperMlmeRate = RATE_24; | |
7581 | ||
7582 | if (pAd->MlmeAux.Channel <= 14) | |
7583 | MinimumRate = RATE_1; | |
7584 | else | |
7585 | MinimumRate = RATE_6; | |
7586 | break; | |
7587 | case PHY_11A: | |
7588 | #ifdef DOT11_N_SUPPORT | |
7589 | case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n | |
7590 | case PHY_11GN_MIXED: | |
7591 | case PHY_11AGN_MIXED: | |
7592 | case PHY_11AN_MIXED: | |
7593 | case PHY_11N_5G: | |
7594 | #endif // DOT11_N_SUPPORT // | |
7595 | ProperMlmeRate = RATE_24; | |
7596 | MinimumRate = RATE_6; | |
7597 | break; | |
7598 | case PHY_11ABG_MIXED: | |
7599 | ProperMlmeRate = RATE_24; | |
7600 | if (pAd->MlmeAux.Channel <= 14) | |
7601 | MinimumRate = RATE_1; | |
7602 | else | |
7603 | MinimumRate = RATE_6; | |
7604 | break; | |
7605 | default: // error | |
7606 | ProperMlmeRate = RATE_1; | |
7607 | MinimumRate = RATE_1; | |
7608 | break; | |
7609 | } | |
7610 | ||
7611 | for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) | |
7612 | { | |
7613 | for (j = 0; j < RateIdx; j++) | |
7614 | { | |
7615 | if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) | |
7616 | { | |
7617 | if (j == ProperMlmeRate) | |
7618 | { | |
7619 | bMatch = TRUE; | |
7620 | break; | |
7621 | } | |
7622 | } | |
7623 | } | |
7624 | ||
7625 | if (bMatch) | |
7626 | break; | |
7627 | } | |
7628 | ||
7629 | if (bMatch == FALSE) | |
7630 | { | |
7631 | for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) | |
7632 | { | |
7633 | for (j = 0; j < RateIdx; j++) | |
7634 | { | |
7635 | if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) | |
7636 | { | |
7637 | if (j == ProperMlmeRate) | |
7638 | { | |
7639 | bMatch = TRUE; | |
7640 | break; | |
7641 | } | |
7642 | } | |
7643 | } | |
7644 | ||
7645 | if (bMatch) | |
7646 | break; | |
7647 | } | |
7648 | } | |
7649 | ||
7650 | if (bMatch == FALSE) | |
7651 | { | |
7652 | ProperMlmeRate = MinimumRate; | |
7653 | } | |
7654 | ||
7655 | pAd->CommonCfg.MlmeRate = MinimumRate; | |
7656 | pAd->CommonCfg.RtsRate = ProperMlmeRate; | |
7657 | if (pAd->CommonCfg.MlmeRate >= RATE_6) | |
7658 | { | |
7659 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | |
7660 | pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | |
7661 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; | |
7662 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | |
7663 | } | |
7664 | else | |
7665 | { | |
7666 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | |
7667 | pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; | |
7668 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; | |
7669 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; | |
7670 | } | |
7671 | ||
7672 | DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); | |
7673 | } | |
7674 | ||
7675 | CHAR RTMPMaxRssi( | |
7676 | IN PRTMP_ADAPTER pAd, | |
7677 | IN CHAR Rssi0, | |
7678 | IN CHAR Rssi1, | |
7679 | IN CHAR Rssi2) | |
7680 | { | |
7681 | CHAR larger = -127; | |
7682 | ||
7683 | if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) | |
7684 | { | |
7685 | larger = Rssi0; | |
7686 | } | |
7687 | ||
7688 | if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) | |
7689 | { | |
7690 | larger = max(Rssi0, Rssi1); | |
7691 | } | |
7692 | ||
7693 | if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) | |
7694 | { | |
7695 | larger = max(larger, Rssi2); | |
7696 | } | |
7697 | ||
7698 | if (larger == -127) | |
7699 | larger = 0; | |
7700 | ||
7701 | return larger; | |
7702 | } | |
7703 | ||
7704 | /* | |
7705 | ======================================================================== | |
7706 | Routine Description: | |
7707 | Periodic evaluate antenna link status | |
7708 | ||
7709 | Arguments: | |
7710 | pAd - Adapter pointer | |
7711 | ||
7712 | Return Value: | |
7713 | None | |
7714 | ||
7715 | ======================================================================== | |
7716 | */ | |
7717 | VOID AsicEvaluateRxAnt( | |
7718 | IN PRTMP_ADAPTER pAd) | |
7719 | { | |
7720 | UCHAR BBPR3 = 0; | |
7721 | ||
91980990 GKH |
7722 | #ifdef CONFIG_STA_SUPPORT |
7723 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
7724 | { | |
7725 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | | |
7726 | fRTMP_ADAPTER_HALT_IN_PROGRESS | | |
7727 | fRTMP_ADAPTER_RADIO_OFF | | |
7728 | fRTMP_ADAPTER_NIC_NOT_EXIST | | |
7729 | fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | |
7730 | return; | |
7731 | ||
7732 | if (pAd->StaCfg.Psm == PWR_SAVE) | |
7733 | return; | |
7734 | } | |
7735 | #endif // CONFIG_STA_SUPPORT // | |
7736 | ||
7737 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); | |
7738 | BBPR3 &= (~0x18); | |
7739 | if(pAd->Antenna.field.RxPath == 3) | |
7740 | { | |
7741 | BBPR3 |= (0x10); | |
7742 | } | |
7743 | else if(pAd->Antenna.field.RxPath == 2) | |
7744 | { | |
7745 | BBPR3 |= (0x8); | |
7746 | } | |
7747 | else if(pAd->Antenna.field.RxPath == 1) | |
7748 | { | |
7749 | BBPR3 |= (0x0); | |
7750 | } | |
7751 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); | |
7752 | #ifdef CONFIG_STA_SUPPORT | |
91980990 GKH |
7753 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) |
7754 | pAd->StaCfg.BBPR3 = BBPR3; | |
91980990 GKH |
7755 | #endif // CONFIG_STA_SUPPORT // |
7756 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | |
7757 | ) | |
7758 | { | |
7759 | ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + | |
7760 | pAd->RalinkCounters.OneSecTxRetryOkCount + | |
7761 | pAd->RalinkCounters.OneSecTxFailCount; | |
7762 | ||
7763 | if (TxTotalCnt > 50) | |
7764 | { | |
7765 | RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20); | |
7766 | pAd->Mlme.bLowThroughput = FALSE; | |
7767 | } | |
7768 | else | |
7769 | { | |
7770 | RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); | |
7771 | pAd->Mlme.bLowThroughput = TRUE; | |
7772 | } | |
7773 | } | |
7774 | } | |
7775 | ||
7776 | /* | |
7777 | ======================================================================== | |
7778 | Routine Description: | |
7779 | After evaluation, check antenna link status | |
7780 | ||
7781 | Arguments: | |
7782 | pAd - Adapter pointer | |
7783 | ||
7784 | Return Value: | |
7785 | None | |
7786 | ||
7787 | ======================================================================== | |
7788 | */ | |
7789 | VOID AsicRxAntEvalTimeout( | |
7790 | IN PVOID SystemSpecific1, | |
7791 | IN PVOID FunctionContext, | |
7792 | IN PVOID SystemSpecific2, | |
7793 | IN PVOID SystemSpecific3) | |
7794 | { | |
7795 | RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; | |
7796 | #ifdef CONFIG_STA_SUPPORT | |
7797 | UCHAR BBPR3 = 0; | |
7798 | CHAR larger = -127, rssi0, rssi1, rssi2; | |
7799 | #endif // CONFIG_STA_SUPPORT // | |
7800 | ||
91980990 GKH |
7801 | #ifdef CONFIG_STA_SUPPORT |
7802 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
7803 | { | |
7804 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || | |
7805 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || | |
7806 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) || | |
7807 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) | |
7808 | return; | |
7809 | ||
7810 | if (pAd->StaCfg.Psm == PWR_SAVE) | |
7811 | return; | |
7812 | ||
7813 | ||
7814 | // if the traffic is low, use average rssi as the criteria | |
7815 | if (pAd->Mlme.bLowThroughput == TRUE) | |
7816 | { | |
7817 | rssi0 = pAd->StaCfg.RssiSample.LastRssi0; | |
7818 | rssi1 = pAd->StaCfg.RssiSample.LastRssi1; | |
7819 | rssi2 = pAd->StaCfg.RssiSample.LastRssi2; | |
7820 | } | |
7821 | else | |
7822 | { | |
7823 | rssi0 = pAd->StaCfg.RssiSample.AvgRssi0; | |
7824 | rssi1 = pAd->StaCfg.RssiSample.AvgRssi1; | |
7825 | rssi2 = pAd->StaCfg.RssiSample.AvgRssi2; | |
7826 | } | |
7827 | ||
7828 | if(pAd->Antenna.field.RxPath == 3) | |
7829 | { | |
7830 | larger = max(rssi0, rssi1); | |
7831 | ||
7832 | if (larger > (rssi2 + 20)) | |
7833 | pAd->Mlme.RealRxPath = 2; | |
7834 | else | |
7835 | pAd->Mlme.RealRxPath = 3; | |
7836 | } | |
7837 | else if(pAd->Antenna.field.RxPath == 2) | |
7838 | { | |
7839 | if (rssi0 > (rssi1 + 20)) | |
7840 | pAd->Mlme.RealRxPath = 1; | |
7841 | else | |
7842 | pAd->Mlme.RealRxPath = 2; | |
7843 | } | |
7844 | ||
7845 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); | |
7846 | BBPR3 &= (~0x18); | |
7847 | if(pAd->Mlme.RealRxPath == 3) | |
7848 | { | |
7849 | BBPR3 |= (0x10); | |
7850 | } | |
7851 | else if(pAd->Mlme.RealRxPath == 2) | |
7852 | { | |
7853 | BBPR3 |= (0x8); | |
7854 | } | |
7855 | else if(pAd->Mlme.RealRxPath == 1) | |
7856 | { | |
7857 | BBPR3 |= (0x0); | |
7858 | } | |
7859 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); | |
bdc0a173 | 7860 | pAd->StaCfg.BBPR3 = BBPR3; |
91980990 GKH |
7861 | } |
7862 | ||
7863 | #endif // CONFIG_STA_SUPPORT // | |
7864 | ||
7865 | } | |
7866 | ||
7867 | ||
7868 | ||
7869 | VOID APSDPeriodicExec( | |
7870 | IN PVOID SystemSpecific1, | |
7871 | IN PVOID FunctionContext, | |
7872 | IN PVOID SystemSpecific2, | |
7873 | IN PVOID SystemSpecific3) | |
7874 | { | |
7875 | RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; | |
7876 | ||
7877 | if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | |
7878 | return; | |
7879 | ||
7880 | pAd->CommonCfg.TriggerTimerCount++; | |
7881 | ||
7882 | } | |
7883 | ||
7884 | /* | |
7885 | ======================================================================== | |
7886 | Routine Description: | |
7887 | Set/reset MAC registers according to bPiggyBack parameter | |
7888 | ||
7889 | Arguments: | |
7890 | pAd - Adapter pointer | |
7891 | bPiggyBack - Enable / Disable Piggy-Back | |
7892 | ||
7893 | Return Value: | |
7894 | None | |
7895 | ||
7896 | ======================================================================== | |
7897 | */ | |
7898 | VOID RTMPSetPiggyBack( | |
7899 | IN PRTMP_ADAPTER pAd, | |
7900 | IN BOOLEAN bPiggyBack) | |
7901 | { | |
7902 | TX_LINK_CFG_STRUC TxLinkCfg; | |
7903 | ||
7904 | RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); | |
7905 | ||
7906 | TxLinkCfg.field.TxCFAckEn = bPiggyBack; | |
7907 | RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); | |
7908 | } | |
7909 | ||
7910 | /* | |
7911 | ======================================================================== | |
7912 | Routine Description: | |
7913 | check if this entry need to switch rate automatically | |
7914 | ||
7915 | Arguments: | |
7916 | pAd | |
7917 | pEntry | |
7918 | ||
7919 | Return Value: | |
7920 | TURE | |
7921 | FALSE | |
7922 | ||
7923 | ======================================================================== | |
7924 | */ | |
7925 | BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( | |
7926 | IN PRTMP_ADAPTER pAd, | |
7927 | IN PMAC_TABLE_ENTRY pEntry) | |
7928 | { | |
7929 | BOOLEAN result = TRUE; | |
7930 | ||
7931 | ||
7932 | #ifdef CONFIG_STA_SUPPORT | |
7933 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
7934 | { | |
7935 | // only associated STA counts | |
7936 | if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC)) | |
7937 | { | |
7938 | result = pAd->StaCfg.bAutoTxRateSwitch; | |
7939 | } | |
7940 | else | |
7941 | result = FALSE; | |
91980990 GKH |
7942 | } |
7943 | #endif // CONFIG_STA_SUPPORT // | |
7944 | ||
7945 | ||
7946 | ||
7947 | return result; | |
7948 | } | |
7949 | ||
7950 | ||
7951 | BOOLEAN RTMPAutoRateSwitchCheck( | |
7952 | IN PRTMP_ADAPTER pAd) | |
7953 | { | |
7954 | ||
7955 | #ifdef CONFIG_STA_SUPPORT | |
7956 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
7957 | { | |
7958 | if (pAd->StaCfg.bAutoTxRateSwitch) | |
7959 | return TRUE; | |
7960 | } | |
7961 | #endif // CONFIG_STA_SUPPORT // | |
7962 | return FALSE; | |
7963 | } | |
7964 | ||
7965 | ||
7966 | /* | |
7967 | ======================================================================== | |
7968 | Routine Description: | |
7969 | check if this entry need to fix tx legacy rate | |
7970 | ||
7971 | Arguments: | |
7972 | pAd | |
7973 | pEntry | |
7974 | ||
7975 | Return Value: | |
7976 | TURE | |
7977 | FALSE | |
7978 | ||
7979 | ======================================================================== | |
7980 | */ | |
7981 | UCHAR RTMPStaFixedTxMode( | |
7982 | IN PRTMP_ADAPTER pAd, | |
7983 | IN PMAC_TABLE_ENTRY pEntry) | |
7984 | { | |
7985 | UCHAR tx_mode = FIXED_TXMODE_HT; | |
7986 | ||
7987 | ||
7988 | #ifdef CONFIG_STA_SUPPORT | |
7989 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
7990 | { | |
7991 | tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode; | |
7992 | } | |
7993 | #endif // CONFIG_STA_SUPPORT // | |
7994 | ||
7995 | return tx_mode; | |
7996 | } | |
7997 | ||
7998 | /* | |
7999 | ======================================================================== | |
8000 | Routine Description: | |
8001 | Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified. | |
8002 | ||
8003 | Arguments: | |
8004 | pAd | |
8005 | pEntry | |
8006 | ||
8007 | Return Value: | |
8008 | TURE | |
8009 | FALSE | |
8010 | ||
8011 | ======================================================================== | |
8012 | */ | |
8013 | VOID RTMPUpdateLegacyTxSetting( | |
8014 | UCHAR fixed_tx_mode, | |
8015 | PMAC_TABLE_ENTRY pEntry) | |
8016 | { | |
8017 | HTTRANSMIT_SETTING TransmitSetting; | |
8018 | ||
8019 | if (fixed_tx_mode == FIXED_TXMODE_HT) | |
8020 | return; | |
8021 | ||
8022 | TransmitSetting.word = 0; | |
8023 | ||
8024 | TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; | |
8025 | TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; | |
8026 | ||
8027 | if (fixed_tx_mode == FIXED_TXMODE_CCK) | |
8028 | { | |
8029 | TransmitSetting.field.MODE = MODE_CCK; | |
8030 | // CCK mode allow MCS 0~3 | |
8031 | if (TransmitSetting.field.MCS > MCS_3) | |
8032 | TransmitSetting.field.MCS = MCS_3; | |
8033 | } | |
8034 | else | |
8035 | { | |
8036 | TransmitSetting.field.MODE = MODE_OFDM; | |
8037 | // OFDM mode allow MCS 0~7 | |
8038 | if (TransmitSetting.field.MCS > MCS_7) | |
8039 | TransmitSetting.field.MCS = MCS_7; | |
8040 | } | |
8041 | ||
8042 | if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) | |
8043 | { | |
8044 | pEntry->HTPhyMode.word = TransmitSetting.word; | |
8045 | DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", | |
8046 | pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS)); | |
8047 | } | |
8048 | } | |
8049 | ||
8050 | #ifdef CONFIG_STA_SUPPORT | |
8051 | /* | |
8052 | ========================================================================== | |
8053 | Description: | |
8054 | dynamic tune BBP R66 to find a balance between sensibility and | |
8055 | noise isolation | |
8056 | ||
8057 | IRQL = DISPATCH_LEVEL | |
8058 | ||
8059 | ========================================================================== | |
8060 | */ | |
8061 | VOID AsicStaBbpTuning( | |
8062 | IN PRTMP_ADAPTER pAd) | |
8063 | { | |
8064 | UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30; | |
8065 | CHAR Rssi; | |
8066 | ||
8067 | // 2860C did not support Fase CCA, therefore can't tune | |
8068 | if (pAd->MACVersion == 0x28600100) | |
8069 | return; | |
8070 | ||
8071 | // | |
8072 | // work as a STA | |
8073 | // | |
8074 | if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING | |
8075 | return; | |
8076 | ||
8077 | if ((pAd->OpMode == OPMODE_STA) | |
8078 | && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | |
8079 | ) | |
8080 | && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | |
bdc0a173 | 8081 | && (pAd->bPCIclkOff == FALSE)) |
91980990 GKH |
8082 | { |
8083 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value); | |
8084 | R66 = OrigR66Value; | |
8085 | ||
8086 | if (pAd->Antenna.field.RxPath > 1) | |
8087 | Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; | |
8088 | else | |
8089 | Rssi = pAd->StaCfg.RssiSample.AvgRssi0; | |
8090 | ||
8091 | if (pAd->LatchRfRegs.Channel <= 14) | |
8092 | { //BG band | |
8093 | { | |
8094 | if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) | |
8095 | { | |
8096 | R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10; | |
8097 | if (OrigR66Value != R66) | |
8098 | { | |
8099 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8100 | } | |
8101 | } | |
8102 | else | |
8103 | { | |
8104 | R66 = 0x2E + GET_LNA_GAIN(pAd); | |
8105 | if (OrigR66Value != R66) | |
8106 | { | |
8107 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8108 | } | |
8109 | } | |
8110 | } | |
8111 | } | |
8112 | else | |
8113 | { //A band | |
8114 | if (pAd->CommonCfg.BBPCurrentBW == BW_20) | |
8115 | { | |
8116 | if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) | |
8117 | { | |
8118 | R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; | |
8119 | if (OrigR66Value != R66) | |
8120 | { | |
8121 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8122 | } | |
8123 | } | |
8124 | else | |
8125 | { | |
8126 | R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3; | |
8127 | if (OrigR66Value != R66) | |
8128 | { | |
8129 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8130 | } | |
8131 | } | |
8132 | } | |
8133 | else | |
8134 | { | |
8135 | if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) | |
8136 | { | |
8137 | R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; | |
8138 | if (OrigR66Value != R66) | |
8139 | { | |
8140 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8141 | } | |
8142 | } | |
8143 | else | |
8144 | { | |
8145 | R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3; | |
8146 | if (OrigR66Value != R66) | |
8147 | { | |
8148 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8149 | } | |
8150 | } | |
8151 | } | |
8152 | } | |
8153 | ||
8154 | ||
8155 | } | |
8156 | } | |
ed291e80 AM |
8157 | |
8158 | VOID AsicResetFromDMABusy( | |
8159 | IN PRTMP_ADAPTER pAd) | |
8160 | { | |
8161 | UINT32 Data; | |
8162 | BOOLEAN bCtrl = FALSE; | |
8163 | ||
8164 | DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n")); | |
8165 | ||
8166 | // Be sure restore link control value so we can write register. | |
8167 | RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); | |
8168 | if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) | |
8169 | { | |
8170 | DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n")); | |
8171 | RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT); | |
8172 | RTMPusecDelay(6000); | |
8173 | pAd->bPCIclkOff = FALSE; | |
8174 | bCtrl = TRUE; | |
8175 | } | |
8176 | // Reset DMA | |
8177 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); | |
8178 | Data |= 0x2; | |
8179 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
8180 | ||
8181 | // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too. | |
8182 | // Reset DMA/CPU ring index | |
8183 | RTMPRingCleanUp(pAd, QID_AC_BK); | |
8184 | RTMPRingCleanUp(pAd, QID_AC_BE); | |
8185 | RTMPRingCleanUp(pAd, QID_AC_VI); | |
8186 | RTMPRingCleanUp(pAd, QID_AC_VO); | |
8187 | RTMPRingCleanUp(pAd, QID_HCCA); | |
8188 | RTMPRingCleanUp(pAd, QID_MGMT); | |
8189 | RTMPRingCleanUp(pAd, QID_RX); | |
8190 | ||
8191 | // Clear Reset | |
8192 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); | |
8193 | Data &= 0xfffffffd; | |
8194 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
8195 | ||
8196 | // If in Radio off, should call RTMPPCIePowerLinkCtrl again. | |
8197 | if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE)) | |
8198 | RTMPPCIeLinkCtrlSetting(pAd, 3); | |
8199 | ||
8200 | RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); | |
8201 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS); | |
8202 | DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n")); | |
8203 | } | |
8204 | ||
8205 | VOID AsicResetBBP( | |
8206 | IN PRTMP_ADAPTER pAd) | |
8207 | { | |
8208 | DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n")); | |
8209 | ||
8210 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); | |
8211 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2); | |
8212 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); | |
8213 | ||
8214 | // After hard-reset BBP, initialize all BBP values. | |
8215 | NICRestoreBBPValue(pAd); | |
8216 | DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n")); | |
8217 | } | |
8218 | ||
8219 | VOID AsicResetMAC( | |
8220 | IN PRTMP_ADAPTER pAd) | |
8221 | { | |
8222 | ULONG Data; | |
8223 | ||
8224 | DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n")); | |
8225 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); | |
8226 | Data |= 0x4; | |
8227 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
8228 | Data &= 0xfffffffb; | |
8229 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
8230 | ||
8231 | DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n")); | |
8232 | } | |
8233 | ||
8234 | VOID AsicResetPBF( | |
8235 | IN PRTMP_ADAPTER pAd) | |
8236 | { | |
8237 | ULONG Value1, Value2; | |
8238 | ULONG Data; | |
8239 | ||
8240 | RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1); | |
8241 | RTMP_IO_READ32(pAd, PBF_DBG, &Value2); | |
8242 | ||
8243 | Value2 &= 0xff; | |
8244 | // sum should be equals to 0xff, which is the total buffer size. | |
8245 | if ((Value1 + Value2) < 0xff) | |
8246 | { | |
8247 | DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n")); | |
8248 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); | |
8249 | Data |= 0x8; | |
8250 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
8251 | Data &= 0xfffffff7; | |
8252 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); | |
8253 | ||
8254 | DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n")); | |
8255 | } | |
8256 | } | |
91980990 GKH |
8257 | #endif // CONFIG_STA_SUPPORT // |
8258 | ||
8259 | VOID RTMPSetAGCInitValue( | |
8260 | IN PRTMP_ADAPTER pAd, | |
8261 | IN UCHAR BandWidth) | |
8262 | { | |
8263 | UCHAR R66 = 0x30; | |
8264 | ||
8265 | if (pAd->LatchRfRegs.Channel <= 14) | |
8266 | { // BG band | |
8267 | R66 = 0x2E + GET_LNA_GAIN(pAd); | |
8268 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8269 | } | |
8270 | else | |
8271 | { //A band | |
8272 | if (BandWidth == BW_20) | |
8273 | { | |
8274 | R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); | |
8275 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8276 | } | |
8277 | #ifdef DOT11_N_SUPPORT | |
8278 | else | |
8279 | { | |
8280 | R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); | |
8281 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | |
8282 | } | |
8283 | #endif // DOT11_N_SUPPORT // | |
8284 | } | |
8285 | ||
8286 | } | |
8287 | ||
8288 | VOID AsicTurnOffRFClk( | |
8289 | IN PRTMP_ADAPTER pAd, | |
8290 | IN UCHAR Channel) | |
8291 | { | |
8292 | ||
8293 | // RF R2 bit 18 = 0 | |
8294 | UINT32 R1 = 0, R2 = 0, R3 = 0; | |
8295 | UCHAR index; | |
8296 | RTMP_RF_REGS *RFRegTable; | |
8297 | ||
8298 | RFRegTable = RF2850RegTable; | |
8299 | ||
8300 | switch (pAd->RfIcType) | |
8301 | { | |
8302 | case RFIC_2820: | |
8303 | case RFIC_2850: | |
8304 | case RFIC_2720: | |
8305 | case RFIC_2750: | |
8306 | ||
8307 | for (index = 0; index < NUM_OF_2850_CHNL; index++) | |
8308 | { | |
8309 | if (Channel == RFRegTable[index].Channel) | |
8310 | { | |
8311 | R1 = RFRegTable[index].R1 & 0xffffdfff; | |
8312 | R2 = RFRegTable[index].R2 & 0xfffbffff; | |
8313 | R3 = RFRegTable[index].R3 & 0xfff3ffff; | |
8314 | ||
8315 | RTMP_RF_IO_WRITE32(pAd, R1); | |
8316 | RTMP_RF_IO_WRITE32(pAd, R2); | |
8317 | ||
8318 | // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. | |
8319 | // Set RF R2 bit18=0, R3 bit[18:19]=0 | |
8320 | //if (pAd->StaCfg.bRadio == FALSE) | |
8321 | if (1) | |
8322 | { | |
8323 | RTMP_RF_IO_WRITE32(pAd, R3); | |
8324 | ||
8325 | DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", | |
8326 | Channel, pAd->RfIcType, R2, R3)); | |
8327 | } | |
8328 | else | |
8329 | DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", | |
8330 | Channel, pAd->RfIcType, R2)); | |
8331 | break; | |
8332 | } | |
8333 | } | |
8334 | break; | |
8335 | ||
8336 | default: | |
8337 | break; | |
8338 | } | |
8339 | } | |
8340 | ||
8341 | ||
8342 | VOID AsicTurnOnRFClk( | |
8343 | IN PRTMP_ADAPTER pAd, | |
8344 | IN UCHAR Channel) | |
8345 | { | |
8346 | ||
8347 | // RF R2 bit 18 = 0 | |
8348 | UINT32 R1 = 0, R2 = 0, R3 = 0; | |
8349 | UCHAR index; | |
8350 | RTMP_RF_REGS *RFRegTable; | |
8351 | ||
8352 | RFRegTable = RF2850RegTable; | |
8353 | ||
8354 | switch (pAd->RfIcType) | |
8355 | { | |
8356 | case RFIC_2820: | |
8357 | case RFIC_2850: | |
8358 | case RFIC_2720: | |
8359 | case RFIC_2750: | |
8360 | ||
8361 | for (index = 0; index < NUM_OF_2850_CHNL; index++) | |
8362 | { | |
8363 | if (Channel == RFRegTable[index].Channel) | |
8364 | { | |
8365 | R3 = pAd->LatchRfRegs.R3; | |
8366 | R3 &= 0xfff3ffff; | |
8367 | R3 |= 0x00080000; | |
8368 | RTMP_RF_IO_WRITE32(pAd, R3); | |
8369 | ||
8370 | R1 = RFRegTable[index].R1; | |
8371 | RTMP_RF_IO_WRITE32(pAd, R1); | |
8372 | ||
8373 | R2 = RFRegTable[index].R2; | |
8374 | if (pAd->Antenna.field.TxPath == 1) | |
8375 | { | |
8376 | R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; | |
8377 | } | |
8378 | ||
8379 | if (pAd->Antenna.field.RxPath == 2) | |
8380 | { | |
8381 | R2 |= 0x40; // write 1 to off Rxpath. | |
8382 | } | |
8383 | else if (pAd->Antenna.field.RxPath == 1) | |
8384 | { | |
8385 | R2 |= 0x20040; // write 1 to off RxPath | |
8386 | } | |
8387 | RTMP_RF_IO_WRITE32(pAd, R2); | |
8388 | ||
8389 | break; | |
8390 | } | |
8391 | } | |
8392 | break; | |
8393 | ||
8394 | default: | |
8395 | break; | |
8396 | } | |
8397 | ||
8398 | DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n", | |
8399 | Channel, | |
8400 | pAd->RfIcType, | |
8401 | R2)); | |
8402 | } | |
8403 |