Staging: rtxxx0: unify MlmeCheckPsmChange()
[linux-2.6/linux-2.6-openrd.git] / drivers / staging / rt2860 / common / mlme.c
blobb7bf17d756cf0bac54c931cddda3d56b4b9e51a2
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
27 Module Name:
28 mlme.c
30 Abstract:
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
39 #include "../rt_config.h"
40 #include <stdarg.h>
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
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 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
55 UCHAR RateSwitchTable[] = {
56 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
57 0x11, 0x00, 0, 0, 0, // Initial used item after association
58 0x00, 0x00, 0, 40, 101,
59 0x01, 0x00, 1, 40, 50,
60 0x02, 0x00, 2, 35, 45,
61 0x03, 0x00, 3, 20, 45,
62 0x04, 0x21, 0, 30, 50,
63 0x05, 0x21, 1, 20, 50,
64 0x06, 0x21, 2, 20, 50,
65 0x07, 0x21, 3, 15, 50,
66 0x08, 0x21, 4, 15, 30,
67 0x09, 0x21, 5, 10, 25,
68 0x0a, 0x21, 6, 8, 25,
69 0x0b, 0x21, 7, 8, 25,
70 0x0c, 0x20, 12, 15, 30,
71 0x0d, 0x20, 13, 8, 20,
72 0x0e, 0x20, 14, 8, 20,
73 0x0f, 0x20, 15, 8, 25,
74 0x10, 0x22, 15, 8, 25,
75 0x11, 0x00, 0, 0, 0,
76 0x12, 0x00, 0, 0, 0,
77 0x13, 0x00, 0, 0, 0,
78 0x14, 0x00, 0, 0, 0,
79 0x15, 0x00, 0, 0, 0,
80 0x16, 0x00, 0, 0, 0,
81 0x17, 0x00, 0, 0, 0,
82 0x18, 0x00, 0, 0, 0,
83 0x19, 0x00, 0, 0, 0,
84 0x1a, 0x00, 0, 0, 0,
85 0x1b, 0x00, 0, 0, 0,
86 0x1c, 0x00, 0, 0, 0,
87 0x1d, 0x00, 0, 0, 0,
88 0x1e, 0x00, 0, 0, 0,
89 0x1f, 0x00, 0, 0, 0,
92 UCHAR RateSwitchTable11B[] = {
93 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
94 0x04, 0x03, 0, 0, 0, // Initial used item after association
95 0x00, 0x00, 0, 40, 101,
96 0x01, 0x00, 1, 40, 50,
97 0x02, 0x00, 2, 35, 45,
98 0x03, 0x00, 3, 20, 45,
101 UCHAR RateSwitchTable11BG[] = {
102 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
103 0x0a, 0x00, 0, 0, 0, // Initial used item after association
104 0x00, 0x00, 0, 40, 101,
105 0x01, 0x00, 1, 40, 50,
106 0x02, 0x00, 2, 35, 45,
107 0x03, 0x00, 3, 20, 45,
108 0x04, 0x10, 2, 20, 35,
109 0x05, 0x10, 3, 16, 35,
110 0x06, 0x10, 4, 10, 25,
111 0x07, 0x10, 5, 16, 25,
112 0x08, 0x10, 6, 10, 25,
113 0x09, 0x10, 7, 10, 13,
116 UCHAR RateSwitchTable11G[] = {
117 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
118 0x08, 0x00, 0, 0, 0, // Initial used item after association
119 0x00, 0x10, 0, 20, 101,
120 0x01, 0x10, 1, 20, 35,
121 0x02, 0x10, 2, 20, 35,
122 0x03, 0x10, 3, 16, 35,
123 0x04, 0x10, 4, 10, 25,
124 0x05, 0x10, 5, 16, 25,
125 0x06, 0x10, 6, 10, 25,
126 0x07, 0x10, 7, 10, 13,
129 UCHAR RateSwitchTable11N1S[] = {
130 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
131 0x09, 0x00, 0, 0, 0, // Initial used item after association
132 0x00, 0x21, 0, 30, 101,
133 0x01, 0x21, 1, 20, 50,
134 0x02, 0x21, 2, 20, 50,
135 0x03, 0x21, 3, 15, 50,
136 0x04, 0x21, 4, 15, 30,
137 0x05, 0x21, 5, 10, 25,
138 0x06, 0x21, 6, 8, 14,
139 0x07, 0x21, 7, 8, 14,
140 0x08, 0x23, 7, 8, 14,
143 UCHAR RateSwitchTable11N2S[] = {
144 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
145 0x0a, 0x00, 0, 0, 0, // Initial used item after association
146 0x00, 0x21, 0, 30, 101,
147 0x01, 0x21, 1, 20, 50,
148 0x02, 0x21, 2, 20, 50,
149 0x03, 0x21, 3, 15, 50,
150 0x04, 0x21, 4, 15, 30,
151 0x05, 0x20, 12, 15, 30,
152 0x06, 0x20, 13, 8, 20,
153 0x07, 0x20, 14, 8, 20,
154 0x08, 0x20, 15, 8, 25,
155 0x09, 0x22, 15, 8, 25,
158 UCHAR RateSwitchTable11N3S[] = {
159 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
160 0x0a, 0x00, 0, 0, 0, // Initial used item after association
161 0x00, 0x21, 0, 30, 101,
162 0x01, 0x21, 1, 20, 50,
163 0x02, 0x21, 2, 20, 50,
164 0x03, 0x21, 3, 15, 50,
165 0x04, 0x21, 4, 15, 30,
166 0x05, 0x20, 12, 15, 30,
167 0x06, 0x20, 13, 8, 20,
168 0x07, 0x20, 14, 8, 20,
169 0x08, 0x20, 15, 8, 25,
170 0x09, 0x22, 15, 8, 25,
173 UCHAR RateSwitchTable11N2SForABand[] = {
174 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
175 0x0b, 0x09, 0, 0, 0, // Initial used item after association
176 0x00, 0x21, 0, 30, 101,
177 0x01, 0x21, 1, 20, 50,
178 0x02, 0x21, 2, 20, 50,
179 0x03, 0x21, 3, 15, 50,
180 0x04, 0x21, 4, 15, 30,
181 0x05, 0x21, 5, 15, 30,
182 0x06, 0x20, 12, 15, 30,
183 0x07, 0x20, 13, 8, 20,
184 0x08, 0x20, 14, 8, 20,
185 0x09, 0x20, 15, 8, 25,
186 0x0a, 0x22, 15, 8, 25,
189 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
190 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
191 0x0b, 0x09, 0, 0, 0, // Initial used item after association
192 0x00, 0x21, 0, 30, 101,
193 0x01, 0x21, 1, 20, 50,
194 0x02, 0x21, 2, 20, 50,
195 0x03, 0x21, 3, 15, 50,
196 0x04, 0x21, 4, 15, 30,
197 0x05, 0x21, 5, 15, 30,
198 0x06, 0x20, 12, 15, 30,
199 0x07, 0x20, 13, 8, 20,
200 0x08, 0x20, 14, 8, 20,
201 0x09, 0x20, 15, 8, 25,
202 0x0a, 0x22, 15, 8, 25,
205 UCHAR RateSwitchTable11BGN1S[] = {
206 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
207 0x0d, 0x00, 0, 0, 0, // Initial used item after association
208 0x00, 0x00, 0, 40, 101,
209 0x01, 0x00, 1, 40, 50,
210 0x02, 0x00, 2, 35, 45,
211 0x03, 0x00, 3, 20, 45,
212 0x04, 0x21, 0, 30,101, //50
213 0x05, 0x21, 1, 20, 50,
214 0x06, 0x21, 2, 20, 50,
215 0x07, 0x21, 3, 15, 50,
216 0x08, 0x21, 4, 15, 30,
217 0x09, 0x21, 5, 10, 25,
218 0x0a, 0x21, 6, 8, 14,
219 0x0b, 0x21, 7, 8, 14,
220 0x0c, 0x23, 7, 8, 14,
223 UCHAR RateSwitchTable11BGN2S[] = {
224 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
225 0x0a, 0x00, 0, 0, 0, // Initial used item after association
226 0x00, 0x21, 0, 30,101, //50
227 0x01, 0x21, 1, 20, 50,
228 0x02, 0x21, 2, 20, 50,
229 0x03, 0x21, 3, 15, 50,
230 0x04, 0x21, 4, 15, 30,
231 0x05, 0x20, 12, 15, 30,
232 0x06, 0x20, 13, 8, 20,
233 0x07, 0x20, 14, 8, 20,
234 0x08, 0x20, 15, 8, 25,
235 0x09, 0x22, 15, 8, 25,
238 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
239 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
240 0x0a, 0x00, 0, 0, 0, // Initial used item after association
241 0x00, 0x21, 0, 30,101, //50
242 0x01, 0x21, 1, 20, 50,
243 0x02, 0x21, 2, 20, 50,
244 0x03, 0x21, 3, 20, 50,
245 0x04, 0x21, 4, 15, 50,
246 0x05, 0x20, 20, 15, 30,
247 0x06, 0x20, 21, 8, 20,
248 0x07, 0x20, 22, 8, 20,
249 0x08, 0x20, 23, 8, 25,
250 0x09, 0x22, 23, 8, 25,
253 UCHAR RateSwitchTable11BGN2SForABand[] = {
254 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
255 0x0b, 0x09, 0, 0, 0, // Initial used item after association
256 0x00, 0x21, 0, 30,101, //50
257 0x01, 0x21, 1, 20, 50,
258 0x02, 0x21, 2, 20, 50,
259 0x03, 0x21, 3, 15, 50,
260 0x04, 0x21, 4, 15, 30,
261 0x05, 0x21, 5, 15, 30,
262 0x06, 0x20, 12, 15, 30,
263 0x07, 0x20, 13, 8, 20,
264 0x08, 0x20, 14, 8, 20,
265 0x09, 0x20, 15, 8, 25,
266 0x0a, 0x22, 15, 8, 25,
269 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
270 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
271 0x0c, 0x09, 0, 0, 0, // Initial used item after association
272 0x00, 0x21, 0, 30,101, //50
273 0x01, 0x21, 1, 20, 50,
274 0x02, 0x21, 2, 20, 50,
275 0x03, 0x21, 3, 15, 50,
276 0x04, 0x21, 4, 15, 30,
277 0x05, 0x21, 5, 15, 30,
278 0x06, 0x21, 12, 15, 30,
279 0x07, 0x20, 20, 15, 30,
280 0x08, 0x20, 21, 8, 20,
281 0x09, 0x20, 22, 8, 20,
282 0x0a, 0x20, 23, 8, 25,
283 0x0b, 0x22, 23, 8, 25,
286 PUCHAR ReasonString[] = {
287 /* 0 */ "Reserved",
288 /* 1 */ "Unspecified Reason",
289 /* 2 */ "Previous Auth no longer valid",
290 /* 3 */ "STA is leaving / has left",
291 /* 4 */ "DIS-ASSOC due to inactivity",
292 /* 5 */ "AP unable to hanle all associations",
293 /* 6 */ "class 2 error",
294 /* 7 */ "class 3 error",
295 /* 8 */ "STA is leaving / has left",
296 /* 9 */ "require auth before assoc/re-assoc",
297 /* 10 */ "Reserved",
298 /* 11 */ "Reserved",
299 /* 12 */ "Reserved",
300 /* 13 */ "invalid IE",
301 /* 14 */ "MIC error",
302 /* 15 */ "4-way handshake timeout",
303 /* 16 */ "2-way (group key) handshake timeout",
304 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
305 /* 18 */
308 extern UCHAR OfdmRateToRxwiMCS[];
309 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
310 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
311 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
312 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
313 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
315 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
316 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
317 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
319 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
320 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
321 // clean environment.
322 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
323 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
325 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
326 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
328 UCHAR SsidIe = IE_SSID;
329 UCHAR SupRateIe = IE_SUPP_RATES;
330 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
331 UCHAR HtCapIe = IE_HT_CAP;
332 UCHAR AddHtInfoIe = IE_ADD_HT;
333 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
334 UCHAR ErpIe = IE_ERP;
335 UCHAR DsIe = IE_DS_PARM;
336 UCHAR TimIe = IE_TIM;
337 UCHAR WpaIe = IE_WPA;
338 UCHAR Wpa2Ie = IE_WPA2;
339 UCHAR IbssIe = IE_IBSS_PARM;
340 UCHAR Ccx2Ie = IE_CCX_V2;
341 #ifdef RT2870
342 UCHAR WapiIe = IE_WAPI;
343 #endif
345 extern UCHAR WPA_OUI[];
347 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
349 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
350 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
352 // Reset the RFIC setting to new series
353 RTMP_RF_REGS RF2850RegTable[] = {
354 // ch R1 R2 R3(TX0~4=0) R4
355 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
356 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
357 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
358 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
359 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
360 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
361 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
362 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
363 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
364 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
365 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
366 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
367 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
368 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
370 // 802.11 UNI / HyperLan 2
371 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
372 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
373 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
374 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
375 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
376 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
377 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
378 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
379 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
380 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
381 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
382 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
384 // 802.11 HyperLan 2
385 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
387 // 2008.04.30 modified
388 // The system team has AN to improve the EVM value
389 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
390 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
391 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
392 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
394 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
395 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
396 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
397 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
398 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
399 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
400 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
401 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
402 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
403 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
404 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
405 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
407 // 802.11 UNII
408 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
409 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
410 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
411 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
412 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
413 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
414 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
416 // Japan
417 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
418 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
419 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
420 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
421 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
422 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
423 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
425 // still lack of MMAC(Japan) ch 34,38,42,46
427 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
429 FREQUENCY_ITEM FreqItems3020[] =
431 /**************************************************/
432 // ISM : 2.4 to 2.483 GHz //
433 /**************************************************/
434 // 11g
435 /**************************************************/
436 //-CH---N-------R---K-----------
437 {1, 241, 2, 2},
438 {2, 241, 2, 7},
439 {3, 242, 2, 2},
440 {4, 242, 2, 7},
441 {5, 243, 2, 2},
442 {6, 243, 2, 7},
443 {7, 244, 2, 2},
444 {8, 244, 2, 7},
445 {9, 245, 2, 2},
446 {10, 245, 2, 7},
447 {11, 246, 2, 2},
448 {12, 246, 2, 7},
449 {13, 247, 2, 2},
450 {14, 248, 2, 4},
452 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
455 ==========================================================================
456 Description:
457 initialize the MLME task and its data structure (queue, spinlock,
458 timer, state machines).
460 IRQL = PASSIVE_LEVEL
462 Return:
463 always return NDIS_STATUS_SUCCESS
465 ==========================================================================
467 NDIS_STATUS MlmeInit(
468 IN PRTMP_ADAPTER pAd)
470 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
472 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
476 Status = MlmeQueueInit(&pAd->Mlme.Queue);
477 if(Status != NDIS_STATUS_SUCCESS)
478 break;
480 pAd->Mlme.bRunning = FALSE;
481 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
484 BssTableInit(&pAd->ScanTab);
486 // init STA state machines
487 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
488 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
489 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
490 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
491 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
492 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
494 // Since we are using switch/case to implement it, the init is different from the above
495 // state machine init
496 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
499 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
501 // Init mlme periodic timer
502 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
504 // Set mlme periodic timer
505 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
507 // software-based RX Antenna diversity
508 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
510 #ifdef RT2860
512 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
514 // only PCIe cards need these two timers
515 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
516 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
519 #endif
520 } while (FALSE);
522 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
524 return Status;
528 ==========================================================================
529 Description:
530 main loop of the MLME
531 Pre:
532 Mlme has to be initialized, and there are something inside the queue
533 Note:
534 This function is invoked from MPSetInformation and MPReceive;
535 This task guarantee only one MlmeHandler will run.
537 IRQL = DISPATCH_LEVEL
539 ==========================================================================
541 VOID MlmeHandler(
542 IN PRTMP_ADAPTER pAd)
544 MLME_QUEUE_ELEM *Elem = NULL;
546 // Only accept MLME and Frame from peer side, no other (control/data) frame should
547 // get into this state machine
549 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
550 if(pAd->Mlme.bRunning)
552 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
553 return;
555 else
557 pAd->Mlme.bRunning = TRUE;
559 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
561 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
563 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
564 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
565 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
567 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
568 break;
571 //From message type, determine which state machine I should drive
572 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
574 #ifdef RT2870
575 if (Elem->MsgType == MT2_RESET_CONF)
577 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
578 MlmeRestartStateMachine(pAd);
579 Elem->Occupied = FALSE;
580 Elem->MsgLen = 0;
581 continue;
583 #endif // RT2870 //
585 // if dequeue success
586 switch (Elem->Machine)
588 // STA state machines
589 case ASSOC_STATE_MACHINE:
590 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
591 break;
592 case AUTH_STATE_MACHINE:
593 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
594 break;
595 case AUTH_RSP_STATE_MACHINE:
596 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
597 break;
598 case SYNC_STATE_MACHINE:
599 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
600 break;
601 case MLME_CNTL_STATE_MACHINE:
602 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
603 break;
604 case WPA_PSK_STATE_MACHINE:
605 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
606 break;
607 case AIRONET_STATE_MACHINE:
608 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
609 break;
610 case ACTION_STATE_MACHINE:
611 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
612 break;
617 default:
618 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
619 break;
620 } // end of switch
622 // free MLME element
623 Elem->Occupied = FALSE;
624 Elem->MsgLen = 0;
627 else {
628 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
632 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
633 pAd->Mlme.bRunning = FALSE;
634 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
638 ==========================================================================
639 Description:
640 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
641 Parameters:
642 Adapter - NIC Adapter pointer
643 Post:
644 The MLME task will no longer work properly
646 IRQL = PASSIVE_LEVEL
648 ==========================================================================
650 VOID MlmeHalt(
651 IN PRTMP_ADAPTER pAd)
653 BOOLEAN Cancelled;
654 #ifdef RT3070
655 UINT32 TxPinCfg = 0x00050F0F;
656 #endif // RT3070 //
658 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
660 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
662 // disable BEACON generation and other BEACON related hardware timers
663 AsicDisableSync(pAd);
667 // Cancel pending timers
668 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
669 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
670 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
671 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
672 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
673 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
674 #ifdef RT2860
675 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
677 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
678 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
680 #endif
683 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
684 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
688 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
690 // Set LED
691 RTMPSetLED(pAd, LED_HALT);
692 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
693 #ifdef RT2870
695 LED_CFG_STRUC LedCfg;
696 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
697 LedCfg.field.LedPolar = 0;
698 LedCfg.field.RLedMode = 0;
699 LedCfg.field.GLedMode = 0;
700 LedCfg.field.YLedMode = 0;
701 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
703 #endif // RT2870 //
704 #ifdef RT3070
706 // Turn off LNA_PE
708 if (IS_RT3070(pAd) || IS_RT3071(pAd))
710 TxPinCfg &= 0xFFFFF0F0;
711 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
713 #endif // RT3070 //
716 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
718 MlmeQueueDestroy(&pAd->Mlme.Queue);
719 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
721 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
724 VOID MlmeResetRalinkCounters(
725 IN PRTMP_ADAPTER pAd)
727 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
728 // clear all OneSecxxx counters.
729 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
730 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
731 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
732 pAd->RalinkCounters.OneSecRxOkCnt = 0;
733 pAd->RalinkCounters.OneSecTxFailCount = 0;
734 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
735 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
736 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
738 // TODO: for debug only. to be removed
739 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
740 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
741 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
742 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
743 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
744 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
745 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
746 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
747 pAd->RalinkCounters.OneSecTxDoneCount = 0;
748 pAd->RalinkCounters.OneSecRxCount = 0;
749 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
750 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
752 return;
755 unsigned long rx_AMSDU;
756 unsigned long rx_Total;
759 ==========================================================================
760 Description:
761 This routine is executed periodically to -
762 1. Decide if it's a right time to turn on PwrMgmt bit of all
763 outgoiing frames
764 2. Calculate ChannelQuality based on statistics of the last
765 period, so that TX rate won't toggling very frequently between a
766 successful TX and a failed TX.
767 3. If the calculated ChannelQuality indicated current connection not
768 healthy, then a ROAMing attempt is tried here.
770 IRQL = DISPATCH_LEVEL
772 ==========================================================================
774 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
775 VOID MlmePeriodicExec(
776 IN PVOID SystemSpecific1,
777 IN PVOID FunctionContext,
778 IN PVOID SystemSpecific2,
779 IN PVOID SystemSpecific3)
781 ULONG TxTotalCnt;
782 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
784 #ifdef RT2860
785 //Baron 2008/07/10
786 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
787 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
788 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
789 if(pAd->StaCfg.WepStatus<2)
791 pAd->StaCfg.WpaSupplicantUP = 0;
793 else
795 pAd->StaCfg.WpaSupplicantUP = 1;
799 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
800 // Move code to here, because following code will return when radio is off
801 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
802 (pAd->StaCfg.bHardwareRadio == TRUE) &&
803 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
804 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
805 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
807 UINT32 data = 0;
809 // Read GPIO pin2 as Hardware controlled radio state
810 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
811 if (data & 0x04)
813 pAd->StaCfg.bHwRadio = TRUE;
815 else
817 pAd->StaCfg.bHwRadio = FALSE;
819 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
821 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
822 if (pAd->StaCfg.bRadio == TRUE)
824 MlmeRadioOn(pAd);
825 // Update extra information
826 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
828 else
830 MlmeRadioOff(pAd);
831 // Update extra information
832 pAd->ExtraInfo = HW_RADIO_OFF;
837 #endif /* RT2860 */
839 // Do nothing if the driver is starting halt state.
840 // This might happen when timer already been fired before cancel timer with mlmehalt
841 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
842 fRTMP_ADAPTER_RADIO_OFF |
843 fRTMP_ADAPTER_RADIO_MEASUREMENT |
844 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
845 return;
847 #ifdef RT2860
849 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
851 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
852 pAd->SameRxByteCount++;
854 else
855 pAd->SameRxByteCount = 0;
857 // If after BBP, still not work...need to check to reset PBF&MAC.
858 if (pAd->SameRxByteCount == 702)
860 pAd->SameRxByteCount = 0;
861 AsicResetPBF(pAd);
862 AsicResetMAC(pAd);
865 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
866 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
868 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
870 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
871 pAd->SameRxByteCount = 700;
872 AsicResetBBP(pAd);
876 // Update lastReceiveByteCount.
877 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
879 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
881 pAd->CheckDmaBusyCount = 0;
882 AsicResetFromDMABusy(pAd);
885 #endif /* RT2860 */
886 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
889 // Do nothing if monitor mode is on
890 if (MONITOR_ON(pAd))
891 return;
893 if (pAd->Mlme.PeriodicRound & 0x1)
895 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
896 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
897 (STA_TGN_WIFI_ON(pAd)) &&
898 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
901 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
902 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
904 else if ((STA_TGN_WIFI_ON(pAd)) &&
905 ((pAd->MACVersion & 0xffff) == 0x0101))
907 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
908 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
913 pAd->bUpdateBcnCntDone = FALSE;
915 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
916 pAd->Mlme.PeriodicRound ++;
918 #ifdef RT3070
919 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
920 NICUpdateFifoStaCounters(pAd);
921 #endif // RT3070 //
922 // execute every 500ms
923 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
925 // perform dynamic tx rate switching based on past TX history
927 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
929 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
930 MlmeDynamicTxRateSwitching(pAd);
934 // Normal 1 second Mlme PeriodicExec.
935 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
937 pAd->Mlme.OneSecPeriodicRound ++;
939 if (rx_Total)
942 // reset counters
943 rx_AMSDU = 0;
944 rx_Total = 0;
947 // Media status changed, report to NDIS
948 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
950 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
951 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
953 pAd->IndicateMediaState = NdisMediaStateConnected;
954 RTMP_IndicateMediaState(pAd);
957 else
959 pAd->IndicateMediaState = NdisMediaStateDisconnected;
960 RTMP_IndicateMediaState(pAd);
964 NdisGetSystemUpTime(&pAd->Mlme.Now32);
966 // add the most up-to-date h/w raw counters into software variable, so that
967 // the dynamic tuning mechanism below are based on most up-to-date information
968 NICUpdateRawCounters(pAd);
970 #ifdef RT2870
971 RT2870_WatchDog(pAd);
972 #endif // RT2870 //
974 // Need statistics after read counter. So put after NICUpdateRawCounters
975 ORIBATimerTimeout(pAd);
977 // The time period for checking antenna is according to traffic
978 if (pAd->Mlme.bEnableAutoAntennaCheck)
980 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
981 pAd->RalinkCounters.OneSecTxRetryOkCount +
982 pAd->RalinkCounters.OneSecTxFailCount;
984 // dynamic adjust antenna evaluation period according to the traffic
985 if (TxTotalCnt > 50)
987 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
989 AsicEvaluateRxAnt(pAd);
992 else
994 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
996 AsicEvaluateRxAnt(pAd);
1001 STAMlmePeriodicExec(pAd);
1003 MlmeResetRalinkCounters(pAd);
1006 #ifdef RT2860
1007 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1008 #endif
1010 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1011 // and sending CTS-to-self over and over.
1012 // Software Patch Solution:
1013 // 1. Polling debug state register 0x10F4 every one second.
1014 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1015 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1017 UINT32 MacReg = 0;
1019 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1020 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1022 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1023 RTMPusecDelay(1);
1024 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1026 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1031 RT28XX_MLME_HANDLER(pAd);
1034 pAd->bUpdateBcnCntDone = FALSE;
1037 VOID STAMlmePeriodicExec(
1038 PRTMP_ADAPTER pAd)
1040 #ifdef RT2860
1041 ULONG TxTotalCnt;
1042 #endif
1043 #ifdef RT2870
1044 ULONG TxTotalCnt;
1045 int i;
1046 #endif
1048 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1050 // WPA MIC error should block association attempt for 60 seconds
1051 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1052 pAd->StaCfg.bBlockAssoc = FALSE;
1055 #ifdef RT2860
1056 //Baron 2008/07/10
1057 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1058 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1059 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1060 if(pAd->StaCfg.WepStatus<2)
1062 pAd->StaCfg.WpaSupplicantUP = 0;
1064 else
1066 pAd->StaCfg.WpaSupplicantUP = 1;
1068 #endif
1070 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1072 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1074 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1076 pAd->PreMediaState = pAd->IndicateMediaState;
1079 #ifdef RT2860
1080 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1081 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1082 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1083 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1084 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1085 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1087 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1089 #endif
1093 AsicStaBbpTuning(pAd);
1095 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1096 pAd->RalinkCounters.OneSecTxRetryOkCount +
1097 pAd->RalinkCounters.OneSecTxFailCount;
1099 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1101 // update channel quality for Roaming and UI LinkQuality display
1102 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1105 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1106 // Radio is currently in noisy environment
1107 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1108 AsicAdjustTxPower(pAd);
1110 if (INFRA_ON(pAd))
1112 // Is PSM bit consistent with user power management policy?
1113 // This is the only place that will set PSM bit ON.
1114 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1115 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1117 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1119 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1120 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1121 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1123 RTMPSetAGCInitValue(pAd, BW_20);
1124 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1128 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1130 // When APSD is enabled, the period changes as 20 sec
1131 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1132 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1134 else
1136 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1137 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1139 if (pAd->CommonCfg.bWmmCapable)
1140 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1141 else
1142 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1147 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1149 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1150 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1151 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1153 // Lost AP, send disconnect & link down event
1154 LinkDown(pAd, FALSE);
1157 union iwreq_data wrqu;
1158 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1159 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1162 MlmeAutoReconnectLastSSID(pAd);
1164 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1166 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1167 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1168 MlmeAutoReconnectLastSSID(pAd);
1171 // Add auto seamless roaming
1172 if (pAd->StaCfg.bFastRoaming)
1174 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1176 DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
1178 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1180 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1184 else if (ADHOC_ON(pAd))
1186 #ifdef RT2860
1187 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1188 // the "TX BEACON competition" for the entire past 1 sec.
1189 // So that even when ASIC's BEACONgen engine been blocked
1190 // by peer's BEACON due to slower system clock, this STA still can send out
1191 // minimum BEACON to tell the peer I'm alive.
1192 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1193 // EnqueueBeaconFrame(pAd); // software send BEACON
1195 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1196 // restore outgoing BEACON to support B/G-mixed mode
1197 if ((pAd->CommonCfg.Channel <= 14) &&
1198 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1199 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1200 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1202 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1203 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1204 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1205 MlmeUpdateTxRates(pAd, FALSE, 0);
1206 MakeIbssBeacon(pAd); // re-build BEACON frame
1207 AsicEnableIbssSync(pAd); // copy to on-chip memory
1208 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1211 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1213 if ((pAd->StaCfg.AdhocBGJoined) &&
1214 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1216 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1217 pAd->StaCfg.AdhocBGJoined = FALSE;
1220 if ((pAd->StaCfg.Adhoc20NJoined) &&
1221 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1223 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1224 pAd->StaCfg.Adhoc20NJoined = FALSE;
1227 #endif /* RT2860 */
1229 //radar detect
1230 if ((pAd->CommonCfg.Channel > 14)
1231 && (pAd->CommonCfg.bIEEE80211H == 1)
1232 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1234 RadarDetectPeriodic(pAd);
1237 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1238 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1239 // join later.
1240 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1241 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1243 MLME_START_REQ_STRUCT StartReq;
1245 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1246 LinkDown(pAd, FALSE);
1248 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1249 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1250 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1253 #ifdef RT2870
1254 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1256 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1258 if (pEntry->ValidAsCLI == FALSE)
1259 continue;
1261 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1262 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1264 #endif
1266 else // no INFRA nor ADHOC connection
1269 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1270 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1271 goto SKIP_AUTO_SCAN_CONN;
1272 else
1273 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1275 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1276 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1277 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1279 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1281 MLME_SCAN_REQ_STRUCT ScanReq;
1283 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1285 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1286 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1287 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1288 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1289 // Reset Missed scan number
1290 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1292 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1293 MlmeAutoReconnectLastSSID(pAd);
1295 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1297 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1299 MlmeAutoScan(pAd);
1300 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1302 else
1304 MlmeAutoReconnectLastSSID(pAd);
1310 SKIP_AUTO_SCAN_CONN:
1312 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1314 pAd->MacTab.fAnyBASession = TRUE;
1315 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1317 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1319 pAd->MacTab.fAnyBASession = FALSE;
1320 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1323 return;
1326 // Link down report
1327 VOID LinkDownExec(
1328 IN PVOID SystemSpecific1,
1329 IN PVOID FunctionContext,
1330 IN PVOID SystemSpecific2,
1331 IN PVOID SystemSpecific3)
1334 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1336 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1337 RTMP_IndicateMediaState(pAd);
1338 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1341 // IRQL = DISPATCH_LEVEL
1342 VOID MlmeAutoScan(
1343 IN PRTMP_ADAPTER pAd)
1345 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1346 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1348 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1349 MlmeEnqueue(pAd,
1350 MLME_CNTL_STATE_MACHINE,
1351 OID_802_11_BSSID_LIST_SCAN,
1353 NULL);
1354 RT28XX_MLME_HANDLER(pAd);
1358 // IRQL = DISPATCH_LEVEL
1359 VOID MlmeAutoReconnectLastSSID(
1360 IN PRTMP_ADAPTER pAd)
1364 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1365 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1366 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1368 NDIS_802_11_SSID OidSsid;
1369 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1370 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1372 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1373 MlmeEnqueue(pAd,
1374 MLME_CNTL_STATE_MACHINE,
1375 OID_802_11_SSID,
1376 sizeof(NDIS_802_11_SSID),
1377 &OidSsid);
1378 RT28XX_MLME_HANDLER(pAd);
1383 ==========================================================================
1384 Validate SSID for connection try and rescan purpose
1385 Valid SSID will have visible chars only.
1386 The valid length is from 0 to 32.
1387 IRQL = DISPATCH_LEVEL
1388 ==========================================================================
1390 BOOLEAN MlmeValidateSSID(
1391 IN PUCHAR pSsid,
1392 IN UCHAR SsidLen)
1394 int index;
1396 if (SsidLen > MAX_LEN_OF_SSID)
1397 return (FALSE);
1399 // Check each character value
1400 for (index = 0; index < SsidLen; index++)
1402 if (pSsid[index] < 0x20)
1403 return (FALSE);
1406 // All checked
1407 return (TRUE);
1410 VOID MlmeSelectTxRateTable(
1411 IN PRTMP_ADAPTER pAd,
1412 IN PMAC_TABLE_ENTRY pEntry,
1413 IN PUCHAR *ppTable,
1414 IN PUCHAR pTableSize,
1415 IN PUCHAR pInitTxRateIdx)
1419 // decide the rate table for tuning
1420 if (pAd->CommonCfg.TxRateTableSize > 0)
1422 *ppTable = RateSwitchTable;
1423 *pTableSize = RateSwitchTable[0];
1424 *pInitTxRateIdx = RateSwitchTable[1];
1426 break;
1429 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1431 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1432 #ifdef RT2860
1433 !pAd->StaCfg.AdhocBOnlyJoined &&
1434 !pAd->StaCfg.AdhocBGJoined &&
1435 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1436 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1437 #endif
1438 #ifdef RT2870
1439 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1440 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1441 #endif
1442 {// 11N 1S Adhoc
1443 *ppTable = RateSwitchTable11N1S;
1444 *pTableSize = RateSwitchTable11N1S[0];
1445 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1448 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1449 #ifdef RT2860
1450 !pAd->StaCfg.AdhocBOnlyJoined &&
1451 !pAd->StaCfg.AdhocBGJoined &&
1452 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1453 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1454 #endif
1455 #ifdef RT2870
1456 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1457 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1458 #endif
1459 (pAd->Antenna.field.TxPath == 2))
1460 {// 11N 2S Adhoc
1461 if (pAd->LatchRfRegs.Channel <= 14)
1463 *ppTable = RateSwitchTable11N2S;
1464 *pTableSize = RateSwitchTable11N2S[0];
1465 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1467 else
1469 *ppTable = RateSwitchTable11N2SForABand;
1470 *pTableSize = RateSwitchTable11N2SForABand[0];
1471 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1475 else
1476 #ifdef RT2860
1477 if (pAd->CommonCfg.PhyMode == PHY_11B)
1479 *ppTable = RateSwitchTable11B;
1480 *pTableSize = RateSwitchTable11B[0];
1481 *pInitTxRateIdx = RateSwitchTable11B[1];
1484 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1485 #endif
1486 #ifdef RT2870
1487 if ((pEntry->RateLen == 4)
1488 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1490 #endif
1492 // USe B Table when Only b-only Station in my IBSS .
1493 *ppTable = RateSwitchTable11B;
1494 *pTableSize = RateSwitchTable11B[0];
1495 *pInitTxRateIdx = RateSwitchTable11B[1];
1498 else if (pAd->LatchRfRegs.Channel <= 14)
1500 *ppTable = RateSwitchTable11BG;
1501 *pTableSize = RateSwitchTable11BG[0];
1502 *pInitTxRateIdx = RateSwitchTable11BG[1];
1505 else
1507 *ppTable = RateSwitchTable11G;
1508 *pTableSize = RateSwitchTable11G[0];
1509 *pInitTxRateIdx = RateSwitchTable11G[1];
1512 break;
1515 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1516 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1517 {// 11BGN 1S AP
1518 *ppTable = RateSwitchTable11BGN1S;
1519 *pTableSize = RateSwitchTable11BGN1S[0];
1520 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1522 break;
1525 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1526 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1527 {// 11BGN 2S AP
1528 if (pAd->LatchRfRegs.Channel <= 14)
1530 *ppTable = RateSwitchTable11BGN2S;
1531 *pTableSize = RateSwitchTable11BGN2S[0];
1532 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1535 else
1537 *ppTable = RateSwitchTable11BGN2SForABand;
1538 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1539 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1542 break;
1545 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1546 {// 11N 1S AP
1547 *ppTable = RateSwitchTable11N1S;
1548 *pTableSize = RateSwitchTable11N1S[0];
1549 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1551 break;
1554 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1555 {// 11N 2S AP
1556 if (pAd->LatchRfRegs.Channel <= 14)
1558 *ppTable = RateSwitchTable11N2S;
1559 *pTableSize = RateSwitchTable11N2S[0];
1560 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1562 else
1564 *ppTable = RateSwitchTable11N2SForABand;
1565 *pTableSize = RateSwitchTable11N2SForABand[0];
1566 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1569 break;
1572 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1573 if ((pEntry->RateLen == 4)
1574 #ifndef RT30xx
1575 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1576 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1577 #endif
1579 {// B only AP
1580 *ppTable = RateSwitchTable11B;
1581 *pTableSize = RateSwitchTable11B[0];
1582 *pInitTxRateIdx = RateSwitchTable11B[1];
1584 break;
1587 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1588 if ((pEntry->RateLen > 8)
1589 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1591 {// B/G mixed AP
1592 *ppTable = RateSwitchTable11BG;
1593 *pTableSize = RateSwitchTable11BG[0];
1594 *pInitTxRateIdx = RateSwitchTable11BG[1];
1596 break;
1599 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1600 if ((pEntry->RateLen == 8)
1601 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1603 {// G only AP
1604 *ppTable = RateSwitchTable11G;
1605 *pTableSize = RateSwitchTable11G[0];
1606 *pInitTxRateIdx = RateSwitchTable11G[1];
1608 break;
1612 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1613 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1614 { // Legacy mode
1615 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1617 *ppTable = RateSwitchTable11B;
1618 *pTableSize = RateSwitchTable11B[0];
1619 *pInitTxRateIdx = RateSwitchTable11B[1];
1621 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1623 *ppTable = RateSwitchTable11G;
1624 *pTableSize = RateSwitchTable11G[0];
1625 *pInitTxRateIdx = RateSwitchTable11G[1];
1628 else
1630 *ppTable = RateSwitchTable11BG;
1631 *pTableSize = RateSwitchTable11BG[0];
1632 *pInitTxRateIdx = RateSwitchTable11BG[1];
1634 break;
1637 if (pAd->LatchRfRegs.Channel <= 14)
1639 if (pAd->CommonCfg.TxStream == 1)
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"));
1646 else
1648 *ppTable = RateSwitchTable11N2S;
1649 *pTableSize = RateSwitchTable11N2S[0];
1650 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1651 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1654 else
1656 if (pAd->CommonCfg.TxStream == 1)
1658 *ppTable = RateSwitchTable11N1S;
1659 *pTableSize = RateSwitchTable11N1S[0];
1660 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1661 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1663 else
1665 *ppTable = RateSwitchTable11N2SForABand;
1666 *pTableSize = RateSwitchTable11N2SForABand[0];
1667 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1668 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1672 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1673 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1675 } while(FALSE);
1679 ==========================================================================
1680 Description:
1681 This routine checks if there're other APs out there capable for
1682 roaming. Caller should call this routine only when Link up in INFRA mode
1683 and channel quality is below CQI_GOOD_THRESHOLD.
1685 IRQL = DISPATCH_LEVEL
1687 Output:
1688 ==========================================================================
1690 VOID MlmeCheckForRoaming(
1691 IN PRTMP_ADAPTER pAd,
1692 IN ULONG Now32)
1694 USHORT i;
1695 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1696 BSS_ENTRY *pBss;
1698 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1699 // put all roaming candidates into RoamTab, and sort in RSSI order
1700 BssTableInit(pRoamTab);
1701 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1703 pBss = &pAd->ScanTab.BssEntry[i];
1705 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1706 continue; // AP disappear
1707 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1708 continue; // RSSI too weak. forget it.
1709 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1710 continue; // skip current AP
1711 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1712 continue; // only AP with stronger RSSI is eligible for roaming
1714 // AP passing all above rules is put into roaming candidate table
1715 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1716 pRoamTab->BssNr += 1;
1719 if (pRoamTab->BssNr > 0)
1721 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1722 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1724 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1725 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1726 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1727 RT28XX_MLME_HANDLER(pAd);
1730 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1734 ==========================================================================
1735 Description:
1736 This routine checks if there're other APs out there capable for
1737 roaming. Caller should call this routine only when link up in INFRA mode
1738 and channel quality is below CQI_GOOD_THRESHOLD.
1740 IRQL = DISPATCH_LEVEL
1742 Output:
1743 ==========================================================================
1745 VOID MlmeCheckForFastRoaming(
1746 IN PRTMP_ADAPTER pAd,
1747 IN ULONG Now)
1749 USHORT i;
1750 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1751 BSS_ENTRY *pBss;
1753 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1754 // put all roaming candidates into RoamTab, and sort in RSSI order
1755 BssTableInit(pRoamTab);
1756 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1758 pBss = &pAd->ScanTab.BssEntry[i];
1760 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1761 continue; // RSSI too weak. forget it.
1762 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1763 continue; // skip current AP
1764 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1765 continue; // skip different SSID
1766 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1767 continue; // skip AP without better RSSI
1769 DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi));
1770 // AP passing all above rules is put into roaming candidate table
1771 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1772 pRoamTab->BssNr += 1;
1775 if (pRoamTab->BssNr > 0)
1777 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1778 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1780 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1781 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1782 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1783 RT28XX_MLME_HANDLER(pAd);
1786 // Maybe site survey required
1787 else
1789 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1791 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1792 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1793 pAd->StaCfg.ScanCnt = 2;
1794 pAd->StaCfg.LastScanTime = Now;
1795 MlmeAutoScan(pAd);
1799 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1803 ==========================================================================
1804 Description:
1805 This routine calculates TxPER, RxPER of the past N-sec period. And
1806 according to the calculation result, ChannelQuality is calculated here
1807 to decide if current AP is still doing the job.
1809 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1810 Output:
1811 StaCfg.ChannelQuality - 0..100
1813 IRQL = DISPATCH_LEVEL
1815 NOTE: This routine decide channle quality based on RX CRC error ratio.
1816 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1817 is performed right before this routine, so that this routine can decide
1818 channel quality based on the most up-to-date information
1819 ==========================================================================
1821 VOID MlmeCalculateChannelQuality(
1822 IN PRTMP_ADAPTER pAd,
1823 IN ULONG Now32)
1825 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1826 ULONG RxCnt, RxPER;
1827 UCHAR NorRssi;
1828 CHAR MaxRssi;
1829 ULONG BeaconLostTime = BEACON_LOST_TIME;
1831 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1834 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1836 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1837 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1838 if (TxCnt < 5)
1840 TxPER = 0;
1841 TxPRR = 0;
1843 else
1845 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1846 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1850 // calculate RX PER - don't take RxPER into consideration if too few sample
1852 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1853 if (RxCnt < 5)
1854 RxPER = 0;
1855 else
1856 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1859 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1861 if (INFRA_ON(pAd) &&
1862 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1863 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1865 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1866 pAd->Mlme.ChannelQuality = 0;
1868 else
1870 // Normalize Rssi
1871 if (MaxRssi > -40)
1872 NorRssi = 100;
1873 else if (MaxRssi < -90)
1874 NorRssi = 0;
1875 else
1876 NorRssi = (MaxRssi + 90) * 2;
1878 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1879 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1880 TX_WEIGHTING * (100 - TxPRR) +
1881 RX_WEIGHTING* (100 - RxPER)) / 100;
1882 if (pAd->Mlme.ChannelQuality >= 100)
1883 pAd->Mlme.ChannelQuality = 100;
1888 VOID MlmeSetTxRate(
1889 IN PRTMP_ADAPTER pAd,
1890 IN PMAC_TABLE_ENTRY pEntry,
1891 IN PRTMP_TX_RATE_SWITCH pTxRate)
1893 UCHAR MaxMode = MODE_OFDM;
1895 MaxMode = MODE_HTGREENFIELD;
1897 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1898 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1899 else
1900 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1902 if (pTxRate->CurrMCS < MCS_AUTO)
1903 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1905 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1906 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1908 if (ADHOC_ON(pAd))
1910 // If peer adhoc is b-only mode, we can't send 11g rate.
1911 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1912 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1915 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1917 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1918 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1919 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1921 // Patch speed error in status page
1922 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1924 else
1926 if (pTxRate->Mode <= MaxMode)
1927 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1929 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1930 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1931 else
1932 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1934 // Reexam each bandwidth's SGI support.
1935 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1937 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1938 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1939 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1940 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1943 // Turn RTS/CTS rate to 6Mbps.
1944 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1946 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1947 if (pAd->MacTab.fAnyBASession)
1949 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1951 else
1953 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1956 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1958 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1959 if (pAd->MacTab.fAnyBASession)
1961 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1963 else
1965 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1968 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1970 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1973 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1975 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1978 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1979 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1980 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1981 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1983 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1984 pAd->WIFItestbed.bGreenField)
1985 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1988 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1992 ==========================================================================
1993 Description:
1994 This routine calculates the acumulated TxPER of eaxh TxRate. And
1995 according to the calculation result, change CommonCfg.TxRate which
1996 is the stable TX Rate we expect the Radio situation could sustained.
1998 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1999 Output:
2000 CommonCfg.TxRate -
2002 IRQL = DISPATCH_LEVEL
2004 NOTE:
2005 call this routine every second
2006 ==========================================================================
2008 VOID MlmeDynamicTxRateSwitching(
2009 IN PRTMP_ADAPTER pAd)
2011 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2012 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2013 ULONG TxErrorRatio = 0;
2014 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2015 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2016 PUCHAR pTable;
2017 UCHAR TableSize = 0;
2018 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2019 CHAR Rssi, RssiOffset = 0;
2020 TX_STA_CNT1_STRUC StaTx1;
2021 TX_STA_CNT0_STRUC TxStaCnt0;
2022 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2023 MAC_TABLE_ENTRY *pEntry;
2026 // walk through MAC table, see if need to change AP's TX rate toward each entry
2028 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2030 pEntry = &pAd->MacTab.Content[i];
2032 // check if this entry need to switch rate automatically
2033 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2034 continue;
2036 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2038 #ifdef RT2860
2039 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2040 #endif
2041 #ifdef RT2870
2042 Rssi = RTMPMaxRssi(pAd,
2043 pAd->StaCfg.RssiSample.AvgRssi0,
2044 pAd->StaCfg.RssiSample.AvgRssi1,
2045 pAd->StaCfg.RssiSample.AvgRssi2);
2046 #endif
2048 // Update statistic counter
2049 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2050 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2051 pAd->bUpdateBcnCntDone = TRUE;
2052 TxRetransmit = StaTx1.field.TxRetransmit;
2053 TxSuccess = StaTx1.field.TxSuccess;
2054 TxFailCount = TxStaCnt0.field.TxFailCount;
2055 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2057 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2058 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2059 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2060 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2061 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2062 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2064 // if no traffic in the past 1-sec period, don't change TX rate,
2065 // but clear all bad history. because the bad history may affect the next
2066 // Chariot throughput test
2067 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2068 pAd->RalinkCounters.OneSecTxRetryOkCount +
2069 pAd->RalinkCounters.OneSecTxFailCount;
2071 if (TxTotalCnt)
2072 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2074 else
2076 #ifdef RT2860
2077 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2078 #endif
2079 #ifdef RT2870
2080 if (INFRA_ON(pAd) && (i == 1))
2081 Rssi = RTMPMaxRssi(pAd,
2082 pAd->StaCfg.RssiSample.AvgRssi0,
2083 pAd->StaCfg.RssiSample.AvgRssi1,
2084 pAd->StaCfg.RssiSample.AvgRssi2);
2085 else
2086 Rssi = RTMPMaxRssi(pAd,
2087 pEntry->RssiSample.AvgRssi0,
2088 pEntry->RssiSample.AvgRssi1,
2089 pEntry->RssiSample.AvgRssi2);
2090 #endif
2092 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2093 pEntry->OneSecTxRetryOkCount +
2094 pEntry->OneSecTxFailCount;
2096 if (TxTotalCnt)
2097 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2100 CurrRateIdx = pEntry->CurrTxRateIndex;
2102 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2104 if (CurrRateIdx >= TableSize)
2106 CurrRateIdx = TableSize - 1;
2109 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2110 // So need to sync here.
2111 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2112 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2113 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2117 // Need to sync Real Tx rate and our record.
2118 // Then return for next DRS.
2119 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2120 pEntry->CurrTxRateIndex = InitTxRateIdx;
2121 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2123 // reset all OneSecTx counters
2124 RESET_ONE_SEC_TX_CNT(pEntry);
2125 continue;
2128 // decide the next upgrade rate and downgrade rate, if any
2129 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2131 UpRateIdx = CurrRateIdx + 1;
2132 DownRateIdx = CurrRateIdx -1;
2134 else if (CurrRateIdx == 0)
2136 UpRateIdx = CurrRateIdx + 1;
2137 DownRateIdx = CurrRateIdx;
2139 else if (CurrRateIdx == (TableSize - 1))
2141 UpRateIdx = CurrRateIdx;
2142 DownRateIdx = CurrRateIdx - 1;
2145 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2147 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2149 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2150 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2152 else
2154 TrainUp = pCurrTxRate->TrainUp;
2155 TrainDown = pCurrTxRate->TrainDown;
2158 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2161 // Keep the last time TxRateChangeAction status.
2163 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2168 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2169 // (criteria copied from RT2500 for Netopia case)
2171 if (TxTotalCnt <= 15)
2173 CHAR idx = 0;
2174 UCHAR TxRateIdx;
2175 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2176 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2177 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2178 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2180 // check the existence and index of each needed MCS
2181 while (idx < pTable[0])
2183 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2185 if (pCurrTxRate->CurrMCS == MCS_0)
2187 MCS0 = idx;
2189 else if (pCurrTxRate->CurrMCS == MCS_1)
2191 MCS1 = idx;
2193 else if (pCurrTxRate->CurrMCS == MCS_2)
2195 MCS2 = idx;
2197 else if (pCurrTxRate->CurrMCS == MCS_3)
2199 MCS3 = idx;
2201 else if (pCurrTxRate->CurrMCS == MCS_4)
2203 MCS4 = idx;
2205 else if (pCurrTxRate->CurrMCS == MCS_5)
2207 MCS5 = idx;
2209 else if (pCurrTxRate->CurrMCS == MCS_6)
2211 MCS6 = idx;
2213 //else if (pCurrTxRate->CurrMCS == MCS_7)
2214 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2216 MCS7 = idx;
2218 else if (pCurrTxRate->CurrMCS == MCS_12)
2220 MCS12 = idx;
2222 else if (pCurrTxRate->CurrMCS == MCS_13)
2224 MCS13 = idx;
2226 else if (pCurrTxRate->CurrMCS == MCS_14)
2228 MCS14 = idx;
2230 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
2232 MCS15 = idx;
2234 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2236 MCS20 = idx;
2238 else if (pCurrTxRate->CurrMCS == MCS_21)
2240 MCS21 = idx;
2242 else if (pCurrTxRate->CurrMCS == MCS_22)
2244 MCS22 = idx;
2246 else if (pCurrTxRate->CurrMCS == MCS_23)
2248 MCS23 = idx;
2250 idx ++;
2253 if (pAd->LatchRfRegs.Channel <= 14)
2255 if (pAd->NicConfig2.field.ExternalLNAForG)
2257 RssiOffset = 2;
2259 else
2261 RssiOffset = 5;
2264 else
2266 if (pAd->NicConfig2.field.ExternalLNAForA)
2268 RssiOffset = 5;
2270 else
2272 RssiOffset = 8;
2276 /*if (MCS15)*/
2277 if ((pTable == RateSwitchTable11BGN3S) ||
2278 (pTable == RateSwitchTable11N3S) ||
2279 (pTable == RateSwitchTable))
2280 {// N mode with 3 stream // 3*3
2281 if (MCS23 && (Rssi >= -70))
2282 TxRateIdx = MCS15;
2283 else if (MCS22 && (Rssi >= -72))
2284 TxRateIdx = MCS14;
2285 else if (MCS21 && (Rssi >= -76))
2286 TxRateIdx = MCS13;
2287 else if (MCS20 && (Rssi >= -78))
2288 TxRateIdx = MCS12;
2289 else if (MCS4 && (Rssi >= -82))
2290 TxRateIdx = MCS4;
2291 else if (MCS3 && (Rssi >= -84))
2292 TxRateIdx = MCS3;
2293 else if (MCS2 && (Rssi >= -86))
2294 TxRateIdx = MCS2;
2295 else if (MCS1 && (Rssi >= -88))
2296 TxRateIdx = MCS1;
2297 else
2298 TxRateIdx = MCS0;
2300 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2301 {// N mode with 2 stream
2302 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2303 TxRateIdx = MCS15;
2304 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2305 TxRateIdx = MCS14;
2306 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2307 TxRateIdx = MCS13;
2308 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2309 TxRateIdx = MCS12;
2310 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2311 TxRateIdx = MCS4;
2312 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2313 TxRateIdx = MCS3;
2314 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2315 TxRateIdx = MCS2;
2316 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2317 TxRateIdx = MCS1;
2318 else
2319 TxRateIdx = MCS0;
2321 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2322 {// N mode with 1 stream
2323 if (MCS7 && (Rssi > (-72+RssiOffset)))
2324 TxRateIdx = MCS7;
2325 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2326 TxRateIdx = MCS6;
2327 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2328 TxRateIdx = MCS5;
2329 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2330 TxRateIdx = MCS4;
2331 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2332 TxRateIdx = MCS3;
2333 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2334 TxRateIdx = MCS2;
2335 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2336 TxRateIdx = MCS1;
2337 else
2338 TxRateIdx = MCS0;
2340 else
2341 {// Legacy mode
2342 if (MCS7 && (Rssi > -70))
2343 TxRateIdx = MCS7;
2344 else if (MCS6 && (Rssi > -74))
2345 TxRateIdx = MCS6;
2346 else if (MCS5 && (Rssi > -78))
2347 TxRateIdx = MCS5;
2348 else if (MCS4 && (Rssi > -82))
2349 TxRateIdx = MCS4;
2350 else if (MCS4 == 0) // for B-only mode
2351 TxRateIdx = MCS3;
2352 else if (MCS3 && (Rssi > -85))
2353 TxRateIdx = MCS3;
2354 else if (MCS2 && (Rssi > -87))
2355 TxRateIdx = MCS2;
2356 else if (MCS1 && (Rssi > -90))
2357 TxRateIdx = MCS1;
2358 else
2359 TxRateIdx = MCS0;
2363 pEntry->CurrTxRateIndex = TxRateIdx;
2364 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2365 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2368 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2369 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2370 pEntry->fLastSecAccordingRSSI = TRUE;
2371 // reset all OneSecTx counters
2372 RESET_ONE_SEC_TX_CNT(pEntry);
2374 continue;
2377 if (pEntry->fLastSecAccordingRSSI == TRUE)
2379 pEntry->fLastSecAccordingRSSI = FALSE;
2380 pEntry->LastSecTxRateChangeAction = 0;
2381 // reset all OneSecTx counters
2382 RESET_ONE_SEC_TX_CNT(pEntry);
2384 continue;
2389 BOOLEAN bTrainUpDown = FALSE;
2391 pEntry->CurrTxRateStableTime ++;
2393 // downgrade TX quality if PER >= Rate-Down threshold
2394 if (TxErrorRatio >= TrainDown)
2396 bTrainUpDown = TRUE;
2397 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2399 // upgrade TX quality if PER <= Rate-Up threshold
2400 else if (TxErrorRatio <= TrainUp)
2402 bTrainUpDown = TRUE;
2403 bUpgradeQuality = TRUE;
2404 if (pEntry->TxQuality[CurrRateIdx])
2405 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2407 if (pEntry->TxRateUpPenalty)
2408 pEntry->TxRateUpPenalty --;
2409 else if (pEntry->TxQuality[UpRateIdx])
2410 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2413 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2415 if (bTrainUpDown)
2417 // perform DRS - consider TxRate Down first, then rate up.
2418 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2420 pEntry->CurrTxRateIndex = DownRateIdx;
2422 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2424 pEntry->CurrTxRateIndex = UpRateIdx;
2427 } while (FALSE);
2429 // if rate-up happen, clear all bad history of all TX rates
2430 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2432 pEntry->CurrTxRateStableTime = 0;
2433 pEntry->TxRateUpPenalty = 0;
2434 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2435 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2436 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2439 // For TxRate fast train up
2441 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2443 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2445 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2447 bTxRateChanged = TRUE;
2449 // if rate-down happen, only clear DownRate's bad history
2450 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2452 pEntry->CurrTxRateStableTime = 0;
2453 pEntry->TxRateUpPenalty = 0; // no penalty
2454 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2455 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2456 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2459 // For TxRate fast train down
2461 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2463 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2465 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2467 bTxRateChanged = TRUE;
2469 else
2471 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2472 bTxRateChanged = FALSE;
2475 pEntry->LastTxOkCount = TxSuccess;
2477 // reset all OneSecTx counters
2478 RESET_ONE_SEC_TX_CNT(pEntry);
2480 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2481 if (bTxRateChanged && pNextTxRate)
2483 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2489 ========================================================================
2490 Routine Description:
2491 Station side, Auto TxRate faster train up timer call back function.
2493 Arguments:
2494 SystemSpecific1 - Not used.
2495 FunctionContext - Pointer to our Adapter context.
2496 SystemSpecific2 - Not used.
2497 SystemSpecific3 - Not used.
2499 Return Value:
2500 None
2502 ========================================================================
2504 VOID StaQuickResponeForRateUpExec(
2505 IN PVOID SystemSpecific1,
2506 IN PVOID FunctionContext,
2507 IN PVOID SystemSpecific2,
2508 IN PVOID SystemSpecific3)
2510 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2511 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2512 ULONG TxTotalCnt;
2513 ULONG TxErrorRatio = 0;
2514 #ifdef RT2860
2515 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2516 #endif
2517 #ifdef RT2870
2518 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2519 #endif
2520 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2521 PUCHAR pTable;
2522 UCHAR TableSize = 0;
2523 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2524 TX_STA_CNT1_STRUC StaTx1;
2525 TX_STA_CNT0_STRUC TxStaCnt0;
2526 CHAR Rssi, ratio;
2527 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2528 MAC_TABLE_ENTRY *pEntry;
2529 ULONG i;
2531 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2534 // walk through MAC table, see if need to change AP's TX rate toward each entry
2536 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2538 pEntry = &pAd->MacTab.Content[i];
2540 // check if this entry need to switch rate automatically
2541 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2542 continue;
2544 #ifdef RT2860
2545 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2546 if (pAd->Antenna.field.TxPath > 1)
2547 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2548 else
2549 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2550 #endif
2551 #ifdef RT2870
2552 if (INFRA_ON(pAd) && (i == 1))
2553 Rssi = RTMPMaxRssi(pAd,
2554 pAd->StaCfg.RssiSample.AvgRssi0,
2555 pAd->StaCfg.RssiSample.AvgRssi1,
2556 pAd->StaCfg.RssiSample.AvgRssi2);
2557 else
2558 Rssi = RTMPMaxRssi(pAd,
2559 pEntry->RssiSample.AvgRssi0,
2560 pEntry->RssiSample.AvgRssi1,
2561 pEntry->RssiSample.AvgRssi2);
2562 #endif
2564 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2566 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2568 // decide the next upgrade rate and downgrade rate, if any
2569 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2571 UpRateIdx = CurrRateIdx + 1;
2572 DownRateIdx = CurrRateIdx -1;
2574 else if (CurrRateIdx == 0)
2576 UpRateIdx = CurrRateIdx + 1;
2577 DownRateIdx = CurrRateIdx;
2579 else if (CurrRateIdx == (TableSize - 1))
2581 UpRateIdx = CurrRateIdx;
2582 DownRateIdx = CurrRateIdx - 1;
2585 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2587 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2589 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2590 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2592 else
2594 TrainUp = pCurrTxRate->TrainUp;
2595 TrainDown = pCurrTxRate->TrainDown;
2598 if (pAd->MacTab.Size == 1)
2600 // Update statistic counter
2601 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2602 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2604 TxRetransmit = StaTx1.field.TxRetransmit;
2605 TxSuccess = StaTx1.field.TxSuccess;
2606 TxFailCount = TxStaCnt0.field.TxFailCount;
2607 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2609 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2610 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2611 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2612 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2613 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2614 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2616 if (TxTotalCnt)
2617 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2619 else
2621 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2622 pEntry->OneSecTxRetryOkCount +
2623 pEntry->OneSecTxFailCount;
2625 if (TxTotalCnt)
2626 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2631 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2632 // (criteria copied from RT2500 for Netopia case)
2634 if (TxTotalCnt <= 12)
2636 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2637 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2639 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2641 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2642 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2644 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2646 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2649 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2650 return;
2655 ULONG OneSecTxNoRetryOKRationCount;
2657 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2658 ratio = 5;
2659 else
2660 ratio = 4;
2662 // downgrade TX quality if PER >= Rate-Down threshold
2663 if (TxErrorRatio >= TrainDown)
2665 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2668 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2670 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2672 // perform DRS - consider TxRate Down first, then rate up.
2673 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2675 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2677 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2678 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2683 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2685 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2689 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2691 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2694 }while (FALSE);
2696 // if rate-up happen, clear all bad history of all TX rates
2697 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2699 pAd->DrsCounters.TxRateUpPenalty = 0;
2700 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2701 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2702 #ifdef RT2870
2703 bTxRateChanged = TRUE;
2704 #endif
2706 // if rate-down happen, only clear DownRate's bad history
2707 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2709 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2711 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2712 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2713 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2714 #ifdef RT2870
2715 bTxRateChanged = TRUE;
2716 #endif
2718 else
2720 bTxRateChanged = FALSE;
2723 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2724 if (bTxRateChanged && pNextTxRate)
2726 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2732 ==========================================================================
2733 Description:
2734 This routine is executed periodically inside MlmePeriodicExec() after
2735 association with an AP.
2736 It checks if StaCfg.Psm is consistent with user policy (recorded in
2737 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2738 there're some conditions to consider:
2739 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2740 the time when Mibss==TRUE
2741 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2742 if outgoing traffic available in TxRing or MgmtRing.
2743 Output:
2744 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2746 IRQL = DISPATCH_LEVEL
2748 ==========================================================================
2750 VOID MlmeCheckPsmChange(
2751 IN PRTMP_ADAPTER pAd,
2752 IN ULONG Now32)
2754 ULONG PowerMode;
2756 // condition -
2757 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2758 // 2. user wants either MAX_PSP or FAST_PSP
2759 // 3. but current psm is not in PWR_SAVE
2760 // 4. CNTL state machine is not doing SCANning
2761 // 5. no TX SUCCESS event for the past 1-sec period
2762 #ifdef NDIS51_MINIPORT
2763 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2764 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2765 else
2766 #endif
2767 PowerMode = pAd->StaCfg.WindowsPowerMode;
2769 if (INFRA_ON(pAd) &&
2770 (PowerMode != Ndis802_11PowerModeCAM) &&
2771 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2772 #ifdef RT2860
2773 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2774 #else
2775 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2776 #endif
2778 #ifdef RT30xx
2779 // add by johnli, use Rx OK data count per second to calculate throughput
2780 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2781 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2782 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2783 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2784 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2785 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2786 #endif
2788 // Get this time
2789 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2790 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2791 MlmeSetPsmBit(pAd, PWR_SAVE);
2792 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2794 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2796 else
2798 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2804 // IRQL = PASSIVE_LEVEL
2805 // IRQL = DISPATCH_LEVEL
2806 VOID MlmeSetPsmBit(
2807 IN PRTMP_ADAPTER pAd,
2808 IN USHORT psm)
2810 AUTO_RSP_CFG_STRUC csr4;
2812 pAd->StaCfg.Psm = psm;
2813 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2814 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2815 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2816 #ifndef RT30xx
2817 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2818 #endif
2821 // IRQL = DISPATCH_LEVEL
2822 VOID MlmeSetTxPreamble(
2823 IN PRTMP_ADAPTER pAd,
2824 IN USHORT TxPreamble)
2826 AUTO_RSP_CFG_STRUC csr4;
2829 // Always use Long preamble before verifiation short preamble functionality works well.
2830 // Todo: remove the following line if short preamble functionality works
2832 //TxPreamble = Rt802_11PreambleLong;
2834 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2835 if (TxPreamble == Rt802_11PreambleLong)
2837 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2838 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2839 csr4.field.AutoResponderPreamble = 0;
2841 else
2843 // NOTE: 1Mbps should always use long preamble
2844 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2845 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2846 csr4.field.AutoResponderPreamble = 1;
2849 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2853 ==========================================================================
2854 Description:
2855 Update basic rate bitmap
2856 ==========================================================================
2859 VOID UpdateBasicRateBitmap(
2860 IN PRTMP_ADAPTER pAdapter)
2862 INT i, j;
2863 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2864 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2865 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2866 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2867 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2870 /* if A mode, always use fix BasicRateBitMap */
2871 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2872 if (pAdapter->CommonCfg.Channel > 14)
2873 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2874 /* End of if */
2876 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2878 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2879 return;
2880 } /* End of if */
2882 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2884 sup_p[i] &= 0x7f;
2885 ext_p[i] &= 0x7f;
2886 } /* End of for */
2888 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2890 if (bitmap & (1 << i))
2892 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2894 if (sup_p[j] == rate[i])
2895 sup_p[j] |= 0x80;
2896 /* End of if */
2897 } /* End of for */
2899 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2901 if (ext_p[j] == rate[i])
2902 ext_p[j] |= 0x80;
2903 /* End of if */
2904 } /* End of for */
2905 } /* End of if */
2906 } /* End of for */
2907 } /* End of UpdateBasicRateBitmap */
2909 // IRQL = PASSIVE_LEVEL
2910 // IRQL = DISPATCH_LEVEL
2911 // bLinkUp is to identify the inital link speed.
2912 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2913 VOID MlmeUpdateTxRates(
2914 IN PRTMP_ADAPTER pAd,
2915 IN BOOLEAN bLinkUp,
2916 IN UCHAR apidx)
2918 int i, num;
2919 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2920 UCHAR MinSupport = RATE_54;
2921 ULONG BasicRateBitmap = 0;
2922 UCHAR CurrBasicRate = RATE_1;
2923 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2924 PHTTRANSMIT_SETTING pHtPhy = NULL;
2925 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2926 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2927 BOOLEAN *auto_rate_cur_p;
2928 UCHAR HtMcs = MCS_AUTO;
2930 // find max desired rate
2931 UpdateBasicRateBitmap(pAd);
2933 num = 0;
2934 auto_rate_cur_p = NULL;
2935 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2937 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2939 case 2: Rate = RATE_1; num++; break;
2940 case 4: Rate = RATE_2; num++; break;
2941 case 11: Rate = RATE_5_5; num++; break;
2942 case 22: Rate = RATE_11; num++; break;
2943 case 12: Rate = RATE_6; num++; break;
2944 case 18: Rate = RATE_9; num++; break;
2945 case 24: Rate = RATE_12; num++; break;
2946 case 36: Rate = RATE_18; num++; break;
2947 case 48: Rate = RATE_24; num++; break;
2948 case 72: Rate = RATE_36; num++; break;
2949 case 96: Rate = RATE_48; num++; break;
2950 case 108: Rate = RATE_54; num++; break;
2951 //default: Rate = RATE_1; break;
2953 if (MaxDesire < Rate) MaxDesire = Rate;
2956 //===========================================================================
2957 //===========================================================================
2959 pHtPhy = &pAd->StaCfg.HTPhyMode;
2960 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2961 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2963 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2964 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2966 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2967 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2968 (MaxDesire > RATE_11))
2970 MaxDesire = RATE_11;
2974 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2975 pMinHtPhy->word = 0;
2976 pMaxHtPhy->word = 0;
2977 pHtPhy->word = 0;
2979 // Auto rate switching is enabled only if more than one DESIRED RATES are
2980 // specified; otherwise disabled
2981 if (num <= 1)
2983 *auto_rate_cur_p = FALSE;
2985 else
2987 *auto_rate_cur_p = TRUE;
2990 #if 1
2991 if (HtMcs != MCS_AUTO)
2993 *auto_rate_cur_p = FALSE;
2995 else
2997 *auto_rate_cur_p = TRUE;
2999 #endif
3001 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3003 pSupRate = &pAd->StaActive.SupRate[0];
3004 pExtRate = &pAd->StaActive.ExtRate[0];
3005 SupRateLen = pAd->StaActive.SupRateLen;
3006 ExtRateLen = pAd->StaActive.ExtRateLen;
3008 else
3010 pSupRate = &pAd->CommonCfg.SupRate[0];
3011 pExtRate = &pAd->CommonCfg.ExtRate[0];
3012 SupRateLen = pAd->CommonCfg.SupRateLen;
3013 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3016 // find max supported rate
3017 for (i=0; i<SupRateLen; i++)
3019 switch (pSupRate[i] & 0x7f)
3021 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3022 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3023 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3024 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3025 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3026 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3027 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3028 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3029 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3030 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3031 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3032 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3033 default: Rate = RATE_1; break;
3035 if (MaxSupport < Rate) MaxSupport = Rate;
3037 if (MinSupport > Rate) MinSupport = Rate;
3040 for (i=0; i<ExtRateLen; i++)
3042 switch (pExtRate[i] & 0x7f)
3044 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3045 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3046 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3047 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3048 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3049 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3050 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3051 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3052 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3053 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3054 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3055 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3056 default: Rate = RATE_1; break;
3058 if (MaxSupport < Rate) MaxSupport = Rate;
3060 if (MinSupport > Rate) MinSupport = Rate;
3063 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3065 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3066 // the DURATION field of outgoing uniicast DATA/MGMT frame
3067 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3069 if (BasicRateBitmap & (0x01 << i))
3070 CurrBasicRate = (UCHAR)i;
3071 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3074 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3075 // max tx rate = min {max desire rate, max supported rate}
3076 if (MaxSupport < MaxDesire)
3077 pAd->CommonCfg.MaxTxRate = MaxSupport;
3078 else
3079 pAd->CommonCfg.MaxTxRate = MaxDesire;
3081 pAd->CommonCfg.MinTxRate = MinSupport;
3082 if (*auto_rate_cur_p)
3084 short dbm = 0;
3086 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3088 if (bLinkUp == TRUE)
3089 pAd->CommonCfg.TxRate = RATE_24;
3090 else
3091 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3093 if (dbm < -75)
3094 pAd->CommonCfg.TxRate = RATE_11;
3095 else if (dbm < -70)
3096 pAd->CommonCfg.TxRate = RATE_24;
3098 // should never exceed MaxTxRate (consider 11B-only mode)
3099 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3100 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3102 pAd->CommonCfg.TxRateIndex = 0;
3104 else
3106 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3107 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3108 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3110 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3111 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3112 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3113 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3116 if (pAd->CommonCfg.TxRate <= RATE_11)
3118 pMaxHtPhy->field.MODE = MODE_CCK;
3119 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3120 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3122 else
3124 pMaxHtPhy->field.MODE = MODE_OFDM;
3125 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3126 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3127 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3128 else
3129 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3132 pHtPhy->word = (pMaxHtPhy->word);
3133 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3135 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3136 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3137 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3139 else
3141 switch (pAd->CommonCfg.PhyMode)
3143 case PHY_11BG_MIXED:
3144 case PHY_11B:
3145 case PHY_11BGN_MIXED:
3146 pAd->CommonCfg.MlmeRate = RATE_1;
3147 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3148 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3149 pAd->CommonCfg.RtsRate = RATE_11;
3150 break;
3151 case PHY_11G:
3152 case PHY_11A:
3153 case PHY_11AGN_MIXED:
3154 case PHY_11GN_MIXED:
3155 case PHY_11N_2_4G:
3156 case PHY_11AN_MIXED:
3157 case PHY_11N_5G:
3158 pAd->CommonCfg.MlmeRate = RATE_6;
3159 pAd->CommonCfg.RtsRate = RATE_6;
3160 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3161 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3162 break;
3163 case PHY_11ABG_MIXED:
3164 case PHY_11ABGN_MIXED:
3165 if (pAd->CommonCfg.Channel <= 14)
3167 pAd->CommonCfg.MlmeRate = RATE_1;
3168 pAd->CommonCfg.RtsRate = RATE_1;
3169 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3170 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3172 else
3174 pAd->CommonCfg.MlmeRate = RATE_6;
3175 pAd->CommonCfg.RtsRate = RATE_6;
3176 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3177 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3179 break;
3180 default: // error
3181 pAd->CommonCfg.MlmeRate = RATE_6;
3182 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3183 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3184 pAd->CommonCfg.RtsRate = RATE_1;
3185 break;
3188 // Keep Basic Mlme Rate.
3190 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3191 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3192 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3193 else
3194 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3195 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3198 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3199 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3200 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3201 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3202 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3203 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3204 pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word ));
3208 ==========================================================================
3209 Description:
3210 This function update HT Rate setting.
3211 Input Wcid value is valid for 2 case :
3212 1. it's used for Station in infra mode that copy AP rate to Mactable.
3213 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3215 IRQL = DISPATCH_LEVEL
3217 ==========================================================================
3219 VOID MlmeUpdateHtTxRates(
3220 IN PRTMP_ADAPTER pAd,
3221 IN UCHAR apidx)
3223 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3224 CHAR i; // 3*3
3225 RT_HT_CAPABILITY *pRtHtCap = NULL;
3226 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3227 ULONG BasicMCS;
3228 UCHAR j, bitmask;
3229 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3230 PHTTRANSMIT_SETTING pHtPhy = NULL;
3231 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3232 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3233 BOOLEAN *auto_rate_cur_p;
3235 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3237 auto_rate_cur_p = NULL;
3240 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3241 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3242 pHtPhy = &pAd->StaCfg.HTPhyMode;
3243 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3244 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3246 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3249 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3251 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3252 return;
3254 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3255 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3256 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3257 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3258 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3259 pMaxHtPhy->field.STBC = STBC_USE;
3260 else
3261 pMaxHtPhy->field.STBC = STBC_NONE;
3263 else
3265 if (pDesireHtPhy->bHtEnable == FALSE)
3266 return;
3268 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3269 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3270 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3271 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3272 pMaxHtPhy->field.STBC = STBC_USE;
3273 else
3274 pMaxHtPhy->field.STBC = STBC_NONE;
3277 // Decide MAX ht rate.
3278 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3279 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3280 else
3281 pMaxHtPhy->field.MODE = MODE_HTMIX;
3283 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3284 pMaxHtPhy->field.BW = BW_40;
3285 else
3286 pMaxHtPhy->field.BW = BW_20;
3288 if (pMaxHtPhy->field.BW == BW_20)
3289 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3290 else
3291 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3293 for (i=23; i>=0; i--) // 3*3
3295 j = i/8;
3296 bitmask = (1<<(i-(j*8)));
3298 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3300 pMaxHtPhy->field.MCS = i;
3301 break;
3304 if (i==0)
3305 break;
3308 // Copy MIN ht rate. rt2860???
3309 pMinHtPhy->field.BW = BW_20;
3310 pMinHtPhy->field.MCS = 0;
3311 pMinHtPhy->field.STBC = 0;
3312 pMinHtPhy->field.ShortGI = 0;
3313 //If STA assigns fixed rate. update to fixed here.
3314 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3316 if (pDesireHtPhy->MCSSet[4] != 0)
3318 pMaxHtPhy->field.MCS = 32;
3319 pMinHtPhy->field.MCS = 32;
3320 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3323 for (i=23; (CHAR)i >= 0; i--) // 3*3
3325 j = i/8;
3326 bitmask = (1<<(i-(j*8)));
3327 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3329 pMaxHtPhy->field.MCS = i;
3330 pMinHtPhy->field.MCS = i;
3331 break;
3333 if (i==0)
3334 break;
3338 // Decide ht rate
3339 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3340 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3341 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3342 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3343 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3345 // use default now. rt2860
3346 if (pDesireHtPhy->MCSSet[0] != 0xff)
3347 *auto_rate_cur_p = FALSE;
3348 else
3349 *auto_rate_cur_p = TRUE;
3351 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3352 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3353 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3354 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3357 // IRQL = DISPATCH_LEVEL
3358 VOID MlmeRadioOff(
3359 IN PRTMP_ADAPTER pAd)
3361 RT28XX_MLME_RADIO_OFF(pAd);
3364 // IRQL = DISPATCH_LEVEL
3365 VOID MlmeRadioOn(
3366 IN PRTMP_ADAPTER pAd)
3368 RT28XX_MLME_RADIO_ON(pAd);
3371 // ===========================================================================================
3372 // bss_table.c
3373 // ===========================================================================================
3376 /*! \brief initialize BSS table
3377 * \param p_tab pointer to the table
3378 * \return none
3379 * \pre
3380 * \post
3382 IRQL = PASSIVE_LEVEL
3383 IRQL = DISPATCH_LEVEL
3386 VOID BssTableInit(
3387 IN BSS_TABLE *Tab)
3389 int i;
3391 Tab->BssNr = 0;
3392 Tab->BssOverlapNr = 0;
3393 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3395 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3396 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3400 VOID BATableInit(
3401 IN PRTMP_ADAPTER pAd,
3402 IN BA_TABLE *Tab)
3404 int i;
3406 Tab->numAsOriginator = 0;
3407 Tab->numAsRecipient = 0;
3408 NdisAllocateSpinLock(&pAd->BATabLock);
3409 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3411 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3412 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3414 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3416 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3420 /*! \brief search the BSS table by SSID
3421 * \param p_tab pointer to the bss table
3422 * \param ssid SSID string
3423 * \return index of the table, BSS_NOT_FOUND if not in the table
3424 * \pre
3425 * \post
3426 * \note search by sequential search
3428 IRQL = DISPATCH_LEVEL
3431 ULONG BssTableSearch(
3432 IN BSS_TABLE *Tab,
3433 IN PUCHAR pBssid,
3434 IN UCHAR Channel)
3436 UCHAR i;
3438 for (i = 0; i < Tab->BssNr; i++)
3441 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3442 // We should distinguish this case.
3444 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3445 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3446 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3448 return i;
3451 return (ULONG)BSS_NOT_FOUND;
3454 ULONG BssSsidTableSearch(
3455 IN BSS_TABLE *Tab,
3456 IN PUCHAR pBssid,
3457 IN PUCHAR pSsid,
3458 IN UCHAR SsidLen,
3459 IN UCHAR Channel)
3461 UCHAR i;
3463 for (i = 0; i < Tab->BssNr; i++)
3466 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3467 // We should distinguish this case.
3469 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3470 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3471 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3472 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3474 return i;
3477 return (ULONG)BSS_NOT_FOUND;
3480 ULONG BssTableSearchWithSSID(
3481 IN BSS_TABLE *Tab,
3482 IN PUCHAR Bssid,
3483 IN PUCHAR pSsid,
3484 IN UCHAR SsidLen,
3485 IN UCHAR Channel)
3487 UCHAR i;
3489 for (i = 0; i < Tab->BssNr; i++)
3491 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3492 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3493 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3494 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3495 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3496 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3498 return i;
3501 return (ULONG)BSS_NOT_FOUND;
3504 // IRQL = DISPATCH_LEVEL
3505 VOID BssTableDeleteEntry(
3506 IN OUT BSS_TABLE *Tab,
3507 IN PUCHAR pBssid,
3508 IN UCHAR Channel)
3510 UCHAR i, j;
3512 for (i = 0; i < Tab->BssNr; i++)
3514 if ((Tab->BssEntry[i].Channel == Channel) &&
3515 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3517 for (j = i; j < Tab->BssNr - 1; j++)
3519 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3521 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3522 Tab->BssNr -= 1;
3523 return;
3529 ========================================================================
3530 Routine Description:
3531 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3533 Arguments:
3534 // IRQL = DISPATCH_LEVEL
3535 ========================================================================
3537 VOID BATableDeleteORIEntry(
3538 IN OUT PRTMP_ADAPTER pAd,
3539 IN BA_ORI_ENTRY *pBAORIEntry)
3542 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3544 NdisAcquireSpinLock(&pAd->BATabLock);
3545 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3547 pAd->BATable.numAsOriginator -= 1;
3548 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3549 // Erase Bitmap flag.
3551 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3552 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3553 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3554 pBAORIEntry->Token = 1;
3555 // Not clear Sequence here.
3556 NdisReleaseSpinLock(&pAd->BATabLock);
3560 /*! \brief
3561 * \param
3562 * \return
3563 * \pre
3564 * \post
3566 IRQL = DISPATCH_LEVEL
3569 VOID BssEntrySet(
3570 IN PRTMP_ADAPTER pAd,
3571 OUT BSS_ENTRY *pBss,
3572 IN PUCHAR pBssid,
3573 IN CHAR Ssid[],
3574 IN UCHAR SsidLen,
3575 IN UCHAR BssType,
3576 IN USHORT BeaconPeriod,
3577 IN PCF_PARM pCfParm,
3578 IN USHORT AtimWin,
3579 IN USHORT CapabilityInfo,
3580 IN UCHAR SupRate[],
3581 IN UCHAR SupRateLen,
3582 IN UCHAR ExtRate[],
3583 IN UCHAR ExtRateLen,
3584 IN HT_CAPABILITY_IE *pHtCapability,
3585 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3586 IN UCHAR HtCapabilityLen,
3587 IN UCHAR AddHtInfoLen,
3588 IN UCHAR NewExtChanOffset,
3589 IN UCHAR Channel,
3590 IN CHAR Rssi,
3591 IN LARGE_INTEGER TimeStamp,
3592 IN UCHAR CkipFlag,
3593 IN PEDCA_PARM pEdcaParm,
3594 IN PQOS_CAPABILITY_PARM pQosCapability,
3595 IN PQBSS_LOAD_PARM pQbssLoad,
3596 IN USHORT LengthVIE,
3597 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3599 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3600 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3601 pBss->Hidden = 1;
3602 if (SsidLen > 0)
3604 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3605 // Or send beacon /probe response with SSID len matching real SSID length,
3606 // but SSID is all zero. such as "00-00-00-00" with length 4.
3607 // We have to prevent this case overwrite correct table
3608 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3610 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3611 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3612 pBss->SsidLen = SsidLen;
3613 pBss->Hidden = 0;
3616 else
3617 pBss->SsidLen = 0;
3618 pBss->BssType = BssType;
3619 pBss->BeaconPeriod = BeaconPeriod;
3620 if (BssType == BSS_INFRA)
3622 if (pCfParm->bValid)
3624 pBss->CfpCount = pCfParm->CfpCount;
3625 pBss->CfpPeriod = pCfParm->CfpPeriod;
3626 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3627 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3630 else
3632 pBss->AtimWin = AtimWin;
3635 pBss->CapabilityInfo = CapabilityInfo;
3636 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3637 // Combine with AuthMode, they will decide the connection methods.
3638 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3639 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3640 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3641 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3642 else
3643 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3644 pBss->SupRateLen = SupRateLen;
3645 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3646 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3647 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3648 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3649 pBss->NewExtChanOffset = NewExtChanOffset;
3650 pBss->ExtRateLen = ExtRateLen;
3651 pBss->Channel = Channel;
3652 pBss->CentralChannel = Channel;
3653 pBss->Rssi = Rssi;
3654 // Update CkipFlag. if not exists, the value is 0x0
3655 pBss->CkipFlag = CkipFlag;
3657 // New for microsoft Fixed IEs
3658 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3659 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3660 pBss->FixIEs.Capabilities = CapabilityInfo;
3662 // New for microsoft Variable IEs
3663 if (LengthVIE != 0)
3665 pBss->VarIELen = LengthVIE;
3666 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3668 else
3670 pBss->VarIELen = 0;
3673 pBss->AddHtInfoLen = 0;
3674 pBss->HtCapabilityLen = 0;
3676 if (HtCapabilityLen> 0)
3678 pBss->HtCapabilityLen = HtCapabilityLen;
3679 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3680 if (AddHtInfoLen > 0)
3682 pBss->AddHtInfoLen = AddHtInfoLen;
3683 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3685 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3687 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3689 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3691 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3696 BssCipherParse(pBss);
3698 // new for QOS
3699 if (pEdcaParm)
3700 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3701 else
3702 pBss->EdcaParm.bValid = FALSE;
3703 if (pQosCapability)
3704 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3705 else
3706 pBss->QosCapability.bValid = FALSE;
3707 if (pQbssLoad)
3708 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3709 else
3710 pBss->QbssLoad.bValid = FALSE;
3713 PEID_STRUCT pEid;
3714 USHORT Length = 0;
3717 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3718 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3720 pEid = (PEID_STRUCT) pVIE;
3722 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3724 switch(pEid->Eid)
3726 case IE_WPA:
3727 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3729 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3731 pBss->WpaIE.IELen = 0;
3732 break;
3734 pBss->WpaIE.IELen = pEid->Len + 2;
3735 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3737 break;
3738 case IE_RSN:
3739 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3741 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3743 pBss->RsnIE.IELen = 0;
3744 break;
3746 pBss->RsnIE.IELen = pEid->Len + 2;
3747 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3749 break;
3751 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3752 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3758 * \brief insert an entry into the bss table
3759 * \param p_tab The BSS table
3760 * \param Bssid BSSID
3761 * \param ssid SSID
3762 * \param ssid_len Length of SSID
3763 * \param bss_type
3764 * \param beacon_period
3765 * \param timestamp
3766 * \param p_cf
3767 * \param atim_win
3768 * \param cap
3769 * \param rates
3770 * \param rates_len
3771 * \param channel_idx
3772 * \return none
3773 * \pre
3774 * \post
3775 * \note If SSID is identical, the old entry will be replaced by the new one
3777 IRQL = DISPATCH_LEVEL
3780 ULONG BssTableSetEntry(
3781 IN PRTMP_ADAPTER pAd,
3782 OUT BSS_TABLE *Tab,
3783 IN PUCHAR pBssid,
3784 IN CHAR Ssid[],
3785 IN UCHAR SsidLen,
3786 IN UCHAR BssType,
3787 IN USHORT BeaconPeriod,
3788 IN CF_PARM *CfParm,
3789 IN USHORT AtimWin,
3790 IN USHORT CapabilityInfo,
3791 IN UCHAR SupRate[],
3792 IN UCHAR SupRateLen,
3793 IN UCHAR ExtRate[],
3794 IN UCHAR ExtRateLen,
3795 IN HT_CAPABILITY_IE *pHtCapability,
3796 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3797 IN UCHAR HtCapabilityLen,
3798 IN UCHAR AddHtInfoLen,
3799 IN UCHAR NewExtChanOffset,
3800 IN UCHAR ChannelNo,
3801 IN CHAR Rssi,
3802 IN LARGE_INTEGER TimeStamp,
3803 IN UCHAR CkipFlag,
3804 IN PEDCA_PARM pEdcaParm,
3805 IN PQOS_CAPABILITY_PARM pQosCapability,
3806 IN PQBSS_LOAD_PARM pQbssLoad,
3807 IN USHORT LengthVIE,
3808 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3810 ULONG Idx;
3812 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3813 if (Idx == BSS_NOT_FOUND)
3815 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3818 // It may happen when BSS Table was full.
3819 // The desired AP will not be added into BSS Table
3820 // In this case, if we found the desired AP then overwrite BSS Table.
3822 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3824 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3825 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3827 Idx = Tab->BssOverlapNr;
3828 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3829 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3830 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3831 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3833 return Idx;
3835 else
3837 return BSS_NOT_FOUND;
3840 Idx = Tab->BssNr;
3841 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3842 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3843 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3844 Tab->BssNr++;
3846 else
3848 #ifdef RT30xx
3849 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3850 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3851 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3853 #endif
3854 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3855 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3856 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3857 #ifdef RT30xx
3859 #endif
3862 return Idx;
3865 // IRQL = DISPATCH_LEVEL
3866 VOID BssTableSsidSort(
3867 IN PRTMP_ADAPTER pAd,
3868 OUT BSS_TABLE *OutTab,
3869 IN CHAR Ssid[],
3870 IN UCHAR SsidLen)
3872 INT i;
3873 BssTableInit(OutTab);
3875 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3877 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3878 BOOLEAN bIsHiddenApIncluded = FALSE;
3880 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3881 (pAd->MlmeAux.Channel > 14) &&
3882 RadarChannelCheck(pAd, pInBss->Channel))
3885 if (pInBss->Hidden)
3886 bIsHiddenApIncluded = TRUE;
3889 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3890 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3892 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3894 // 2.4G/5G N only mode
3895 if ((pInBss->HtCapabilityLen == 0) &&
3896 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3898 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3899 continue;
3902 // New for WPA2
3903 // Check the Authmode first
3904 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3906 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3907 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3908 // None matched
3909 continue;
3911 // Check cipher suite, AP must have more secured cipher than station setting
3912 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3914 // If it's not mixed mode, we should only let BSS pass with the same encryption
3915 if (pInBss->WPA.bMixMode == FALSE)
3916 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3917 continue;
3919 // check group cipher
3920 if (
3921 #ifndef RT30xx
3922 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3923 pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3924 #endif
3925 pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3926 continue;
3928 // check pairwise cipher, skip if none matched
3929 // If profile set to AES, let it pass without question.
3930 // If profile set to TKIP, we must find one mateched
3931 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3932 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3933 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3934 continue;
3936 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3938 // If it's not mixed mode, we should only let BSS pass with the same encryption
3939 if (pInBss->WPA2.bMixMode == FALSE)
3940 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3941 continue;
3943 // check group cipher
3944 if (
3945 #ifndef RT30xx
3946 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3947 pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3948 #endif
3949 pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3950 continue;
3952 // check pairwise cipher, skip if none matched
3953 // If profile set to AES, let it pass without question.
3954 // If profile set to TKIP, we must find one mateched
3955 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3956 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3957 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3958 continue;
3961 // Bss Type matched, SSID matched.
3962 // We will check wepstatus for qualification Bss
3963 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3965 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3967 // For the SESv2 case, we will not qualify WepStatus.
3969 if (!pInBss->bSES)
3970 continue;
3973 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3974 // It definitely will fail. So, skip it.
3975 // CCX also require not even try to connect it!!
3976 if (SsidLen == 0)
3977 continue;
3979 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3980 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3981 if ((pInBss->CentralChannel != pInBss->Channel) &&
3982 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3984 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3986 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3987 SetCommonHT(pAd);
3988 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3990 else
3992 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3994 SetCommonHT(pAd);
3999 // copy matching BSS from InTab to OutTab
4000 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4002 OutTab->BssNr++;
4004 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4006 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4008 // 2.4G/5G N only mode
4009 if ((pInBss->HtCapabilityLen == 0) &&
4010 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4012 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4013 continue;
4016 // New for WPA2
4017 // Check the Authmode first
4018 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4020 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4021 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4022 // None matched
4023 continue;
4025 // Check cipher suite, AP must have more secured cipher than station setting
4026 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4028 // If it's not mixed mode, we should only let BSS pass with the same encryption
4029 if (pInBss->WPA.bMixMode == FALSE)
4030 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4031 continue;
4033 // check group cipher
4034 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4035 continue;
4037 // check pairwise cipher, skip if none matched
4038 // If profile set to AES, let it pass without question.
4039 // If profile set to TKIP, we must find one mateched
4040 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4041 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4042 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4043 continue;
4045 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4047 // If it's not mixed mode, we should only let BSS pass with the same encryption
4048 if (pInBss->WPA2.bMixMode == FALSE)
4049 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4050 continue;
4052 // check group cipher
4053 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4054 continue;
4056 // check pairwise cipher, skip if none matched
4057 // If profile set to AES, let it pass without question.
4058 // If profile set to TKIP, we must find one mateched
4059 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4060 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4061 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4062 continue;
4065 // Bss Type matched, SSID matched.
4066 // We will check wepstatus for qualification Bss
4067 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4068 continue;
4070 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4071 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4072 if ((pInBss->CentralChannel != pInBss->Channel) &&
4073 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4075 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4077 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4078 SetCommonHT(pAd);
4079 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4083 // copy matching BSS from InTab to OutTab
4084 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4086 OutTab->BssNr++;
4089 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4090 break;
4093 BssTableSortByRssi(OutTab);
4097 // IRQL = DISPATCH_LEVEL
4098 VOID BssTableSortByRssi(
4099 IN OUT BSS_TABLE *OutTab)
4101 INT i, j;
4102 BSS_ENTRY TmpBss;
4104 for (i = 0; i < OutTab->BssNr - 1; i++)
4106 for (j = i+1; j < OutTab->BssNr; j++)
4108 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4110 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4111 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4112 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4118 VOID BssCipherParse(
4119 IN OUT PBSS_ENTRY pBss)
4121 PEID_STRUCT pEid;
4122 PUCHAR pTmp;
4123 PRSN_IE_HEADER_STRUCT pRsnHeader;
4124 PCIPHER_SUITE_STRUCT pCipher;
4125 PAKM_SUITE_STRUCT pAKM;
4126 USHORT Count;
4127 INT Length;
4128 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4131 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4133 if (pBss->Privacy)
4135 pBss->WepStatus = Ndis802_11WEPEnabled;
4137 else
4139 pBss->WepStatus = Ndis802_11WEPDisabled;
4141 // Set default to disable & open authentication before parsing variable IE
4142 pBss->AuthMode = Ndis802_11AuthModeOpen;
4143 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4145 // Init WPA setting
4146 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4147 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4148 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4149 pBss->WPA.RsnCapability = 0;
4150 pBss->WPA.bMixMode = FALSE;
4152 // Init WPA2 setting
4153 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4154 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4155 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4156 pBss->WPA2.RsnCapability = 0;
4157 pBss->WPA2.bMixMode = FALSE;
4160 Length = (INT) pBss->VarIELen;
4162 while (Length > 0)
4164 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4165 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4166 pEid = (PEID_STRUCT) pTmp;
4167 switch (pEid->Eid)
4169 case IE_WPA:
4170 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4171 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4173 pTmp += 11;
4174 switch (*pTmp)
4176 case 1:
4177 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4178 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4179 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4180 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4181 break;
4182 case 2:
4183 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4184 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4185 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4186 break;
4187 case 4:
4188 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4189 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4190 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4191 break;
4192 default:
4193 break;
4196 // if Cisco IE_WPA, break
4197 break;
4199 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4201 pBss->bSES = TRUE;
4202 break;
4204 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4206 // if unsupported vendor specific IE
4207 break;
4209 // Skip OUI, version, and multicast suite
4210 // This part should be improved in the future when AP supported multiple cipher suite.
4211 // For now, it's OK since almost all APs have fixed cipher suite supported.
4212 // pTmp = (PUCHAR) pEid->Octet;
4213 pTmp += 11;
4215 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4216 // Value Meaning
4217 // 0 None
4218 // 1 WEP-40
4219 // 2 Tkip
4220 // 3 WRAP
4221 // 4 AES
4222 // 5 WEP-104
4223 // Parse group cipher
4224 switch (*pTmp)
4226 case 1:
4227 #ifndef RT30xx
4228 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4229 break;
4230 case 5:
4231 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4232 #endif
4233 #ifdef RT30xx
4234 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4235 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4236 #endif
4237 break;
4238 case 2:
4239 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4240 break;
4241 case 4:
4242 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4243 break;
4244 default:
4245 break;
4247 // number of unicast suite
4248 pTmp += 1;
4250 // skip all unicast cipher suites
4251 //Count = *(PUSHORT) pTmp;
4252 Count = (pTmp[1]<<8) + pTmp[0];
4253 pTmp += sizeof(USHORT);
4255 // Parsing all unicast cipher suite
4256 while (Count > 0)
4258 // Skip OUI
4259 pTmp += 3;
4260 TmpCipher = Ndis802_11WEPDisabled;
4261 switch (*pTmp)
4263 case 1:
4264 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4265 TmpCipher = Ndis802_11Encryption1Enabled;
4266 break;
4267 case 2:
4268 TmpCipher = Ndis802_11Encryption2Enabled;
4269 break;
4270 case 4:
4271 TmpCipher = Ndis802_11Encryption3Enabled;
4272 break;
4273 default:
4274 break;
4276 if (TmpCipher > pBss->WPA.PairCipher)
4278 // Move the lower cipher suite to PairCipherAux
4279 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4280 pBss->WPA.PairCipher = TmpCipher;
4282 else
4284 pBss->WPA.PairCipherAux = TmpCipher;
4286 pTmp++;
4287 Count--;
4290 // 4. get AKM suite counts
4291 //Count = *(PUSHORT) pTmp;
4292 Count = (pTmp[1]<<8) + pTmp[0];
4293 pTmp += sizeof(USHORT);
4294 pTmp += 3;
4296 switch (*pTmp)
4298 case 1:
4299 // Set AP support WPA mode
4300 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4301 pBss->AuthMode = Ndis802_11AuthModeWPA;
4302 else
4303 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4304 break;
4305 case 2:
4306 // Set AP support WPA mode
4307 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4308 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4309 else
4310 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4311 break;
4312 default:
4313 break;
4315 pTmp += 1;
4317 // Fixed for WPA-None
4318 if (pBss->BssType == BSS_ADHOC)
4320 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4321 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4322 pBss->WepStatus = pBss->WPA.GroupCipher;
4323 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4324 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4326 else
4327 pBss->WepStatus = pBss->WPA.PairCipher;
4329 // Check the Pair & Group, if different, turn on mixed mode flag
4330 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4331 pBss->WPA.bMixMode = TRUE;
4333 break;
4335 case IE_RSN:
4336 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4338 // 0. Version must be 1
4339 if (le2cpu16(pRsnHeader->Version) != 1)
4340 break;
4341 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4343 // 1. Check group cipher
4344 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4345 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4346 break;
4348 // Parse group cipher
4349 switch (pCipher->Type)
4351 case 1:
4352 #ifndef RT30xx
4353 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4354 break;
4355 case 5:
4356 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4357 #endif
4358 #ifdef RT30xx
4359 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4360 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4361 #endif
4362 break;
4363 case 2:
4364 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4365 break;
4366 case 4:
4367 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4368 break;
4369 default:
4370 break;
4372 // set to correct offset for next parsing
4373 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4375 // 2. Get pairwise cipher counts
4376 //Count = *(PUSHORT) pTmp;
4377 Count = (pTmp[1]<<8) + pTmp[0];
4378 pTmp += sizeof(USHORT);
4380 // 3. Get pairwise cipher
4381 // Parsing all unicast cipher suite
4382 while (Count > 0)
4384 // Skip OUI
4385 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4386 TmpCipher = Ndis802_11WEPDisabled;
4387 switch (pCipher->Type)
4389 case 1:
4390 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4391 TmpCipher = Ndis802_11Encryption1Enabled;
4392 break;
4393 case 2:
4394 TmpCipher = Ndis802_11Encryption2Enabled;
4395 break;
4396 case 4:
4397 TmpCipher = Ndis802_11Encryption3Enabled;
4398 break;
4399 default:
4400 break;
4402 if (TmpCipher > pBss->WPA2.PairCipher)
4404 // Move the lower cipher suite to PairCipherAux
4405 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4406 pBss->WPA2.PairCipher = TmpCipher;
4408 else
4410 pBss->WPA2.PairCipherAux = TmpCipher;
4412 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4413 Count--;
4416 // 4. get AKM suite counts
4417 //Count = *(PUSHORT) pTmp;
4418 Count = (pTmp[1]<<8) + pTmp[0];
4419 pTmp += sizeof(USHORT);
4421 // 5. Get AKM ciphers
4422 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4423 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4424 break;
4426 switch (pAKM->Type)
4428 case 1:
4429 // Set AP support WPA mode
4430 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4431 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4432 else
4433 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4434 break;
4435 case 2:
4436 // Set AP support WPA mode
4437 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4438 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4439 else
4440 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4441 break;
4442 default:
4443 break;
4445 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4447 // Fixed for WPA-None
4448 if (pBss->BssType == BSS_ADHOC)
4450 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4451 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4452 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4453 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4454 pBss->WepStatus = pBss->WPA.GroupCipher;
4455 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4456 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4458 pBss->WepStatus = pBss->WPA2.PairCipher;
4460 // 6. Get RSN capability
4461 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4462 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4463 pTmp += sizeof(USHORT);
4465 // Check the Pair & Group, if different, turn on mixed mode flag
4466 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4467 pBss->WPA2.bMixMode = TRUE;
4469 break;
4470 default:
4471 break;
4473 Length -= (pEid->Len + 2);
4477 // ===========================================================================================
4478 // mac_table.c
4479 // ===========================================================================================
4481 /*! \brief generates a random mac address value for IBSS BSSID
4482 * \param Addr the bssid location
4483 * \return none
4484 * \pre
4485 * \post
4487 VOID MacAddrRandomBssid(
4488 IN PRTMP_ADAPTER pAd,
4489 OUT PUCHAR pAddr)
4491 INT i;
4493 for (i = 0; i < MAC_ADDR_LEN; i++)
4495 pAddr[i] = RandomByte(pAd);
4498 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4501 /*! \brief init the management mac frame header
4502 * \param p_hdr mac header
4503 * \param subtype subtype of the frame
4504 * \param p_ds destination address, don't care if it is a broadcast address
4505 * \return none
4506 * \pre the station has the following information in the pAd->StaCfg
4507 * - bssid
4508 * - station address
4509 * \post
4510 * \note this function initializes the following field
4512 IRQL = PASSIVE_LEVEL
4513 IRQL = DISPATCH_LEVEL
4516 VOID MgtMacHeaderInit(
4517 IN PRTMP_ADAPTER pAd,
4518 IN OUT PHEADER_802_11 pHdr80211,
4519 IN UCHAR SubType,
4520 IN UCHAR ToDs,
4521 IN PUCHAR pDA,
4522 IN PUCHAR pBssid)
4524 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4526 pHdr80211->FC.Type = BTYPE_MGMT;
4527 pHdr80211->FC.SubType = SubType;
4528 pHdr80211->FC.ToDs = ToDs;
4529 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4531 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4533 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4536 // ===========================================================================================
4537 // mem_mgmt.c
4538 // ===========================================================================================
4540 /*!***************************************************************************
4541 * This routine build an outgoing frame, and fill all information specified
4542 * in argument list to the frame body. The actual frame size is the summation
4543 * of all arguments.
4544 * input params:
4545 * Buffer - pointer to a pre-allocated memory segment
4546 * args - a list of <int arg_size, arg> pairs.
4547 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4548 * function will FAIL!!!
4549 * return:
4550 * Size of the buffer
4551 * usage:
4552 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4554 IRQL = PASSIVE_LEVEL
4555 IRQL = DISPATCH_LEVEL
4557 ****************************************************************************/
4558 ULONG MakeOutgoingFrame(
4559 OUT CHAR *Buffer,
4560 OUT ULONG *FrameLen, ...)
4562 CHAR *p;
4563 int leng;
4564 ULONG TotLeng;
4565 va_list Args;
4567 // calculates the total length
4568 TotLeng = 0;
4569 va_start(Args, FrameLen);
4572 leng = va_arg(Args, int);
4573 if (leng == END_OF_ARGS)
4575 break;
4577 p = va_arg(Args, PVOID);
4578 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4579 TotLeng = TotLeng + leng;
4580 } while(TRUE);
4582 va_end(Args); /* clean up */
4583 *FrameLen = TotLeng;
4584 return TotLeng;
4587 // ===========================================================================================
4588 // mlme_queue.c
4589 // ===========================================================================================
4591 /*! \brief Initialize The MLME Queue, used by MLME Functions
4592 * \param *Queue The MLME Queue
4593 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4594 * \pre
4595 * \post
4596 * \note Because this is done only once (at the init stage), no need to be locked
4598 IRQL = PASSIVE_LEVEL
4601 NDIS_STATUS MlmeQueueInit(
4602 IN MLME_QUEUE *Queue)
4604 INT i;
4606 NdisAllocateSpinLock(&Queue->Lock);
4608 Queue->Num = 0;
4609 Queue->Head = 0;
4610 Queue->Tail = 0;
4612 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4614 Queue->Entry[i].Occupied = FALSE;
4615 Queue->Entry[i].MsgLen = 0;
4616 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4619 return NDIS_STATUS_SUCCESS;
4622 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4623 * \param *Queue The MLME Queue
4624 * \param Machine The State Machine Id
4625 * \param MsgType The Message Type
4626 * \param MsgLen The Message length
4627 * \param *Msg The message pointer
4628 * \return TRUE if enqueue is successful, FALSE if the queue is full
4629 * \pre
4630 * \post
4631 * \note The message has to be initialized
4633 IRQL = PASSIVE_LEVEL
4634 IRQL = DISPATCH_LEVEL
4637 BOOLEAN MlmeEnqueue(
4638 IN PRTMP_ADAPTER pAd,
4639 IN ULONG Machine,
4640 IN ULONG MsgType,
4641 IN ULONG MsgLen,
4642 IN VOID *Msg)
4644 INT Tail;
4645 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4647 // Do nothing if the driver is starting halt state.
4648 // This might happen when timer already been fired before cancel timer with mlmehalt
4649 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4650 return FALSE;
4652 // First check the size, it MUST not exceed the mlme queue size
4653 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4655 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4656 return FALSE;
4659 if (MlmeQueueFull(Queue))
4661 return FALSE;
4664 NdisAcquireSpinLock(&(Queue->Lock));
4665 Tail = Queue->Tail;
4666 Queue->Tail++;
4667 Queue->Num++;
4668 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4670 Queue->Tail = 0;
4673 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4674 Queue->Entry[Tail].Occupied = TRUE;
4675 Queue->Entry[Tail].Machine = Machine;
4676 Queue->Entry[Tail].MsgType = MsgType;
4677 Queue->Entry[Tail].MsgLen = MsgLen;
4679 if (Msg != NULL)
4681 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4684 NdisReleaseSpinLock(&(Queue->Lock));
4685 return TRUE;
4688 /*! \brief This function is used when Recv gets a MLME message
4689 * \param *Queue The MLME Queue
4690 * \param TimeStampHigh The upper 32 bit of timestamp
4691 * \param TimeStampLow The lower 32 bit of timestamp
4692 * \param Rssi The receiving RSSI strength
4693 * \param MsgLen The length of the message
4694 * \param *Msg The message pointer
4695 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4696 * \pre
4697 * \post
4699 IRQL = DISPATCH_LEVEL
4702 BOOLEAN MlmeEnqueueForRecv(
4703 IN PRTMP_ADAPTER pAd,
4704 IN ULONG Wcid,
4705 IN ULONG TimeStampHigh,
4706 IN ULONG TimeStampLow,
4707 IN UCHAR Rssi0,
4708 IN UCHAR Rssi1,
4709 IN UCHAR Rssi2,
4710 IN ULONG MsgLen,
4711 IN VOID *Msg,
4712 IN UCHAR Signal)
4714 INT Tail, Machine;
4715 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4716 INT MsgType;
4717 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4719 // Do nothing if the driver is starting halt state.
4720 // This might happen when timer already been fired before cancel timer with mlmehalt
4721 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4723 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4724 return FALSE;
4727 // First check the size, it MUST not exceed the mlme queue size
4728 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4730 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4731 return FALSE;
4734 if (MlmeQueueFull(Queue))
4736 return FALSE;
4740 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4742 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4743 return FALSE;
4747 // OK, we got all the informations, it is time to put things into queue
4748 NdisAcquireSpinLock(&(Queue->Lock));
4749 Tail = Queue->Tail;
4750 Queue->Tail++;
4751 Queue->Num++;
4752 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4754 Queue->Tail = 0;
4756 Queue->Entry[Tail].Occupied = TRUE;
4757 Queue->Entry[Tail].Machine = Machine;
4758 Queue->Entry[Tail].MsgType = MsgType;
4759 Queue->Entry[Tail].MsgLen = MsgLen;
4760 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4761 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4762 Queue->Entry[Tail].Rssi0 = Rssi0;
4763 Queue->Entry[Tail].Rssi1 = Rssi1;
4764 Queue->Entry[Tail].Rssi2 = Rssi2;
4765 Queue->Entry[Tail].Signal = Signal;
4766 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4768 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4770 if (Msg != NULL)
4772 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4775 NdisReleaseSpinLock(&(Queue->Lock));
4777 RT28XX_MLME_HANDLER(pAd);
4779 return TRUE;
4783 /*! \brief Dequeue a message from the MLME Queue
4784 * \param *Queue The MLME Queue
4785 * \param *Elem The message dequeued from MLME Queue
4786 * \return TRUE if the Elem contains something, FALSE otherwise
4787 * \pre
4788 * \post
4790 IRQL = DISPATCH_LEVEL
4793 BOOLEAN MlmeDequeue(
4794 IN MLME_QUEUE *Queue,
4795 OUT MLME_QUEUE_ELEM **Elem)
4797 NdisAcquireSpinLock(&(Queue->Lock));
4798 *Elem = &(Queue->Entry[Queue->Head]);
4799 Queue->Num--;
4800 Queue->Head++;
4801 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4803 Queue->Head = 0;
4805 NdisReleaseSpinLock(&(Queue->Lock));
4806 return TRUE;
4809 // IRQL = DISPATCH_LEVEL
4810 VOID MlmeRestartStateMachine(
4811 IN PRTMP_ADAPTER pAd)
4813 #ifdef RT2860
4814 MLME_QUEUE_ELEM *Elem = NULL;
4815 #endif
4816 BOOLEAN Cancelled;
4818 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4820 #ifdef RT2860
4821 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4822 if(pAd->Mlme.bRunning)
4824 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4825 return;
4827 else
4829 pAd->Mlme.bRunning = TRUE;
4831 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4833 // Remove all Mlme queues elements
4834 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4836 //From message type, determine which state machine I should drive
4837 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4839 // free MLME element
4840 Elem->Occupied = FALSE;
4841 Elem->MsgLen = 0;
4844 else {
4845 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4848 #endif /* RT2860 */
4851 // Cancel all timer events
4852 // Be careful to cancel new added timer
4853 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4854 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4855 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4856 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4857 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4858 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4861 // Change back to original channel in case of doing scan
4862 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4863 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4865 // Resume MSDU which is turned off durning scan
4866 RTMPResumeMsduTransmission(pAd);
4869 // Set all state machines back IDLE
4870 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4871 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4872 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4873 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4874 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4875 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4878 #ifdef RT2860
4879 // Remove running state
4880 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4881 pAd->Mlme.bRunning = FALSE;
4882 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4883 #endif
4886 /*! \brief test if the MLME Queue is empty
4887 * \param *Queue The MLME Queue
4888 * \return TRUE if the Queue is empty, FALSE otherwise
4889 * \pre
4890 * \post
4892 IRQL = DISPATCH_LEVEL
4895 BOOLEAN MlmeQueueEmpty(
4896 IN MLME_QUEUE *Queue)
4898 BOOLEAN Ans;
4900 NdisAcquireSpinLock(&(Queue->Lock));
4901 Ans = (Queue->Num == 0);
4902 NdisReleaseSpinLock(&(Queue->Lock));
4904 return Ans;
4907 /*! \brief test if the MLME Queue is full
4908 * \param *Queue The MLME Queue
4909 * \return TRUE if the Queue is empty, FALSE otherwise
4910 * \pre
4911 * \post
4913 IRQL = PASSIVE_LEVEL
4914 IRQL = DISPATCH_LEVEL
4917 BOOLEAN MlmeQueueFull(
4918 IN MLME_QUEUE *Queue)
4920 BOOLEAN Ans;
4922 NdisAcquireSpinLock(&(Queue->Lock));
4923 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4924 NdisReleaseSpinLock(&(Queue->Lock));
4926 return Ans;
4929 /*! \brief The destructor of MLME Queue
4930 * \param
4931 * \return
4932 * \pre
4933 * \post
4934 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4936 IRQL = PASSIVE_LEVEL
4939 VOID MlmeQueueDestroy(
4940 IN MLME_QUEUE *pQueue)
4942 NdisAcquireSpinLock(&(pQueue->Lock));
4943 pQueue->Num = 0;
4944 pQueue->Head = 0;
4945 pQueue->Tail = 0;
4946 NdisReleaseSpinLock(&(pQueue->Lock));
4947 NdisFreeSpinLock(&(pQueue->Lock));
4950 /*! \brief To substitute the message type if the message is coming from external
4951 * \param pFrame The frame received
4952 * \param *Machine The state machine
4953 * \param *MsgType the message type for the state machine
4954 * \return TRUE if the substitution is successful, FALSE otherwise
4955 * \pre
4956 * \post
4958 IRQL = DISPATCH_LEVEL
4961 BOOLEAN MsgTypeSubst(
4962 IN PRTMP_ADAPTER pAd,
4963 IN PFRAME_802_11 pFrame,
4964 OUT INT *Machine,
4965 OUT INT *MsgType)
4967 USHORT Seq;
4968 UCHAR EAPType;
4969 PUCHAR pData;
4971 // Pointer to start of data frames including SNAP header
4972 pData = (PUCHAR) pFrame + LENGTH_802_11;
4974 // The only data type will pass to this function is EAPOL frame
4975 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4977 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4979 // Cisco Aironet SNAP header
4980 *Machine = AIRONET_STATE_MACHINE;
4981 *MsgType = MT2_AIRONET_MSG;
4982 return (TRUE);
4985 *Machine = WPA_PSK_STATE_MACHINE;
4986 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4987 return(WpaMsgTypeSubst(EAPType, MsgType));
4991 switch (pFrame->Hdr.FC.SubType)
4993 case SUBTYPE_ASSOC_REQ:
4994 *Machine = ASSOC_STATE_MACHINE;
4995 *MsgType = MT2_PEER_ASSOC_REQ;
4996 break;
4997 case SUBTYPE_ASSOC_RSP:
4998 *Machine = ASSOC_STATE_MACHINE;
4999 *MsgType = MT2_PEER_ASSOC_RSP;
5000 break;
5001 case SUBTYPE_REASSOC_REQ:
5002 *Machine = ASSOC_STATE_MACHINE;
5003 *MsgType = MT2_PEER_REASSOC_REQ;
5004 break;
5005 case SUBTYPE_REASSOC_RSP:
5006 *Machine = ASSOC_STATE_MACHINE;
5007 *MsgType = MT2_PEER_REASSOC_RSP;
5008 break;
5009 case SUBTYPE_PROBE_REQ:
5010 *Machine = SYNC_STATE_MACHINE;
5011 *MsgType = MT2_PEER_PROBE_REQ;
5012 break;
5013 case SUBTYPE_PROBE_RSP:
5014 *Machine = SYNC_STATE_MACHINE;
5015 *MsgType = MT2_PEER_PROBE_RSP;
5016 break;
5017 case SUBTYPE_BEACON:
5018 *Machine = SYNC_STATE_MACHINE;
5019 *MsgType = MT2_PEER_BEACON;
5020 break;
5021 case SUBTYPE_ATIM:
5022 *Machine = SYNC_STATE_MACHINE;
5023 *MsgType = MT2_PEER_ATIM;
5024 break;
5025 case SUBTYPE_DISASSOC:
5026 *Machine = ASSOC_STATE_MACHINE;
5027 *MsgType = MT2_PEER_DISASSOC_REQ;
5028 break;
5029 case SUBTYPE_AUTH:
5030 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5031 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5032 if (Seq == 1 || Seq == 3)
5034 *Machine = AUTH_RSP_STATE_MACHINE;
5035 *MsgType = MT2_PEER_AUTH_ODD;
5037 else if (Seq == 2 || Seq == 4)
5039 *Machine = AUTH_STATE_MACHINE;
5040 *MsgType = MT2_PEER_AUTH_EVEN;
5042 else
5044 return FALSE;
5046 break;
5047 case SUBTYPE_DEAUTH:
5048 *Machine = AUTH_RSP_STATE_MACHINE;
5049 *MsgType = MT2_PEER_DEAUTH;
5050 break;
5051 case SUBTYPE_ACTION:
5052 *Machine = ACTION_STATE_MACHINE;
5053 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5054 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5056 *MsgType = MT2_ACT_INVALID;
5058 else
5060 *MsgType = (pFrame->Octet[0]&0x7F);
5062 break;
5063 default:
5064 return FALSE;
5065 break;
5068 return TRUE;
5071 // ===========================================================================================
5072 // state_machine.c
5073 // ===========================================================================================
5075 /*! \brief Initialize the state machine.
5076 * \param *S pointer to the state machine
5077 * \param Trans State machine transition function
5078 * \param StNr number of states
5079 * \param MsgNr number of messages
5080 * \param DefFunc default function, when there is invalid state/message combination
5081 * \param InitState initial state of the state machine
5082 * \param Base StateMachine base, internal use only
5083 * \pre p_sm should be a legal pointer
5084 * \post
5086 IRQL = PASSIVE_LEVEL
5089 VOID StateMachineInit(
5090 IN STATE_MACHINE *S,
5091 IN STATE_MACHINE_FUNC Trans[],
5092 IN ULONG StNr,
5093 IN ULONG MsgNr,
5094 IN STATE_MACHINE_FUNC DefFunc,
5095 IN ULONG InitState,
5096 IN ULONG Base)
5098 ULONG i, j;
5100 // set number of states and messages
5101 S->NrState = StNr;
5102 S->NrMsg = MsgNr;
5103 S->Base = Base;
5105 S->TransFunc = Trans;
5107 // init all state transition to default function
5108 for (i = 0; i < StNr; i++)
5110 for (j = 0; j < MsgNr; j++)
5112 S->TransFunc[i * MsgNr + j] = DefFunc;
5116 // set the starting state
5117 S->CurrState = InitState;
5120 /*! \brief This function fills in the function pointer into the cell in the state machine
5121 * \param *S pointer to the state machine
5122 * \param St state
5123 * \param Msg incoming message
5124 * \param f the function to be executed when (state, message) combination occurs at the state machine
5125 * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
5126 * \post
5128 IRQL = PASSIVE_LEVEL
5131 VOID StateMachineSetAction(
5132 IN STATE_MACHINE *S,
5133 IN ULONG St,
5134 IN ULONG Msg,
5135 IN STATE_MACHINE_FUNC Func)
5137 ULONG MsgIdx;
5139 MsgIdx = Msg - S->Base;
5141 if (St < S->NrState && MsgIdx < S->NrMsg)
5143 // boundary checking before setting the action
5144 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5148 /*! \brief This function does the state transition
5149 * \param *Adapter the NIC adapter pointer
5150 * \param *S the state machine
5151 * \param *Elem the message to be executed
5152 * \return None
5154 IRQL = DISPATCH_LEVEL
5157 VOID StateMachinePerformAction(
5158 IN PRTMP_ADAPTER pAd,
5159 IN STATE_MACHINE *S,
5160 IN MLME_QUEUE_ELEM *Elem)
5162 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5166 ==========================================================================
5167 Description:
5168 The drop function, when machine executes this, the message is simply
5169 ignored. This function does nothing, the message is freed in
5170 StateMachinePerformAction()
5171 ==========================================================================
5173 VOID Drop(
5174 IN PRTMP_ADAPTER pAd,
5175 IN MLME_QUEUE_ELEM *Elem)
5179 // ===========================================================================================
5180 // lfsr.c
5181 // ===========================================================================================
5184 ==========================================================================
5185 Description:
5187 IRQL = PASSIVE_LEVEL
5189 ==========================================================================
5191 VOID LfsrInit(
5192 IN PRTMP_ADAPTER pAd,
5193 IN ULONG Seed)
5195 if (Seed == 0)
5196 pAd->Mlme.ShiftReg = 1;
5197 else
5198 pAd->Mlme.ShiftReg = Seed;
5202 ==========================================================================
5203 Description:
5204 ==========================================================================
5206 UCHAR RandomByte(
5207 IN PRTMP_ADAPTER pAd)
5209 ULONG i;
5210 UCHAR R, Result;
5212 R = 0;
5214 if (pAd->Mlme.ShiftReg == 0)
5215 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5217 for (i = 0; i < 8; i++)
5219 if (pAd->Mlme.ShiftReg & 0x00000001)
5221 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5222 Result = 1;
5224 else
5226 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5227 Result = 0;
5229 R = (R << 1) | Result;
5232 return R;
5235 VOID AsicUpdateAutoFallBackTable(
5236 IN PRTMP_ADAPTER pAd,
5237 IN PUCHAR pRateTable)
5239 UCHAR i;
5240 HT_FBK_CFG0_STRUC HtCfg0;
5241 HT_FBK_CFG1_STRUC HtCfg1;
5242 LG_FBK_CFG0_STRUC LgCfg0;
5243 LG_FBK_CFG1_STRUC LgCfg1;
5244 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5246 // set to initial value
5247 HtCfg0.word = 0x65432100;
5248 HtCfg1.word = 0xedcba988;
5249 LgCfg0.word = 0xedcba988;
5250 LgCfg1.word = 0x00002100;
5252 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5253 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5255 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5256 switch (pCurrTxRate->Mode)
5258 case 0: //CCK
5259 break;
5260 case 1: //OFDM
5262 switch(pCurrTxRate->CurrMCS)
5264 case 0:
5265 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5266 break;
5267 case 1:
5268 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5269 break;
5270 case 2:
5271 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5272 break;
5273 case 3:
5274 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5275 break;
5276 case 4:
5277 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5278 break;
5279 case 5:
5280 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5281 break;
5282 case 6:
5283 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5284 break;
5285 case 7:
5286 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5287 break;
5290 break;
5291 case 2: //HT-MIX
5292 case 3: //HT-GF
5294 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5296 switch(pCurrTxRate->CurrMCS)
5298 case 0:
5299 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5300 break;
5301 case 1:
5302 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5303 break;
5304 case 2:
5305 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5306 break;
5307 case 3:
5308 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5309 break;
5310 case 4:
5311 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5312 break;
5313 case 5:
5314 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5315 break;
5316 case 6:
5317 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5318 break;
5319 case 7:
5320 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5321 break;
5322 case 8:
5323 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5324 break;
5325 case 9:
5326 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5327 break;
5328 case 10:
5329 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5330 break;
5331 case 11:
5332 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5333 break;
5334 case 12:
5335 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5336 break;
5337 case 13:
5338 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5339 break;
5340 case 14:
5341 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5342 break;
5343 case 15:
5344 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5345 break;
5346 default:
5347 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5351 break;
5354 pNextTxRate = pCurrTxRate;
5357 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5358 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5359 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5360 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5364 ========================================================================
5366 Routine Description:
5367 Set MAC register value according operation mode.
5368 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5369 If MM or GF mask is not set, those passing argument doesn't not take effect.
5371 Operation mode meaning:
5372 = 0 : Pure HT, no preotection.
5373 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5374 = 0x10: No Transmission in 40M is protected.
5375 = 0x11: Transmission in both 40M and 20M shall be protected
5376 if (bNonGFExist)
5377 we should choose not to use GF. But still set correct ASIC registers.
5378 ========================================================================
5380 VOID AsicUpdateProtect(
5381 IN PRTMP_ADAPTER pAd,
5382 IN USHORT OperationMode,
5383 IN UCHAR SetMask,
5384 IN BOOLEAN bDisableBGProtect,
5385 IN BOOLEAN bNonGFExist)
5387 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5388 UINT32 Protect[6];
5389 USHORT offset;
5390 UCHAR i;
5391 UINT32 MacReg = 0;
5393 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5395 return;
5398 if (pAd->BATable.numAsOriginator)
5401 // enable the RTS/CTS to avoid channel collision
5403 SetMask = ALLN_SETPROTECT;
5404 OperationMode = 8;
5407 // Config ASIC RTS threshold register
5408 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5409 MacReg &= 0xFF0000FF;
5411 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5412 if ((
5413 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5414 (pAd->CommonCfg.bAggregationCapable == TRUE))
5415 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5417 MacReg |= (0x1000 << 8);
5419 else
5421 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5424 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5426 // Initial common protection settings
5427 RTMPZeroMemory(Protect, sizeof(Protect));
5428 ProtCfg4.word = 0;
5429 ProtCfg.word = 0;
5430 ProtCfg.field.TxopAllowGF40 = 1;
5431 ProtCfg.field.TxopAllowGF20 = 1;
5432 ProtCfg.field.TxopAllowMM40 = 1;
5433 ProtCfg.field.TxopAllowMM20 = 1;
5434 ProtCfg.field.TxopAllowOfdm = 1;
5435 ProtCfg.field.TxopAllowCck = 1;
5436 ProtCfg.field.RTSThEn = 1;
5437 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5439 // update PHY mode and rate
5440 if (pAd->CommonCfg.Channel > 14)
5441 ProtCfg.field.ProtectRate = 0x4000;
5442 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5444 // Handle legacy(B/G) protection
5445 if (bDisableBGProtect)
5447 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5448 ProtCfg.field.ProtectCtrl = 0;
5449 Protect[0] = ProtCfg.word;
5450 Protect[1] = ProtCfg.word;
5452 else
5454 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5455 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5456 Protect[0] = ProtCfg.word;
5457 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5458 Protect[1] = ProtCfg.word;
5461 // Decide HT frame protection.
5462 if ((SetMask & ALLN_SETPROTECT) != 0)
5464 switch(OperationMode)
5466 case 0x0:
5467 // NO PROTECT
5468 // 1.All STAs in the BSS are 20/40 MHz HT
5469 // 2. in ai 20/40MHz BSS
5470 // 3. all STAs are 20MHz in a 20MHz BSS
5471 // Pure HT. no protection.
5473 // MM20_PROT_CFG
5474 // Reserved (31:27)
5475 // PROT_TXOP(25:20) -- 010111
5476 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5477 // PROT_CTRL(17:16) -- 00 (None)
5478 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5479 Protect[2] = 0x01744004;
5481 // MM40_PROT_CFG
5482 // Reserved (31:27)
5483 // PROT_TXOP(25:20) -- 111111
5484 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5485 // PROT_CTRL(17:16) -- 00 (None)
5486 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5487 Protect[3] = 0x03f44084;
5489 // CF20_PROT_CFG
5490 // Reserved (31:27)
5491 // PROT_TXOP(25:20) -- 010111
5492 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5493 // PROT_CTRL(17:16) -- 00 (None)
5494 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5495 Protect[4] = 0x01744004;
5497 // CF40_PROT_CFG
5498 // Reserved (31:27)
5499 // PROT_TXOP(25:20) -- 111111
5500 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5501 // PROT_CTRL(17:16) -- 00 (None)
5502 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5503 Protect[5] = 0x03f44084;
5505 if (bNonGFExist)
5507 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5508 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5509 Protect[4] = 0x01754004;
5510 Protect[5] = 0x03f54084;
5512 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5513 break;
5515 case 1:
5516 // This is "HT non-member protection mode."
5517 // If there may be non-HT STAs my BSS
5518 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5519 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5520 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5522 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5523 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5525 //Assign Protection method for 20&40 MHz packets
5526 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5527 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5528 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5529 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5530 Protect[2] = ProtCfg.word;
5531 Protect[3] = ProtCfg4.word;
5532 Protect[4] = ProtCfg.word;
5533 Protect[5] = ProtCfg4.word;
5534 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5535 break;
5537 case 2:
5538 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5539 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5540 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5542 //Assign Protection method for 40MHz packets
5543 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5544 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5545 Protect[2] = ProtCfg.word;
5546 Protect[3] = ProtCfg4.word;
5547 if (bNonGFExist)
5549 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5550 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5552 Protect[4] = ProtCfg.word;
5553 Protect[5] = ProtCfg4.word;
5555 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5556 break;
5558 case 3:
5559 // HT mixed mode. PROTECT ALL!
5560 // Assign Rate
5561 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5562 ProtCfg4.word = 0x03f44084;
5563 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5564 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5566 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5567 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5569 //Assign Protection method for 20&40 MHz packets
5570 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5571 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5572 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5573 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5574 Protect[2] = ProtCfg.word;
5575 Protect[3] = ProtCfg4.word;
5576 Protect[4] = ProtCfg.word;
5577 Protect[5] = ProtCfg4.word;
5578 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5579 break;
5581 case 8:
5582 // Special on for Atheros problem n chip.
5583 Protect[2] = 0x01754004;
5584 Protect[3] = 0x03f54084;
5585 Protect[4] = 0x01754004;
5586 Protect[5] = 0x03f54084;
5587 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5588 break;
5592 offset = CCK_PROT_CFG;
5593 for (i = 0;i < 6;i++)
5595 if ((SetMask & (1<< i)))
5597 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5602 #ifdef RT30xx
5603 // add by johnli, RF power sequence setup
5605 ==========================================================================
5606 Description:
5608 Load RF normal operation-mode setup
5610 ==========================================================================
5612 VOID RT30xxLoadRFNormalModeSetup(
5613 IN PRTMP_ADAPTER pAd)
5615 UCHAR RFValue;
5617 // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5618 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5619 RFValue = (RFValue & (~0x0C)) | 0x31;
5620 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5622 // TX_LO2_en, RF R15 register Bit 3 to 0
5623 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5624 RFValue &= (~0x08);
5625 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5627 // TX_LO1_en, RF R17 register Bit 3 to 0
5628 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5629 RFValue &= (~0x08);
5630 // to fix rx long range issue
5631 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5633 RFValue |= 0x20;
5635 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5637 // RX_LO1_en, RF R20 register Bit 3 to 0
5638 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5639 RFValue &= (~0x08);
5640 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5642 // RX_LO2_en, RF R21 register Bit 3 to 0
5643 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5644 RFValue &= (~0x08);
5645 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5647 // LDORF_VC, RF R27 register Bit 2 to 0
5648 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5649 if ((pAd->MACVersion & 0xffff) < 0x0211)
5650 RFValue = (RFValue & (~0x77)) | 0x3;
5651 else
5652 RFValue = (RFValue & (~0x77));
5653 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5654 /* end johnli */
5658 ==========================================================================
5659 Description:
5661 Load RF sleep-mode setup
5663 ==========================================================================
5665 VOID RT30xxLoadRFSleepModeSetup(
5666 IN PRTMP_ADAPTER pAd)
5668 UCHAR RFValue;
5669 UINT32 MACValue;
5671 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5672 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5673 RFValue &= (~0x01);
5674 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5676 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5677 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5678 RFValue &= (~0x30);
5679 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5681 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5682 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5683 RFValue &= (~0x0E);
5684 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5686 // RX_CTB_en, RF R21 register Bit 7 to 0
5687 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5688 RFValue &= (~0x80);
5689 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5691 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5692 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5693 RFValue |= 0x77;
5694 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5696 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5697 MACValue |= 0x1D000000;
5698 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5702 ==========================================================================
5703 Description:
5705 Reverse RF sleep-mode setup
5707 ==========================================================================
5709 VOID RT30xxReverseRFSleepModeSetup(
5710 IN PRTMP_ADAPTER pAd)
5712 UCHAR RFValue;
5713 UINT32 MACValue;
5715 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5716 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5717 RFValue |= 0x01;
5718 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5720 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5721 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5722 RFValue |= 0x30;
5723 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5725 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5726 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5727 RFValue |= 0x0E;
5728 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5730 // RX_CTB_en, RF R21 register Bit 7 to 1
5731 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5732 RFValue |= 0x80;
5733 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5735 // LDORF_VC, RF R27 register Bit 2 to 0
5736 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5737 if ((pAd->MACVersion & 0xffff) < 0x0211)
5738 RFValue = (RFValue & (~0x77)) | 0x3;
5739 else
5740 RFValue = (RFValue & (~0x77));
5741 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5743 // RT3071 version E has fixed this issue
5744 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5746 // patch tx EVM issue temporarily
5747 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5748 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5749 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5751 else
5753 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5754 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5755 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5758 // end johnli
5759 #endif // RT30xx //
5762 ==========================================================================
5763 Description:
5765 IRQL = PASSIVE_LEVEL
5766 IRQL = DISPATCH_LEVEL
5768 ==========================================================================
5770 VOID AsicSwitchChannel(
5771 IN PRTMP_ADAPTER pAd,
5772 IN UCHAR Channel,
5773 IN BOOLEAN bScan)
5775 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5776 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5777 UCHAR index;
5778 UINT32 Value = 0; //BbpReg, Value;
5779 RTMP_RF_REGS *RFRegTable;
5781 // Search Tx power value
5782 #ifdef RT30xx
5783 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5784 // in ChannelList, so use TxPower array instead.
5786 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5788 if (Channel == pAd->TxPower[index].Channel)
5790 TxPwer = pAd->TxPower[index].Power;
5791 TxPwer2 = pAd->TxPower[index].Power2;
5792 break;
5795 #endif
5796 #ifndef RT30xx
5797 for (index = 0; index < pAd->ChannelListNum; index++)
5799 if (Channel == pAd->ChannelList[index].Channel)
5801 TxPwer = pAd->ChannelList[index].Power;
5802 TxPwer2 = pAd->ChannelList[index].Power2;
5803 break;
5806 #endif
5808 if (index == MAX_NUM_OF_CHANNELS)
5810 #ifndef RT30xx
5811 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5812 #endif
5813 #ifdef RT30xx
5814 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5815 #endif
5818 #ifdef RT2870
5819 // The RF programming sequence is difference between 3xxx and 2xxx
5820 #ifdef RT30xx
5821 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5822 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5823 #endif
5824 #ifndef RT30xx
5825 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5826 #endif
5828 /* modify by WY for Read RF Reg. error */
5829 UCHAR RFValue;
5831 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5833 if (Channel == FreqItems3020[index].Channel)
5835 // Programming channel parameters
5836 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5837 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5839 #ifndef RT30xx
5840 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5841 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5842 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5844 // Set Tx Power
5845 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5846 RFValue = (RFValue & 0xE0) | TxPwer;
5847 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5849 // Set RF offset
5850 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5851 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5852 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5853 #endif
5854 #ifdef RT30xx
5855 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5856 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5857 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5859 // Set Tx0 Power
5860 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5861 RFValue = (RFValue & 0xE0) | TxPwer;
5862 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5864 // Set Tx1 Power
5865 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5866 RFValue = (RFValue & 0xE0) | TxPwer2;
5867 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5869 // Tx/Rx Stream setting
5870 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5871 //if (IS_RT3090(pAd))
5872 // RFValue |= 0x01; // Enable RF block.
5873 RFValue &= 0x03; //clear bit[7~2]
5874 if (pAd->Antenna.field.TxPath == 1)
5875 RFValue |= 0xA0;
5876 else if (pAd->Antenna.field.TxPath == 2)
5877 RFValue |= 0x80;
5878 if (pAd->Antenna.field.RxPath == 1)
5879 RFValue |= 0x50;
5880 else if (pAd->Antenna.field.RxPath == 2)
5881 RFValue |= 0x40;
5882 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5884 // Set RF offset
5885 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5886 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5887 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5888 #endif
5890 // Set BW
5891 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5893 RFValue = pAd->Mlme.CaliBW40RfR24;
5894 //DISABLE_11N_CHECK(pAd);
5896 else
5898 RFValue = pAd->Mlme.CaliBW20RfR24;
5900 #ifndef RT30xx
5901 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5903 // Enable RF tuning
5904 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5905 RFValue = RFValue | 0x1;
5906 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5908 // latch channel for future usage.
5909 pAd->LatchRfRegs.Channel = Channel;
5910 #endif
5911 #ifdef RT30xx
5912 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5913 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5915 // Enable RF tuning
5916 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5917 RFValue = RFValue | 0x1;
5918 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5920 // latch channel for future usage.
5921 pAd->LatchRfRegs.Channel = Channel;
5923 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5924 Channel,
5925 pAd->RfIcType,
5926 TxPwer,
5927 TxPwer2,
5928 pAd->Antenna.field.TxPath,
5929 FreqItems3020[index].N,
5930 FreqItems3020[index].K,
5931 FreqItems3020[index].R));
5932 #endif
5934 break;
5938 #ifndef RT30xx
5939 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5940 Channel,
5941 pAd->RfIcType,
5942 TxPwer,
5943 TxPwer2,
5944 pAd->Antenna.field.TxPath,
5945 FreqItems3020[index].N,
5946 FreqItems3020[index].K,
5947 FreqItems3020[index].R));
5948 #endif
5950 else
5951 #endif // RT2870 //
5953 RFRegTable = RF2850RegTable;
5955 switch (pAd->RfIcType)
5957 case RFIC_2820:
5958 case RFIC_2850:
5959 case RFIC_2720:
5960 case RFIC_2750:
5962 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5964 if (Channel == RFRegTable[index].Channel)
5966 R2 = RFRegTable[index].R2;
5967 if (pAd->Antenna.field.TxPath == 1)
5969 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5972 if (pAd->Antenna.field.RxPath == 2)
5974 R2 |= 0x40; // write 1 to off Rxpath.
5976 else if (pAd->Antenna.field.RxPath == 1)
5978 R2 |= 0x20040; // write 1 to off RxPath
5981 if (Channel > 14)
5983 // initialize R3, R4
5984 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5985 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5987 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5988 // R3
5989 if ((TxPwer >= -7) && (TxPwer < 0))
5991 TxPwer = (7+TxPwer);
5992 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5993 R3 |= (TxPwer << 10);
5994 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5996 else
5998 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5999 R3 |= (TxPwer << 10) | (1 << 9);
6002 // R4
6003 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
6005 TxPwer2 = (7+TxPwer2);
6006 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6007 R4 |= (TxPwer2 << 7);
6008 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
6010 else
6012 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6013 R4 |= (TxPwer2 << 7) | (1 << 6);
6016 else
6018 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6019 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6022 // Based on BBP current mode before changing RF channel.
6023 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6025 R4 |=0x200000;
6028 // Update variables
6029 pAd->LatchRfRegs.Channel = Channel;
6030 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6031 pAd->LatchRfRegs.R2 = R2;
6032 pAd->LatchRfRegs.R3 = R3;
6033 pAd->LatchRfRegs.R4 = R4;
6035 // Set RF value 1's set R3[bit2] = [0]
6036 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6037 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6038 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6039 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6041 RTMPusecDelay(200);
6043 // Set RF value 2's set R3[bit2] = [1]
6044 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6045 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6046 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6047 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6049 RTMPusecDelay(200);
6051 // Set RF value 3's set R3[bit2] = [0]
6052 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6053 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6054 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6055 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6057 break;
6060 break;
6062 default:
6063 break;
6067 // Change BBP setting during siwtch from a->g, g->a
6068 if (Channel <= 14)
6070 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6072 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6073 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6074 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6075 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue.
6076 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6078 // Rx High power VGA offset for LNA select
6079 if (pAd->NicConfig2.field.ExternalLNAForG)
6081 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6082 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6084 else
6086 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6087 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6090 // 5G band selection PIN, bit1 and bit2 are complement
6091 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6092 Value &= (~0x6);
6093 Value |= (0x04);
6094 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6096 // Turn off unused PA or LNA when only 1T or 1R
6097 if (pAd->Antenna.field.TxPath == 1)
6099 TxPinCfg &= 0xFFFFFFF3;
6101 if (pAd->Antenna.field.RxPath == 1)
6103 TxPinCfg &= 0xFFFFF3FF;
6106 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6108 else
6110 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6112 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6113 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6114 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6115 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue.
6116 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6118 // Rx High power VGA offset for LNA select
6119 if (pAd->NicConfig2.field.ExternalLNAForA)
6121 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6123 else
6125 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6128 // 5G band selection PIN, bit1 and bit2 are complement
6129 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6130 Value &= (~0x6);
6131 Value |= (0x02);
6132 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6134 // Turn off unused PA or LNA when only 1T or 1R
6135 if (pAd->Antenna.field.TxPath == 1)
6137 TxPinCfg &= 0xFFFFFFF3;
6139 if (pAd->Antenna.field.RxPath == 1)
6141 TxPinCfg &= 0xFFFFF3FF;
6144 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6147 // R66 should be set according to Channel and use 20MHz when scanning
6148 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6149 if (bScan)
6150 RTMPSetAGCInitValue(pAd, BW_20);
6151 else
6152 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6155 // On 11A, We should delay and wait RF/BBP to be stable
6156 // and the appropriate time should be 1000 micro seconds
6157 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6159 RTMPusecDelay(1000);
6161 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
6162 Channel,
6163 pAd->RfIcType,
6164 (R3 & 0x00003e00) >> 9,
6165 (R4 & 0x000007c0) >> 6,
6166 pAd->Antenna.field.TxPath,
6167 pAd->LatchRfRegs.R1,
6168 pAd->LatchRfRegs.R2,
6169 pAd->LatchRfRegs.R3,
6170 pAd->LatchRfRegs.R4));
6174 ==========================================================================
6175 Description:
6176 This function is required for 2421 only, and should not be used during
6177 site survey. It's only required after NIC decided to stay at a channel
6178 for a longer period.
6179 When this function is called, it's always after AsicSwitchChannel().
6181 IRQL = PASSIVE_LEVEL
6182 IRQL = DISPATCH_LEVEL
6184 ==========================================================================
6186 VOID AsicLockChannel(
6187 IN PRTMP_ADAPTER pAd,
6188 IN UCHAR Channel)
6193 ==========================================================================
6194 Description:
6196 IRQL = PASSIVE_LEVEL
6197 IRQL = DISPATCH_LEVEL
6199 ==========================================================================
6201 VOID AsicAntennaSelect(
6202 IN PRTMP_ADAPTER pAd,
6203 IN UCHAR Channel)
6205 #ifdef RT30xx
6206 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6208 // patch for AsicSetRxAnt failed
6209 pAd->RxAnt.EvaluatePeriod = 0;
6211 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6212 // valid indication of the distance between this AP and its clients.
6213 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6215 SHORT realavgrssi1;
6217 // if no traffic then reset average rssi to trigger evaluation
6218 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6220 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6221 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6222 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6225 pAd->StaCfg.NumOfAvgRssiSample = 0;
6226 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6228 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6230 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6231 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6233 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6234 AsicEvaluateRxAnt(pAd);
6237 else
6239 // if not connected, always switch antenna to try to connect
6240 UCHAR temp;
6242 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6243 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6244 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6246 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6248 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6251 #endif /* RT30xx */
6255 ========================================================================
6257 Routine Description:
6258 Antenna miscellaneous setting.
6260 Arguments:
6261 pAd Pointer to our adapter
6262 BandState Indicate current Band State.
6264 Return Value:
6265 None
6267 IRQL <= DISPATCH_LEVEL
6269 Note:
6270 1.) Frame End type control
6271 only valid for G only (RF_2527 & RF_2529)
6272 0: means DPDT, set BBP R4 bit 5 to 1
6273 1: means SPDT, set BBP R4 bit 5 to 0
6276 ========================================================================
6278 VOID AsicAntennaSetting(
6279 IN PRTMP_ADAPTER pAd,
6280 IN ABGBAND_STATE BandState)
6284 VOID AsicRfTuningExec(
6285 IN PVOID SystemSpecific1,
6286 IN PVOID FunctionContext,
6287 IN PVOID SystemSpecific2,
6288 IN PVOID SystemSpecific3)
6293 ==========================================================================
6294 Description:
6295 Gives CCK TX rate 2 more dB TX power.
6296 This routine works only in LINK UP in INFRASTRUCTURE mode.
6298 calculate desired Tx power in RF R3.Tx0~5, should consider -
6299 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6300 1. TxPowerPercentage
6301 2. auto calibration based on TSSI feedback
6302 3. extra 2 db for CCK
6303 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6305 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6306 it should be called AFTER MlmeDynamicTxRatSwitching()
6307 ==========================================================================
6309 VOID AsicAdjustTxPower(
6310 IN PRTMP_ADAPTER pAd)
6312 INT i, j;
6313 CHAR DeltaPwr = 0;
6314 BOOLEAN bAutoTxAgc = FALSE;
6315 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6316 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6317 PCHAR pTxAgcCompensate;
6318 ULONG TxPwr[5];
6319 CHAR Value;
6321 #ifdef RT2860
6322 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6323 || (pAd->bPCIclkOff == TRUE)
6324 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6325 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6326 return;
6327 #endif
6329 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6331 if (pAd->CommonCfg.CentralChannel > 14)
6333 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6334 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6335 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6336 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6337 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6339 else
6341 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6342 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6343 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6344 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6345 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6348 else
6350 if (pAd->CommonCfg.Channel > 14)
6352 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6353 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6354 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6355 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6356 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6358 else
6360 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6361 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6362 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6363 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6364 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6368 // TX power compensation for temperature variation based on TSSI. try every 4 second
6369 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6371 if (pAd->CommonCfg.Channel <= 14)
6373 /* bg channel */
6374 bAutoTxAgc = pAd->bAutoTxAgcG;
6375 TssiRef = pAd->TssiRefG;
6376 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6377 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6378 TxAgcStep = pAd->TxAgcStepG;
6379 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6381 else
6383 /* a channel */
6384 bAutoTxAgc = pAd->bAutoTxAgcA;
6385 TssiRef = pAd->TssiRefA;
6386 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6387 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6388 TxAgcStep = pAd->TxAgcStepA;
6389 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6392 if (bAutoTxAgc)
6394 /* BbpR1 is unsigned char */
6395 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6397 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6398 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6399 /* step value is defined in pAd->TxAgcStepG for tx power value */
6401 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6402 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6403 above value are examined in mass factory production */
6404 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6406 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6407 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6408 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6410 if (BbpR49 > pTssiMinusBoundary[1])
6412 // Reading is larger than the reference value
6413 // check for how large we need to decrease the Tx power
6414 for (idx = 1; idx < 5; idx++)
6416 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6417 break;
6419 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6420 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6422 DeltaPwr += (*pTxAgcCompensate);
6423 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6424 BbpR49, TssiRef, TxAgcStep, idx-1));
6426 else if (BbpR49 < pTssiPlusBoundary[1])
6428 // Reading is smaller than the reference value
6429 // check for how large we need to increase the Tx power
6430 for (idx = 1; idx < 5; idx++)
6432 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6433 break;
6435 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6436 *pTxAgcCompensate = TxAgcStep * (idx-1);
6437 DeltaPwr += (*pTxAgcCompensate);
6438 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6439 BbpR49, TssiRef, TxAgcStep, idx-1));
6441 else
6443 *pTxAgcCompensate = 0;
6444 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6445 BbpR49, TssiRef, TxAgcStep, 0));
6449 else
6451 if (pAd->CommonCfg.Channel <= 14)
6453 bAutoTxAgc = pAd->bAutoTxAgcG;
6454 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6456 else
6458 bAutoTxAgc = pAd->bAutoTxAgcA;
6459 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6462 if (bAutoTxAgc)
6463 DeltaPwr += (*pTxAgcCompensate);
6466 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6467 BbpR1 &= 0xFC;
6469 /* calculate delta power based on the percentage specified from UI */
6470 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6471 // We lower TX power here according to the percentage specified from UI
6472 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6474 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6476 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6478 DeltaPwr -= 1;
6480 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6482 DeltaPwr -= 3;
6484 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6486 BbpR1 |= 0x01;
6488 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6490 BbpR1 |= 0x01;
6491 DeltaPwr -= 3;
6493 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6495 BbpR1 |= 0x02;
6498 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6500 /* reset different new tx power for different TX rate */
6501 for(i=0; i<5; i++)
6503 if (TxPwr[i] != 0xffffffff)
6505 for (j=0; j<8; j++)
6507 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6509 if ((Value + DeltaPwr) < 0)
6511 Value = 0; /* min */
6513 else if ((Value + DeltaPwr) > 0xF)
6515 Value = 0xF; /* max */
6517 else
6519 Value += DeltaPwr; /* temperature compensation */
6522 /* fill new value to CSR offset */
6523 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6526 /* write tx power value to CSR */
6527 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6528 TX power for OFDM 6M/9M
6529 TX power for CCK5.5M/11M
6530 TX power for CCK1M/2M */
6531 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6532 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6539 ==========================================================================
6540 Description:
6541 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6542 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6543 the wakeup timer timeout. Driver has to issue a separate command to wake
6544 PHY up.
6546 IRQL = DISPATCH_LEVEL
6548 ==========================================================================
6550 VOID AsicSleepThenAutoWakeup(
6551 IN PRTMP_ADAPTER pAd,
6552 IN USHORT TbttNumToNextWakeUp)
6554 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6558 ==========================================================================
6559 Description:
6560 AsicForceWakeup() is used whenever manual wakeup is required
6561 AsicForceSleep() should only be used when not in INFRA BSS. When
6562 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6563 ==========================================================================
6565 VOID AsicForceSleep(
6566 IN PRTMP_ADAPTER pAd)
6572 ==========================================================================
6573 Description:
6574 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6575 expired.
6577 IRQL = PASSIVE_LEVEL
6578 IRQL = DISPATCH_LEVEL
6579 ==========================================================================
6581 VOID AsicForceWakeup(
6582 IN PRTMP_ADAPTER pAd,
6583 #ifdef RT2860
6584 IN UCHAR Level)
6585 #endif
6586 #ifdef RT2870
6587 IN BOOLEAN bFromTx)
6588 #endif
6590 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6591 #ifdef RT2860
6592 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6593 #endif
6594 #ifdef RT2870
6595 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6596 #endif
6600 ==========================================================================
6601 Description:
6602 Set My BSSID
6604 IRQL = DISPATCH_LEVEL
6606 ==========================================================================
6608 VOID AsicSetBssid(
6609 IN PRTMP_ADAPTER pAd,
6610 IN PUCHAR pBssid)
6612 ULONG Addr4;
6613 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6614 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6616 Addr4 = (ULONG)(pBssid[0]) |
6617 (ULONG)(pBssid[1] << 8) |
6618 (ULONG)(pBssid[2] << 16) |
6619 (ULONG)(pBssid[3] << 24);
6620 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6622 Addr4 = 0;
6623 // always one BSSID in STA mode
6624 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6626 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6629 VOID AsicSetMcastWC(
6630 IN PRTMP_ADAPTER pAd)
6632 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6633 USHORT offset;
6635 pEntry->Sst = SST_ASSOC;
6636 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6637 pEntry->PsMode = PWR_ACTIVE;
6638 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6639 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6643 ==========================================================================
6644 Description:
6646 IRQL = DISPATCH_LEVEL
6648 ==========================================================================
6650 VOID AsicDelWcidTab(
6651 IN PRTMP_ADAPTER pAd,
6652 IN UCHAR Wcid)
6654 ULONG Addr0 = 0x0, Addr1 = 0x0;
6655 ULONG offset;
6657 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6658 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6659 RTMP_IO_WRITE32(pAd, offset, Addr0);
6660 offset += 4;
6661 RTMP_IO_WRITE32(pAd, offset, Addr1);
6665 ==========================================================================
6666 Description:
6668 IRQL = DISPATCH_LEVEL
6670 ==========================================================================
6672 VOID AsicEnableRDG(
6673 IN PRTMP_ADAPTER pAd)
6675 TX_LINK_CFG_STRUC TxLinkCfg;
6676 UINT32 Data = 0;
6678 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6679 TxLinkCfg.field.TxRDGEn = 1;
6680 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6682 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6683 Data &= 0xFFFFFF00;
6684 Data |= 0x80;
6685 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6687 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6691 ==========================================================================
6692 Description:
6694 IRQL = DISPATCH_LEVEL
6696 ==========================================================================
6698 VOID AsicDisableRDG(
6699 IN PRTMP_ADAPTER pAd)
6701 TX_LINK_CFG_STRUC TxLinkCfg;
6702 UINT32 Data = 0;
6705 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6706 TxLinkCfg.field.TxRDGEn = 0;
6707 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6709 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6711 Data &= 0xFFFFFF00;
6712 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6713 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6716 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6717 if (pAd->CommonCfg.bEnableTxBurst)
6718 Data |= 0x20;
6720 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6724 ==========================================================================
6725 Description:
6727 IRQL = PASSIVE_LEVEL
6728 IRQL = DISPATCH_LEVEL
6730 ==========================================================================
6732 VOID AsicDisableSync(
6733 IN PRTMP_ADAPTER pAd)
6735 BCN_TIME_CFG_STRUC csr;
6737 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6739 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6740 // that NIC will never wakes up because TSF stops and no more
6741 // TBTT interrupts
6742 pAd->TbttTickCount = 0;
6743 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6744 csr.field.bBeaconGen = 0;
6745 csr.field.bTBTTEnable = 0;
6746 csr.field.TsfSyncMode = 0;
6747 csr.field.bTsfTicking = 0;
6748 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6753 ==========================================================================
6754 Description:
6756 IRQL = DISPATCH_LEVEL
6758 ==========================================================================
6760 VOID AsicEnableBssSync(
6761 IN PRTMP_ADAPTER pAd)
6763 BCN_TIME_CFG_STRUC csr;
6765 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6767 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6770 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6771 csr.field.bTsfTicking = 1;
6772 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6773 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6774 csr.field.bTBTTEnable = 1;
6777 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6781 ==========================================================================
6782 Description:
6783 Note:
6784 BEACON frame in shared memory should be built ok before this routine
6785 can be called. Otherwise, a garbage frame maybe transmitted out every
6786 Beacon period.
6788 IRQL = DISPATCH_LEVEL
6790 ==========================================================================
6792 VOID AsicEnableIbssSync(
6793 IN PRTMP_ADAPTER pAd)
6795 BCN_TIME_CFG_STRUC csr9;
6796 PUCHAR ptr;
6797 UINT i;
6799 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6801 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6802 csr9.field.bBeaconGen = 0;
6803 csr9.field.bTBTTEnable = 0;
6804 csr9.field.bTsfTicking = 0;
6805 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6807 #ifdef RT2860
6808 // move BEACON TXD and frame content to on-chip memory
6809 ptr = (PUCHAR)&pAd->BeaconTxWI;
6810 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6812 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6813 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6814 ptr += 4;
6817 // start right after the 16-byte TXWI field
6818 ptr = pAd->BeaconBuf;
6819 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6821 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6822 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6823 ptr +=4;
6825 #endif
6826 #ifdef RT2870
6827 // move BEACON TXD and frame content to on-chip memory
6828 ptr = (PUCHAR)&pAd->BeaconTxWI;
6829 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6831 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6832 ptr += 2;
6835 // start right after the 16-byte TXWI field
6836 ptr = pAd->BeaconBuf;
6837 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6839 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6840 ptr +=2;
6842 #endif // RT2870 //
6844 // start sending BEACON
6845 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6846 csr9.field.bTsfTicking = 1;
6847 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6848 csr9.field.bTBTTEnable = 1;
6849 csr9.field.bBeaconGen = 1;
6850 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6854 ==========================================================================
6855 Description:
6857 IRQL = PASSIVE_LEVEL
6858 IRQL = DISPATCH_LEVEL
6860 ==========================================================================
6862 VOID AsicSetEdcaParm(
6863 IN PRTMP_ADAPTER pAd,
6864 IN PEDCA_PARM pEdcaParm)
6866 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6867 AC_TXOP_CSR0_STRUC csr0;
6868 AC_TXOP_CSR1_STRUC csr1;
6869 AIFSN_CSR_STRUC AifsnCsr;
6870 CWMIN_CSR_STRUC CwminCsr;
6871 CWMAX_CSR_STRUC CwmaxCsr;
6872 int i;
6874 Ac0Cfg.word = 0;
6875 Ac1Cfg.word = 0;
6876 Ac2Cfg.word = 0;
6877 Ac3Cfg.word = 0;
6878 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6880 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6881 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6882 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6884 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6885 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6888 //========================================================
6889 // MAC Register has a copy .
6890 //========================================================
6891 if( pAd->CommonCfg.bEnableTxBurst )
6893 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6894 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6896 else
6897 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6898 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6899 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6900 Ac0Cfg.field.Aifsn = 2;
6901 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6903 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6904 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6905 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6906 Ac1Cfg.field.Aifsn = 2;
6907 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6909 if (pAd->CommonCfg.PhyMode == PHY_11B)
6911 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6912 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6914 else
6916 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6917 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6919 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6920 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6921 Ac2Cfg.field.Aifsn = 2;
6922 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6923 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6924 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6925 Ac3Cfg.field.Aifsn = 2;
6926 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6928 //========================================================
6929 // DMA Register has a copy too.
6930 //========================================================
6931 csr0.field.Ac0Txop = 0; // QID_AC_BE
6932 csr0.field.Ac1Txop = 0; // QID_AC_BK
6933 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6934 if (pAd->CommonCfg.PhyMode == PHY_11B)
6936 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6937 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6939 else
6941 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6942 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6944 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6946 CwminCsr.word = 0;
6947 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6948 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6949 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6950 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6951 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6953 CwmaxCsr.word = 0;
6954 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6955 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6956 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6957 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6958 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6960 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6962 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6964 else
6966 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6967 //========================================================
6968 // MAC Register has a copy.
6969 //========================================================
6971 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6972 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6974 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6976 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6977 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6978 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6979 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6981 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6982 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6983 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6984 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6986 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6987 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6988 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6989 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6992 // Tuning for Wi-Fi WMM S06
6993 if (pAd->CommonCfg.bWiFiTest &&
6994 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6995 Ac2Cfg.field.Aifsn -= 1;
6997 // Tuning for TGn Wi-Fi 5.2.32
6998 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6999 if (STA_TGN_WIFI_ON(pAd) &&
7000 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7002 Ac0Cfg.field.Aifsn = 3;
7003 Ac2Cfg.field.AcTxop = 5;
7006 #ifdef RT30xx
7007 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7009 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
7010 Ac2Cfg.field.Aifsn = 5;
7012 #endif // RT30xx //
7015 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7016 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7017 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7018 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7020 //#ifdef WIFI_TEST
7021 if (pAd->CommonCfg.bWiFiTest)
7023 if (Ac3Cfg.field.AcTxop == 102)
7025 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7026 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7027 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7028 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7029 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7030 } /* End of if */
7032 //#endif // WIFI_TEST //
7034 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7035 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7036 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7037 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7040 //========================================================
7041 // DMA Register has a copy too.
7042 //========================================================
7043 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7044 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7045 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7047 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7048 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7049 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7051 CwminCsr.word = 0;
7052 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7053 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7054 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7056 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7058 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7060 CwmaxCsr.word = 0;
7061 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7062 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7063 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7064 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7065 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7067 AifsnCsr.word = 0;
7068 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7069 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7070 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7073 // Tuning for Wi-Fi WMM S06
7074 if (pAd->CommonCfg.bWiFiTest &&
7075 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7076 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7078 // Tuning for TGn Wi-Fi 5.2.32
7079 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7080 if (STA_TGN_WIFI_ON(pAd) &&
7081 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7083 AifsnCsr.field.Aifsn0 = 3;
7084 AifsnCsr.field.Aifsn2 = 7;
7086 #ifdef RT2870
7087 if (INFRA_ON(pAd))
7088 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7089 #endif
7092 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7093 #ifdef RT30xx
7094 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7095 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7096 #endif // RT30xx //
7098 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7100 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7101 if (!ADHOC_ON(pAd))
7103 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7104 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7105 pEdcaParm->Aifsn[0],
7106 pEdcaParm->Cwmin[0],
7107 pEdcaParm->Cwmax[0],
7108 pEdcaParm->Txop[0]<<5,
7109 pEdcaParm->bACM[0]));
7110 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7111 pEdcaParm->Aifsn[1],
7112 pEdcaParm->Cwmin[1],
7113 pEdcaParm->Cwmax[1],
7114 pEdcaParm->Txop[1]<<5,
7115 pEdcaParm->bACM[1]));
7116 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7117 pEdcaParm->Aifsn[2],
7118 pEdcaParm->Cwmin[2],
7119 pEdcaParm->Cwmax[2],
7120 pEdcaParm->Txop[2]<<5,
7121 pEdcaParm->bACM[2]));
7122 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7123 pEdcaParm->Aifsn[3],
7124 pEdcaParm->Cwmin[3],
7125 pEdcaParm->Cwmax[3],
7126 pEdcaParm->Txop[3]<<5,
7127 pEdcaParm->bACM[3]));
7133 ==========================================================================
7134 Description:
7136 IRQL = PASSIVE_LEVEL
7137 IRQL = DISPATCH_LEVEL
7139 ==========================================================================
7141 VOID AsicSetSlotTime(
7142 IN PRTMP_ADAPTER pAd,
7143 IN BOOLEAN bUseShortSlotTime)
7145 ULONG SlotTime;
7146 UINT32 RegValue = 0;
7148 if (pAd->CommonCfg.Channel > 14)
7149 bUseShortSlotTime = TRUE;
7151 if (bUseShortSlotTime)
7152 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7153 else
7154 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7156 SlotTime = (bUseShortSlotTime)? 9 : 20;
7159 #ifndef RT30xx
7160 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7161 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7162 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7165 // In this case, we will think it is doing Wi-Fi test
7166 // And we will not set to short slot when bEnableTxBurst is TRUE.
7168 else if (pAd->CommonCfg.bEnableTxBurst)
7169 #endif
7170 #ifdef RT30xx
7171 if (pAd->CommonCfg.bEnableTxBurst)
7172 #endif
7173 SlotTime = 9;
7177 // For some reasons, always set it to short slot time.
7179 // ToDo: Should consider capability with 11B
7181 if (pAd->StaCfg.BssType == BSS_ADHOC)
7182 SlotTime = 20;
7184 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7185 RegValue = RegValue & 0xFFFFFF00;
7187 RegValue |= SlotTime;
7189 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7193 ========================================================================
7194 Description:
7195 Add Shared key information into ASIC.
7196 Update shared key, TxMic and RxMic to Asic Shared key table
7197 Update its cipherAlg to Asic Shared key Mode.
7199 Return:
7200 ========================================================================
7202 VOID AsicAddSharedKeyEntry(
7203 IN PRTMP_ADAPTER pAd,
7204 IN UCHAR BssIndex,
7205 IN UCHAR KeyIdx,
7206 IN UCHAR CipherAlg,
7207 IN PUCHAR pKey,
7208 IN PUCHAR pTxMic,
7209 IN PUCHAR pRxMic)
7211 ULONG offset; //, csr0;
7212 SHAREDKEY_MODE_STRUC csr1;
7213 #ifdef RT2860
7214 INT i;
7215 #endif
7217 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7218 //============================================================================================
7220 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7221 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7222 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7223 if (pRxMic)
7225 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7226 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7228 if (pTxMic)
7230 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7231 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7233 //============================================================================================
7235 // fill key material - key + TX MIC + RX MIC
7238 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7239 #ifdef RT2860
7240 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7242 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7244 #endif
7245 #ifdef RT2870
7246 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7247 #endif
7248 offset += MAX_LEN_OF_SHARE_KEY;
7249 if (pTxMic)
7251 #ifdef RT2860
7252 for (i=0; i<8; i++)
7254 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7256 #endif
7257 #ifdef RT2870
7258 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7259 #endif
7262 offset += 8;
7263 if (pRxMic)
7265 #ifdef RT2860
7266 for (i=0; i<8; i++)
7268 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7270 #endif
7271 #ifdef RT2870
7272 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7273 #endif
7278 // Update cipher algorithm. WSTA always use BSS0
7280 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7281 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7282 if ((BssIndex%2) == 0)
7284 if (KeyIdx == 0)
7285 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7286 else if (KeyIdx == 1)
7287 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7288 else if (KeyIdx == 2)
7289 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7290 else
7291 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7293 else
7295 if (KeyIdx == 0)
7296 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7297 else if (KeyIdx == 1)
7298 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7299 else if (KeyIdx == 2)
7300 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7301 else
7302 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7304 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7305 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7309 // IRQL = DISPATCH_LEVEL
7310 VOID AsicRemoveSharedKeyEntry(
7311 IN PRTMP_ADAPTER pAd,
7312 IN UCHAR BssIndex,
7313 IN UCHAR KeyIdx)
7315 //ULONG SecCsr0;
7316 SHAREDKEY_MODE_STRUC csr1;
7318 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7320 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7321 if ((BssIndex%2) == 0)
7323 if (KeyIdx == 0)
7324 csr1.field.Bss0Key0CipherAlg = 0;
7325 else if (KeyIdx == 1)
7326 csr1.field.Bss0Key1CipherAlg = 0;
7327 else if (KeyIdx == 2)
7328 csr1.field.Bss0Key2CipherAlg = 0;
7329 else
7330 csr1.field.Bss0Key3CipherAlg = 0;
7332 else
7334 if (KeyIdx == 0)
7335 csr1.field.Bss1Key0CipherAlg = 0;
7336 else if (KeyIdx == 1)
7337 csr1.field.Bss1Key1CipherAlg = 0;
7338 else if (KeyIdx == 2)
7339 csr1.field.Bss1Key2CipherAlg = 0;
7340 else
7341 csr1.field.Bss1Key3CipherAlg = 0;
7343 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7344 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7345 ASSERT(BssIndex < 4);
7346 ASSERT(KeyIdx < 4);
7351 VOID AsicUpdateWCIDAttribute(
7352 IN PRTMP_ADAPTER pAd,
7353 IN USHORT WCID,
7354 IN UCHAR BssIndex,
7355 IN UCHAR CipherAlg,
7356 IN BOOLEAN bUsePairewiseKeyTable)
7358 ULONG WCIDAttri = 0, offset;
7361 // Update WCID attribute.
7362 // Only TxKey could update WCID attribute.
7364 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7365 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7366 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7369 VOID AsicUpdateWCIDIVEIV(
7370 IN PRTMP_ADAPTER pAd,
7371 IN USHORT WCID,
7372 IN ULONG uIV,
7373 IN ULONG uEIV)
7375 ULONG offset;
7377 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7379 RTMP_IO_WRITE32(pAd, offset, uIV);
7380 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7383 VOID AsicUpdateRxWCIDTable(
7384 IN PRTMP_ADAPTER pAd,
7385 IN USHORT WCID,
7386 IN PUCHAR pAddr)
7388 ULONG offset;
7389 ULONG Addr;
7391 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7392 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7393 RTMP_IO_WRITE32(pAd, offset, Addr);
7394 Addr = pAddr[4] + (pAddr[5] << 8);
7395 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7400 ========================================================================
7402 Routine Description:
7403 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7405 Arguments:
7406 pAd Pointer to our adapter
7407 WCID WCID Entry number.
7408 BssIndex BSSID index, station or none multiple BSSID support
7409 this value should be 0.
7410 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7411 pCipherKey Pointer to Cipher Key.
7412 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7413 otherwise PairewiseKey table
7414 bTxKey This is the transmit key if enabled.
7416 Return Value:
7417 None
7419 Note:
7420 This routine will set the relative key stuff to Asic including WCID attribute,
7421 Cipher Key, Cipher algorithm and IV/EIV.
7423 IV/EIV will be update if this CipherKey is the transmission key because
7424 ASIC will base on IV's KeyID value to select Cipher Key.
7426 If bTxKey sets to FALSE, this is not the TX key, but it could be
7427 RX key
7429 For AP mode bTxKey must be always set to TRUE.
7430 ========================================================================
7432 VOID AsicAddKeyEntry(
7433 IN PRTMP_ADAPTER pAd,
7434 IN USHORT WCID,
7435 IN UCHAR BssIndex,
7436 IN UCHAR KeyIdx,
7437 IN PCIPHER_KEY pCipherKey,
7438 IN BOOLEAN bUsePairewiseKeyTable,
7439 IN BOOLEAN bTxKey)
7441 ULONG offset;
7442 UCHAR IV4 = 0;
7443 PUCHAR pKey = pCipherKey->Key;
7444 PUCHAR pTxMic = pCipherKey->TxMic;
7445 PUCHAR pRxMic = pCipherKey->RxMic;
7446 PUCHAR pTxtsc = pCipherKey->TxTsc;
7447 UCHAR CipherAlg = pCipherKey->CipherAlg;
7448 SHAREDKEY_MODE_STRUC csr1;
7449 #ifdef RT2860
7450 UCHAR i;
7451 #endif
7453 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7455 // 1.) decide key table offset
7457 if (bUsePairewiseKeyTable)
7458 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7459 else
7460 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7463 // 2.) Set Key to Asic
7465 //for (i = 0; i < KeyLen; i++)
7466 #ifdef RT2860
7467 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7469 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7471 #endif
7472 #ifdef RT2870
7473 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7474 #endif
7475 offset += MAX_LEN_OF_PEER_KEY;
7478 // 3.) Set MIC key if available
7480 if (pTxMic)
7482 #ifdef RT2860
7483 for (i = 0; i < 8; i++)
7485 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7487 #endif
7488 #ifdef RT2870
7489 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7490 #endif
7492 offset += LEN_TKIP_TXMICK;
7494 if (pRxMic)
7496 #ifdef RT2860
7497 for (i = 0; i < 8; i++)
7499 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7501 #endif
7502 #ifdef RT2870
7503 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7504 #endif
7509 // 4.) Modify IV/EIV if needs
7510 // This will force Asic to use this key ID by setting IV.
7512 if (bTxKey)
7514 #ifdef RT2860
7515 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7517 // Write IV
7519 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7520 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7521 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7523 IV4 = (KeyIdx << 6);
7524 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7525 IV4 |= 0x20; // turn on extension bit means EIV existence
7527 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7530 // Write EIV
7532 offset += 4;
7533 for (i = 0; i < 4; i++)
7535 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7538 #endif
7539 #ifdef RT2870
7540 UINT32 tmpVal;
7543 // Write IV
7545 IV4 = (KeyIdx << 6);
7546 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7547 IV4 |= 0x20; // turn on extension bit means EIV existence
7549 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7550 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7553 // Write EIV
7555 offset += 4;
7556 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7557 #endif // RT2870 //
7558 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7561 if (!bUsePairewiseKeyTable)
7564 // Only update the shared key security mode
7566 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7567 if ((BssIndex % 2) == 0)
7569 if (KeyIdx == 0)
7570 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7571 else if (KeyIdx == 1)
7572 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7573 else if (KeyIdx == 2)
7574 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7575 else
7576 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7578 else
7580 if (KeyIdx == 0)
7581 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7582 else if (KeyIdx == 1)
7583 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7584 else if (KeyIdx == 2)
7585 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7586 else
7587 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7589 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7592 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7597 ========================================================================
7598 Description:
7599 Add Pair-wise key material into ASIC.
7600 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7602 Return:
7603 ========================================================================
7605 VOID AsicAddPairwiseKeyEntry(
7606 IN PRTMP_ADAPTER pAd,
7607 IN PUCHAR pAddr,
7608 IN UCHAR WCID,
7609 IN CIPHER_KEY *pCipherKey)
7611 INT i;
7612 ULONG offset;
7613 PUCHAR pKey = pCipherKey->Key;
7614 PUCHAR pTxMic = pCipherKey->TxMic;
7615 PUCHAR pRxMic = pCipherKey->RxMic;
7616 #ifdef DBG
7617 UCHAR CipherAlg = pCipherKey->CipherAlg;
7618 #endif // DBG //
7620 // EKEY
7621 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7622 #ifdef RT2860
7623 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7625 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7627 #endif
7628 #ifdef RT2870
7629 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7630 #endif // RT2870 //
7631 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7633 UINT32 Value;
7634 RTMP_IO_READ32(pAd, offset + i, &Value);
7637 offset += MAX_LEN_OF_PEER_KEY;
7639 // MIC KEY
7640 if (pTxMic)
7642 #ifdef RT2860
7643 for (i=0; i<8; i++)
7645 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7647 #endif
7648 #ifdef RT2870
7649 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7650 #endif // RT2870 //
7652 offset += 8;
7653 if (pRxMic)
7655 #ifdef RT2860
7656 for (i=0; i<8; i++)
7658 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7660 #endif
7661 #ifdef RT2870
7662 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7663 #endif // RT2870 //
7666 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7667 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7668 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7669 if (pRxMic)
7671 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7672 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7674 if (pTxMic)
7676 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7677 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7681 ========================================================================
7682 Description:
7683 Remove Pair-wise key material from ASIC.
7685 Return:
7686 ========================================================================
7688 VOID AsicRemovePairwiseKeyEntry(
7689 IN PRTMP_ADAPTER pAd,
7690 IN UCHAR BssIdx,
7691 IN UCHAR Wcid)
7693 ULONG WCIDAttri;
7694 USHORT offset;
7696 // re-set the entry's WCID attribute as OPEN-NONE.
7697 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7698 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7699 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7702 BOOLEAN AsicSendCommandToMcu(
7703 IN PRTMP_ADAPTER pAd,
7704 IN UCHAR Command,
7705 IN UCHAR Token,
7706 IN UCHAR Arg0,
7707 IN UCHAR Arg1)
7709 HOST_CMD_CSR_STRUC H2MCmd;
7710 H2M_MAILBOX_STRUC H2MMailbox;
7711 ULONG i = 0;
7715 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7716 if (H2MMailbox.field.Owner == 0)
7717 break;
7719 RTMPusecDelay(2);
7720 } while(i++ < 100);
7722 if (i > 100)
7725 #ifdef RT2860
7726 UINT32 Data;
7728 // Reset DMA
7729 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7730 Data |= 0x2;
7731 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7733 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7734 // Reset DMA/CPU ring index
7735 RTMPRingCleanUp(pAd, QID_AC_BK);
7736 RTMPRingCleanUp(pAd, QID_AC_BE);
7737 RTMPRingCleanUp(pAd, QID_AC_VI);
7738 RTMPRingCleanUp(pAd, QID_AC_VO);
7739 RTMPRingCleanUp(pAd, QID_HCCA);
7740 RTMPRingCleanUp(pAd, QID_MGMT);
7741 RTMPRingCleanUp(pAd, QID_RX);
7743 // Clear Reset
7744 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7745 Data &= 0xfffffffd;
7746 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7747 #endif /* RT2860 */
7748 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7750 //return FALSE;
7751 #ifdef RT2870
7752 return FALSE;
7753 #endif
7756 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7757 H2MMailbox.field.CmdToken = Token;
7758 H2MMailbox.field.HighByte = Arg1;
7759 H2MMailbox.field.LowByte = Arg0;
7760 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7762 H2MCmd.word = 0;
7763 H2MCmd.field.HostCommand = Command;
7764 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7766 if (Command != 0x80)
7770 return TRUE;
7773 #ifdef RT2860
7774 BOOLEAN AsicCheckCommanOk(
7775 IN PRTMP_ADAPTER pAd,
7776 IN UCHAR Command)
7778 UINT32 CmdStatus = 0, CID = 0, i;
7779 UINT32 ThisCIDMask = 0;
7781 i = 0;
7784 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7785 // Find where the command is. Because this is randomly specified by firmware.
7786 if ((CID & CID0MASK) == Command)
7788 ThisCIDMask = CID0MASK;
7789 break;
7791 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7793 ThisCIDMask = CID1MASK;
7794 break;
7796 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7798 ThisCIDMask = CID2MASK;
7799 break;
7801 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7803 ThisCIDMask = CID3MASK;
7804 break;
7807 RTMPusecDelay(100);
7808 i++;
7809 }while (i < 200);
7811 // Get CommandStatus Value
7812 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7814 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7815 if (i < 200)
7817 // If Status is 1, the comamnd is success.
7818 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7819 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7821 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7822 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7823 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7824 return TRUE;
7826 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7828 else
7830 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7832 // Clear Command and Status.
7833 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7834 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7836 return FALSE;
7838 #endif /* RT8260 */
7841 ========================================================================
7843 Routine Description:
7844 Verify the support rate for different PHY type
7846 Arguments:
7847 pAd Pointer to our adapter
7849 Return Value:
7850 None
7852 IRQL = PASSIVE_LEVEL
7854 ========================================================================
7856 VOID RTMPCheckRates(
7857 IN PRTMP_ADAPTER pAd,
7858 IN OUT UCHAR SupRate[],
7859 IN OUT UCHAR *SupRateLen)
7861 UCHAR RateIdx, i, j;
7862 UCHAR NewRate[12], NewRateLen;
7864 NewRateLen = 0;
7866 if (pAd->CommonCfg.PhyMode == PHY_11B)
7867 RateIdx = 4;
7868 else
7869 RateIdx = 12;
7871 // Check for support rates exclude basic rate bit
7872 for (i = 0; i < *SupRateLen; i++)
7873 for (j = 0; j < RateIdx; j++)
7874 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7875 NewRate[NewRateLen++] = SupRate[i];
7877 *SupRateLen = NewRateLen;
7878 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7881 BOOLEAN RTMPCheckChannel(
7882 IN PRTMP_ADAPTER pAd,
7883 IN UCHAR CentralChannel,
7884 IN UCHAR Channel)
7886 UCHAR k;
7887 UCHAR UpperChannel = 0, LowerChannel = 0;
7888 UCHAR NoEffectChannelinList = 0;
7890 // Find upper and lower channel according to 40MHz current operation.
7891 if (CentralChannel < Channel)
7893 UpperChannel = Channel;
7894 if (CentralChannel > 2)
7895 LowerChannel = CentralChannel - 2;
7896 else
7897 return FALSE;
7899 else if (CentralChannel > Channel)
7901 UpperChannel = CentralChannel + 2;
7902 LowerChannel = Channel;
7905 for (k = 0;k < pAd->ChannelListNum;k++)
7907 if (pAd->ChannelList[k].Channel == UpperChannel)
7909 NoEffectChannelinList ++;
7911 if (pAd->ChannelList[k].Channel == LowerChannel)
7913 NoEffectChannelinList ++;
7917 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7918 if (NoEffectChannelinList == 2)
7919 return TRUE;
7920 else
7921 return FALSE;
7925 ========================================================================
7927 Routine Description:
7928 Verify the support rate for HT phy type
7930 Arguments:
7931 pAd Pointer to our adapter
7933 Return Value:
7934 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7936 IRQL = PASSIVE_LEVEL
7938 ========================================================================
7940 BOOLEAN RTMPCheckHt(
7941 IN PRTMP_ADAPTER pAd,
7942 IN UCHAR Wcid,
7943 IN HT_CAPABILITY_IE *pHtCapability,
7944 IN ADD_HT_INFO_IE *pAddHtInfo)
7946 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7947 return FALSE;
7949 // If use AMSDU, set flag.
7950 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7951 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7952 // Save Peer Capability
7953 if (pHtCapability->HtCapInfo.ShortGIfor20)
7954 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7955 if (pHtCapability->HtCapInfo.ShortGIfor40)
7956 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7957 if (pHtCapability->HtCapInfo.TxSTBC)
7958 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7959 if (pHtCapability->HtCapInfo.RxSTBC)
7960 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7961 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7963 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7966 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7968 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7971 // Will check ChannelWidth for MCSSet[4] below
7972 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7973 switch (pAd->CommonCfg.RxStream)
7975 case 1:
7976 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7977 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7978 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7979 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7980 break;
7981 case 2:
7982 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7983 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7984 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7985 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7986 break;
7987 case 3:
7988 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7989 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7990 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7991 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7992 break;
7995 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7997 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7998 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7999 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
8001 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
8003 // Send Assoc Req with my HT capability.
8004 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
8005 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
8006 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
8007 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
8008 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
8009 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
8010 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
8011 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
8012 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8013 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8014 if (pAd->CommonCfg.bRdg)
8016 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8017 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8020 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8021 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8023 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8024 return TRUE;
8028 ========================================================================
8030 Routine Description:
8031 Verify the support rate for different PHY type
8033 Arguments:
8034 pAd Pointer to our adapter
8036 Return Value:
8037 None
8039 IRQL = PASSIVE_LEVEL
8041 ========================================================================
8043 VOID RTMPUpdateMlmeRate(
8044 IN PRTMP_ADAPTER pAd)
8046 UCHAR MinimumRate;
8047 UCHAR ProperMlmeRate; //= RATE_54;
8048 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8049 BOOLEAN bMatch = FALSE;
8051 switch (pAd->CommonCfg.PhyMode)
8053 case PHY_11B:
8054 ProperMlmeRate = RATE_11;
8055 MinimumRate = RATE_1;
8056 break;
8057 case PHY_11BG_MIXED:
8058 case PHY_11ABGN_MIXED:
8059 case PHY_11BGN_MIXED:
8060 if ((pAd->MlmeAux.SupRateLen == 4) &&
8061 (pAd->MlmeAux.ExtRateLen == 0))
8062 // B only AP
8063 ProperMlmeRate = RATE_11;
8064 else
8065 ProperMlmeRate = RATE_24;
8067 if (pAd->MlmeAux.Channel <= 14)
8068 MinimumRate = RATE_1;
8069 else
8070 MinimumRate = RATE_6;
8071 break;
8072 case PHY_11A:
8073 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8074 case PHY_11GN_MIXED:
8075 case PHY_11AGN_MIXED:
8076 case PHY_11AN_MIXED:
8077 case PHY_11N_5G:
8078 ProperMlmeRate = RATE_24;
8079 MinimumRate = RATE_6;
8080 break;
8081 case PHY_11ABG_MIXED:
8082 ProperMlmeRate = RATE_24;
8083 if (pAd->MlmeAux.Channel <= 14)
8084 MinimumRate = RATE_1;
8085 else
8086 MinimumRate = RATE_6;
8087 break;
8088 default: // error
8089 ProperMlmeRate = RATE_1;
8090 MinimumRate = RATE_1;
8091 break;
8094 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8096 for (j = 0; j < RateIdx; j++)
8098 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8100 if (j == ProperMlmeRate)
8102 bMatch = TRUE;
8103 break;
8108 if (bMatch)
8109 break;
8112 if (bMatch == FALSE)
8114 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8116 for (j = 0; j < RateIdx; j++)
8118 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8120 if (j == ProperMlmeRate)
8122 bMatch = TRUE;
8123 break;
8128 if (bMatch)
8129 break;
8133 if (bMatch == FALSE)
8135 ProperMlmeRate = MinimumRate;
8138 pAd->CommonCfg.MlmeRate = MinimumRate;
8139 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8140 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8142 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8143 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8144 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8145 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8147 else
8149 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8150 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8151 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8152 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8155 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8158 CHAR RTMPMaxRssi(
8159 IN PRTMP_ADAPTER pAd,
8160 IN CHAR Rssi0,
8161 IN CHAR Rssi1,
8162 IN CHAR Rssi2)
8164 CHAR larger = -127;
8166 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8168 larger = Rssi0;
8171 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8173 larger = max(Rssi0, Rssi1);
8176 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8178 larger = max(larger, Rssi2);
8181 if (larger == -127)
8182 larger = 0;
8184 return larger;
8187 #ifdef RT30xx
8188 // Antenna divesity use GPIO3 and EESK pin for control
8189 // Antenna and EEPROM access are both using EESK pin,
8190 // Therefor we should avoid accessing EESK at the same time
8191 // Then restore antenna after EEPROM access
8192 VOID AsicSetRxAnt(
8193 IN PRTMP_ADAPTER pAd,
8194 IN UCHAR Ant)
8196 UINT32 Value;
8197 UINT32 x;
8199 if ((pAd->EepromAccess) ||
8200 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8201 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8202 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8203 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8205 return;
8208 // the antenna selection is through firmware and MAC register(GPIO3)
8209 if (Ant == 0)
8211 // Main antenna
8212 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8213 x |= (EESK);
8214 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8216 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8217 Value &= ~(0x0808);
8218 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8219 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8221 else
8223 // Aux antenna
8224 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8225 x &= ~(EESK);
8226 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8228 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8229 Value &= ~(0x0808);
8230 Value |= 0x08;
8231 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8232 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8235 #endif /* RT30xx */
8238 ========================================================================
8239 Routine Description:
8240 Periodic evaluate antenna link status
8242 Arguments:
8243 pAd - Adapter pointer
8245 Return Value:
8246 None
8248 ========================================================================
8250 VOID AsicEvaluateRxAnt(
8251 IN PRTMP_ADAPTER pAd)
8253 UCHAR BBPR3 = 0;
8255 #ifndef RT30xx
8257 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8258 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8259 fRTMP_ADAPTER_RADIO_OFF |
8260 fRTMP_ADAPTER_NIC_NOT_EXIST |
8261 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8262 return;
8264 if (pAd->StaCfg.Psm == PWR_SAVE)
8265 return;
8268 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8269 BBPR3 &= (~0x18);
8270 if(pAd->Antenna.field.RxPath == 3)
8272 BBPR3 |= (0x10);
8274 else if(pAd->Antenna.field.RxPath == 2)
8276 BBPR3 |= (0x8);
8278 else if(pAd->Antenna.field.RxPath == 1)
8280 BBPR3 |= (0x0);
8282 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8284 #ifdef RT2860
8285 pAd->StaCfg.BBPR3 = BBPR3;
8286 #endif
8287 #endif /* RT30xx */
8288 #ifdef RT30xx
8289 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8290 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8291 fRTMP_ADAPTER_RADIO_OFF |
8292 fRTMP_ADAPTER_NIC_NOT_EXIST |
8293 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
8294 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8295 || (pAd->EepromAccess)
8297 return;
8301 //if (pAd->StaCfg.Psm == PWR_SAVE)
8302 // return;
8305 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8306 // one is antenna diversity:there is only one antenna can rx and tx
8307 // the other is failed antenna remove:two physical antenna can rx and tx
8308 if (pAd->NicConfig2.field.AntDiversity)
8310 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8311 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8313 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8315 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8316 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8317 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8319 // a one-shot timer to end the evalution
8320 // dynamic adjust antenna evaluation period according to the traffic
8321 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8322 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8323 else
8324 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8326 else
8328 if (pAd->StaCfg.Psm == PWR_SAVE)
8329 return;
8331 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8332 BBPR3 &= (~0x18);
8333 if(pAd->Antenna.field.RxPath == 3)
8335 BBPR3 |= (0x10);
8337 else if(pAd->Antenna.field.RxPath == 2)
8339 BBPR3 |= (0x8);
8341 else if(pAd->Antenna.field.RxPath == 1)
8343 BBPR3 |= (0x0);
8345 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8347 #endif /* RT30xx */
8349 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8352 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8353 pAd->RalinkCounters.OneSecTxRetryOkCount +
8354 pAd->RalinkCounters.OneSecTxFailCount;
8356 // dynamic adjust antenna evaluation period according to the traffic
8357 if (TxTotalCnt > 50)
8359 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8360 pAd->Mlme.bLowThroughput = FALSE;
8362 else
8364 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8365 pAd->Mlme.bLowThroughput = TRUE;
8371 ========================================================================
8372 Routine Description:
8373 After evaluation, check antenna link status
8375 Arguments:
8376 pAd - Adapter pointer
8378 Return Value:
8379 None
8381 ========================================================================
8383 VOID AsicRxAntEvalTimeout(
8384 IN PVOID SystemSpecific1,
8385 IN PVOID FunctionContext,
8386 IN PVOID SystemSpecific2,
8387 IN PVOID SystemSpecific3)
8389 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8390 UCHAR BBPR3 = 0;
8391 CHAR larger = -127, rssi0, rssi1, rssi2;
8393 #ifndef RT30xx
8395 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8396 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8397 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8398 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8399 return;
8401 if (pAd->StaCfg.Psm == PWR_SAVE)
8402 return;
8405 // if the traffic is low, use average rssi as the criteria
8406 if (pAd->Mlme.bLowThroughput == TRUE)
8408 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8409 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8410 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8412 else
8414 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8415 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8416 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8419 if(pAd->Antenna.field.RxPath == 3)
8421 larger = max(rssi0, rssi1);
8423 if (larger > (rssi2 + 20))
8424 pAd->Mlme.RealRxPath = 2;
8425 else
8426 pAd->Mlme.RealRxPath = 3;
8428 else if(pAd->Antenna.field.RxPath == 2)
8430 if (rssi0 > (rssi1 + 20))
8431 pAd->Mlme.RealRxPath = 1;
8432 else
8433 pAd->Mlme.RealRxPath = 2;
8436 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8437 BBPR3 &= (~0x18);
8438 if(pAd->Mlme.RealRxPath == 3)
8440 BBPR3 |= (0x10);
8442 else if(pAd->Mlme.RealRxPath == 2)
8444 BBPR3 |= (0x8);
8446 else if(pAd->Mlme.RealRxPath == 1)
8448 BBPR3 |= (0x0);
8450 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8451 #ifdef RT2860
8452 pAd->StaCfg.BBPR3 = BBPR3;
8453 #endif
8455 #endif /* RT30xx */
8456 #ifdef RT30xx
8457 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8458 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8459 fRTMP_ADAPTER_RADIO_OFF |
8460 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8461 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8462 #ifdef RT30xx
8463 || (pAd->EepromAccess)
8464 #endif // RT30xx //
8466 return;
8469 //if (pAd->StaCfg.Psm == PWR_SAVE)
8470 // return;
8472 if (pAd->NicConfig2.field.AntDiversity)
8474 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8476 UCHAR temp;
8479 // select PrimaryRxAntPair
8480 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8481 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8483 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8484 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8485 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8487 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8488 pAd->RxAnt.EvaluateStableCnt = 0;
8490 else
8492 // if the evaluated antenna is not better than original, switch back to original antenna
8493 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8494 pAd->RxAnt.EvaluateStableCnt ++;
8497 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8499 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8500 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8502 else
8504 if (pAd->StaCfg.Psm == PWR_SAVE)
8505 return;
8507 // if the traffic is low, use average rssi as the criteria
8508 if (pAd->Mlme.bLowThroughput == TRUE)
8510 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8511 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8512 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8514 else
8516 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8517 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8518 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8521 if(pAd->Antenna.field.RxPath == 3)
8523 larger = max(rssi0, rssi1);
8525 if (larger > (rssi2 + 20))
8526 pAd->Mlme.RealRxPath = 2;
8527 else
8528 pAd->Mlme.RealRxPath = 3;
8530 else if(pAd->Antenna.field.RxPath == 2)
8532 if (rssi0 > (rssi1 + 20))
8533 pAd->Mlme.RealRxPath = 1;
8534 else
8535 pAd->Mlme.RealRxPath = 2;
8538 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8539 BBPR3 &= (~0x18);
8540 if(pAd->Mlme.RealRxPath == 3)
8542 BBPR3 |= (0x10);
8544 else if(pAd->Mlme.RealRxPath == 2)
8546 BBPR3 |= (0x8);
8548 else if(pAd->Mlme.RealRxPath == 1)
8550 BBPR3 |= (0x0);
8552 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8555 #endif /* RT30xx */
8560 VOID APSDPeriodicExec(
8561 IN PVOID SystemSpecific1,
8562 IN PVOID FunctionContext,
8563 IN PVOID SystemSpecific2,
8564 IN PVOID SystemSpecific3)
8566 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8568 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8569 return;
8571 pAd->CommonCfg.TriggerTimerCount++;
8576 ========================================================================
8577 Routine Description:
8578 Set/reset MAC registers according to bPiggyBack parameter
8580 Arguments:
8581 pAd - Adapter pointer
8582 bPiggyBack - Enable / Disable Piggy-Back
8584 Return Value:
8585 None
8587 ========================================================================
8589 VOID RTMPSetPiggyBack(
8590 IN PRTMP_ADAPTER pAd,
8591 IN BOOLEAN bPiggyBack)
8593 TX_LINK_CFG_STRUC TxLinkCfg;
8595 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8597 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8598 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8602 ========================================================================
8603 Routine Description:
8604 check if this entry need to switch rate automatically
8606 Arguments:
8608 pEntry
8610 Return Value:
8611 TURE
8612 FALSE
8614 ========================================================================
8616 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8617 IN PRTMP_ADAPTER pAd,
8618 IN PMAC_TABLE_ENTRY pEntry)
8620 BOOLEAN result = TRUE;
8623 // only associated STA counts
8624 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8626 result = pAd->StaCfg.bAutoTxRateSwitch;
8628 else
8629 result = FALSE;
8632 return result;
8636 BOOLEAN RTMPAutoRateSwitchCheck(
8637 IN PRTMP_ADAPTER pAd)
8639 if (pAd->StaCfg.bAutoTxRateSwitch)
8640 return TRUE;
8642 return FALSE;
8647 ========================================================================
8648 Routine Description:
8649 check if this entry need to fix tx legacy rate
8651 Arguments:
8653 pEntry
8655 Return Value:
8656 TURE
8657 FALSE
8659 ========================================================================
8661 UCHAR RTMPStaFixedTxMode(
8662 IN PRTMP_ADAPTER pAd,
8663 IN PMAC_TABLE_ENTRY pEntry)
8665 UCHAR tx_mode = FIXED_TXMODE_HT;
8667 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8669 return tx_mode;
8673 ========================================================================
8674 Routine Description:
8675 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8677 Arguments:
8679 pEntry
8681 Return Value:
8682 TURE
8683 FALSE
8685 ========================================================================
8687 VOID RTMPUpdateLegacyTxSetting(
8688 UCHAR fixed_tx_mode,
8689 PMAC_TABLE_ENTRY pEntry)
8691 HTTRANSMIT_SETTING TransmitSetting;
8693 if (fixed_tx_mode == FIXED_TXMODE_HT)
8694 return;
8696 TransmitSetting.word = 0;
8698 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8699 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8701 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8703 TransmitSetting.field.MODE = MODE_CCK;
8704 // CCK mode allow MCS 0~3
8705 if (TransmitSetting.field.MCS > MCS_3)
8706 TransmitSetting.field.MCS = MCS_3;
8708 else
8710 TransmitSetting.field.MODE = MODE_OFDM;
8711 // OFDM mode allow MCS 0~7
8712 if (TransmitSetting.field.MCS > MCS_7)
8713 TransmitSetting.field.MCS = MCS_7;
8716 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8718 pEntry->HTPhyMode.word = TransmitSetting.word;
8719 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8720 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8725 ==========================================================================
8726 Description:
8727 dynamic tune BBP R66 to find a balance between sensibility and
8728 noise isolation
8730 IRQL = DISPATCH_LEVEL
8732 ==========================================================================
8734 VOID AsicStaBbpTuning(
8735 IN PRTMP_ADAPTER pAd)
8737 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8738 CHAR Rssi;
8740 // 2860C did not support Fase CCA, therefore can't tune
8741 if (pAd->MACVersion == 0x28600100)
8742 return;
8745 // work as a STA
8747 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8748 return;
8750 if ((pAd->OpMode == OPMODE_STA)
8751 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8753 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8754 #ifdef RT2860
8755 && (pAd->bPCIclkOff == FALSE))
8756 #endif
8757 #ifdef RT2870
8759 #endif
8761 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8762 R66 = OrigR66Value;
8764 if (pAd->Antenna.field.RxPath > 1)
8765 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8766 else
8767 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8769 if (pAd->LatchRfRegs.Channel <= 14)
8770 { //BG band
8771 #ifdef RT2870
8772 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8773 // Otherwise, it will have some throughput side effect when low RSSI
8774 #ifndef RT30xx
8775 if (IS_RT3070(pAd))
8776 #endif
8777 #ifdef RT30xx
8778 if (IS_RT30xx(pAd))
8779 #endif
8781 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8783 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8784 if (OrigR66Value != R66)
8785 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8787 else
8789 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8790 if (OrigR66Value != R66)
8791 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8794 else
8795 #endif // RT2870 //
8797 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8799 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8800 if (OrigR66Value != R66)
8802 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8805 else
8807 R66 = 0x2E + GET_LNA_GAIN(pAd);
8808 if (OrigR66Value != R66)
8810 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8815 else
8816 { //A band
8817 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8819 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8821 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8822 if (OrigR66Value != R66)
8824 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8827 else
8829 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8830 if (OrigR66Value != R66)
8832 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8836 else
8838 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8840 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8841 if (OrigR66Value != R66)
8843 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8846 else
8848 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8849 if (OrigR66Value != R66)
8851 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8861 #ifdef RT2860
8862 VOID AsicResetFromDMABusy(
8863 IN PRTMP_ADAPTER pAd)
8865 UINT32 Data;
8866 BOOLEAN bCtrl = FALSE;
8868 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8870 // Be sure restore link control value so we can write register.
8871 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8872 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8874 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8875 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8876 RTMPusecDelay(6000);
8877 pAd->bPCIclkOff = FALSE;
8878 bCtrl = TRUE;
8880 // Reset DMA
8881 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8882 Data |= 0x2;
8883 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8885 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8886 // Reset DMA/CPU ring index
8887 RTMPRingCleanUp(pAd, QID_AC_BK);
8888 RTMPRingCleanUp(pAd, QID_AC_BE);
8889 RTMPRingCleanUp(pAd, QID_AC_VI);
8890 RTMPRingCleanUp(pAd, QID_AC_VO);
8891 RTMPRingCleanUp(pAd, QID_HCCA);
8892 RTMPRingCleanUp(pAd, QID_MGMT);
8893 RTMPRingCleanUp(pAd, QID_RX);
8895 // Clear Reset
8896 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8897 Data &= 0xfffffffd;
8898 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8900 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8901 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8902 RTMPPCIeLinkCtrlSetting(pAd, 3);
8904 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8905 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8906 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8909 VOID AsicResetBBP(
8910 IN PRTMP_ADAPTER pAd)
8912 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8914 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8915 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8916 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8918 // After hard-reset BBP, initialize all BBP values.
8919 NICRestoreBBPValue(pAd);
8920 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8923 VOID AsicResetMAC(
8924 IN PRTMP_ADAPTER pAd)
8926 ULONG Data;
8928 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8929 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8930 Data |= 0x4;
8931 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8932 Data &= 0xfffffffb;
8933 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8935 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8938 VOID AsicResetPBF(
8939 IN PRTMP_ADAPTER pAd)
8941 ULONG Value1, Value2;
8942 ULONG Data;
8944 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8945 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8947 Value2 &= 0xff;
8948 // sum should be equals to 0xff, which is the total buffer size.
8949 if ((Value1 + Value2) < 0xff)
8951 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8952 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8953 Data |= 0x8;
8954 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8955 Data &= 0xfffffff7;
8956 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8958 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8961 #endif /* RT2860 */
8963 VOID RTMPSetAGCInitValue(
8964 IN PRTMP_ADAPTER pAd,
8965 IN UCHAR BandWidth)
8967 UCHAR R66 = 0x30;
8969 if (pAd->LatchRfRegs.Channel <= 14)
8970 { // BG band
8971 R66 = 0x2E + GET_LNA_GAIN(pAd);
8972 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8974 else
8975 { //A band
8976 if (BandWidth == BW_20)
8978 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8979 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8981 else
8983 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8984 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8990 VOID AsicTurnOffRFClk(
8991 IN PRTMP_ADAPTER pAd,
8992 IN UCHAR Channel)
8995 // RF R2 bit 18 = 0
8996 UINT32 R1 = 0, R2 = 0, R3 = 0;
8997 UCHAR index;
8998 RTMP_RF_REGS *RFRegTable;
9000 // The RF programming sequence is difference between 3xxx and 2xxx
9001 if (IS_RT3090(pAd))
9003 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
9004 return;
9007 RFRegTable = RF2850RegTable;
9009 switch (pAd->RfIcType)
9011 case RFIC_2820:
9012 case RFIC_2850:
9013 case RFIC_2720:
9014 case RFIC_2750:
9016 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9018 if (Channel == RFRegTable[index].Channel)
9020 R1 = RFRegTable[index].R1 & 0xffffdfff;
9021 R2 = RFRegTable[index].R2 & 0xfffbffff;
9022 R3 = RFRegTable[index].R3 & 0xfff3ffff;
9024 RTMP_RF_IO_WRITE32(pAd, R1);
9025 RTMP_RF_IO_WRITE32(pAd, R2);
9027 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
9028 // Set RF R2 bit18=0, R3 bit[18:19]=0
9029 //if (pAd->StaCfg.bRadio == FALSE)
9030 if (1)
9032 RTMP_RF_IO_WRITE32(pAd, R3);
9034 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
9035 Channel, pAd->RfIcType, R2, R3));
9037 else
9038 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
9039 Channel, pAd->RfIcType, R2));
9040 break;
9043 break;
9045 default:
9046 break;
9051 VOID AsicTurnOnRFClk(
9052 IN PRTMP_ADAPTER pAd,
9053 IN UCHAR Channel)
9056 // RF R2 bit 18 = 0
9057 UINT32 R1 = 0, R2 = 0, R3 = 0;
9058 UCHAR index;
9059 RTMP_RF_REGS *RFRegTable;
9061 // The RF programming sequence is difference between 3xxx and 2xxx
9062 if (IS_RT3090(pAd))
9063 return;
9065 RFRegTable = RF2850RegTable;
9067 switch (pAd->RfIcType)
9069 case RFIC_2820:
9070 case RFIC_2850:
9071 case RFIC_2720:
9072 case RFIC_2750:
9074 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9076 if (Channel == RFRegTable[index].Channel)
9078 R3 = pAd->LatchRfRegs.R3;
9079 R3 &= 0xfff3ffff;
9080 R3 |= 0x00080000;
9081 RTMP_RF_IO_WRITE32(pAd, R3);
9083 R1 = RFRegTable[index].R1;
9084 RTMP_RF_IO_WRITE32(pAd, R1);
9086 R2 = RFRegTable[index].R2;
9087 if (pAd->Antenna.field.TxPath == 1)
9089 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
9092 if (pAd->Antenna.field.RxPath == 2)
9094 R2 |= 0x40; // write 1 to off Rxpath.
9096 else if (pAd->Antenna.field.RxPath == 1)
9098 R2 |= 0x20040; // write 1 to off RxPath
9100 RTMP_RF_IO_WRITE32(pAd, R2);
9102 break;
9105 break;
9107 default:
9108 break;
9111 #ifndef RT30xx
9112 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
9113 Channel,
9114 pAd->RfIcType,
9115 R2));
9116 #endif