Full support for Ginger Console
[linux-ginger.git] / drivers / staging / rt3090 / common / mlme.c
blob1613c04c59325b63e91af3486de2439f4f5063d8
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 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
59 UCHAR RateSwitchTable[] = {
60 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
72 0x0a, 0x21, 6, 8, 25,
73 0x0b, 0x21, 7, 8, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
79 0x11, 0x00, 0, 0, 0,
80 0x12, 0x00, 0, 0, 0,
81 0x13, 0x00, 0, 0, 0,
82 0x14, 0x00, 0, 0, 0,
83 0x15, 0x00, 0, 0, 0,
84 0x16, 0x00, 0, 0, 0,
85 0x17, 0x00, 0, 0, 0,
86 0x18, 0x00, 0, 0, 0,
87 0x19, 0x00, 0, 0, 0,
88 0x1a, 0x00, 0, 0, 0,
89 0x1b, 0x00, 0, 0, 0,
90 0x1c, 0x00, 0, 0, 0,
91 0x1d, 0x00, 0, 0, 0,
92 0x1e, 0x00, 0, 0, 0,
93 0x1f, 0x00, 0, 0, 0,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x0c, 0x0a, 0, 0, 0, // Initial used item after association
137 0x00, 0x00, 0, 40, 101,
138 0x01, 0x00, 1, 40, 50,
139 0x02, 0x00, 2, 25, 45,
140 0x03, 0x21, 0, 20, 35,
141 0x04, 0x21, 1, 20, 35,
142 0x05, 0x21, 2, 20, 35,
143 0x06, 0x21, 3, 15, 35,
144 0x07, 0x21, 4, 15, 30,
145 0x08, 0x21, 5, 10, 25,
146 0x09, 0x21, 6, 8, 14,
147 0x0a, 0x21, 7, 8, 14,
148 0x0b, 0x23, 7, 8, 14,
151 UCHAR RateSwitchTable11N2S[] = {
152 // 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)
153 0x0e, 0x0c, 0, 0, 0, // Initial used item after association
154 0x00, 0x00, 0, 40, 101,
155 0x01, 0x00, 1, 40, 50,
156 0x02, 0x00, 2, 25, 45,
157 0x03, 0x21, 0, 20, 35,
158 0x04, 0x21, 1, 20, 35,
159 0x05, 0x21, 2, 20, 35,
160 0x06, 0x21, 3, 15, 35,
161 0x07, 0x21, 4, 15, 30,
162 0x08, 0x20, 11, 15, 30,
163 0x09, 0x20, 12, 15, 30,
164 0x0a, 0x20, 13, 8, 20,
165 0x0b, 0x20, 14, 8, 20,
166 0x0c, 0x20, 15, 8, 25,
167 0x0d, 0x22, 15, 8, 15,
170 UCHAR RateSwitchTable11N3S[] = {
171 // 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)
172 0x0b, 0x00, 0, 0, 0, // 0x0a, 0x00, 0, 0, 0, // Initial used item after association
173 0x00, 0x21, 0, 30, 101,
174 0x01, 0x21, 1, 20, 50,
175 0x02, 0x21, 2, 20, 50,
176 0x03, 0x21, 3, 15, 50,
177 0x04, 0x21, 4, 15, 30,
178 0x05, 0x20, 11, 15, 30, // Required by System-Alan @ 20080812
179 0x06, 0x20, 12, 15, 30, // 0x05, 0x20, 12, 15, 30,
180 0x07, 0x20, 13, 8, 20, // 0x06, 0x20, 13, 8, 20,
181 0x08, 0x20, 14, 8, 20, // 0x07, 0x20, 14, 8, 20,
182 0x09, 0x20, 15, 8, 25, // 0x08, 0x20, 15, 8, 25,
183 0x0a, 0x22, 15, 8, 25, // 0x09, 0x22, 15, 8, 25,
186 UCHAR RateSwitchTable11N2SForABand[] = {
187 // 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)
188 0x0b, 0x09, 0, 0, 0, // Initial used item after association
189 0x00, 0x21, 0, 30, 101,
190 0x01, 0x21, 1, 20, 50,
191 0x02, 0x21, 2, 20, 50,
192 0x03, 0x21, 3, 15, 50,
193 0x04, 0x21, 4, 15, 30,
194 0x05, 0x21, 5, 15, 30,
195 0x06, 0x20, 12, 15, 30,
196 0x07, 0x20, 13, 8, 20,
197 0x08, 0x20, 14, 8, 20,
198 0x09, 0x20, 15, 8, 25,
199 0x0a, 0x22, 15, 8, 25,
202 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
203 // 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)
204 0x0b, 0x09, 0, 0, 0, // Initial used item after association
205 0x00, 0x21, 0, 30, 101,
206 0x01, 0x21, 1, 20, 50,
207 0x02, 0x21, 2, 20, 50,
208 0x03, 0x21, 3, 15, 50,
209 0x04, 0x21, 4, 15, 30,
210 0x05, 0x21, 5, 15, 30,
211 0x06, 0x20, 12, 15, 30,
212 0x07, 0x20, 13, 8, 20,
213 0x08, 0x20, 14, 8, 20,
214 0x09, 0x20, 15, 8, 25,
215 0x0a, 0x22, 15, 8, 25,
218 UCHAR RateSwitchTable11BGN1S[] = {
219 // 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)
220 0x0c, 0x0a, 0, 0, 0, // Initial used item after association
221 0x00, 0x00, 0, 40, 101,
222 0x01, 0x00, 1, 40, 50,
223 0x02, 0x00, 2, 25, 45,
224 0x03, 0x21, 0, 20, 35,
225 0x04, 0x21, 1, 20, 35,
226 0x05, 0x21, 2, 20, 35,
227 0x06, 0x21, 3, 15, 35,
228 0x07, 0x21, 4, 15, 30,
229 0x08, 0x21, 5, 10, 25,
230 0x09, 0x21, 6, 8, 14,
231 0x0a, 0x21, 7, 8, 14,
232 0x0b, 0x23, 7, 8, 14,
235 UCHAR RateSwitchTable11BGN2S[] = {
236 // 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)
237 0x0e, 0x0c, 0, 0, 0, // Initial used item after association
238 0x00, 0x00, 0, 40, 101,
239 0x01, 0x00, 1, 40, 50,
240 0x02, 0x00, 2, 25, 45,
241 0x03, 0x21, 0, 20, 35,
242 0x04, 0x21, 1, 20, 35,
243 0x05, 0x21, 2, 20, 35,
244 0x06, 0x21, 3, 15, 35,
245 0x07, 0x21, 4, 15, 30,
246 0x08, 0x20, 11, 15, 30,
247 0x09, 0x20, 12, 15, 30,
248 0x0a, 0x20, 13, 8, 20,
249 0x0b, 0x20, 14, 8, 20,
250 0x0c, 0x20, 15, 8, 25,
251 0x0d, 0x22, 15, 8, 15,
254 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
255 // 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)
256 0x0a, 0x00, 0, 0, 0, // Initial used item after association
257 0x00, 0x21, 0, 30,101, //50
258 0x01, 0x21, 1, 20, 50,
259 0x02, 0x21, 2, 20, 50,
260 0x03, 0x21, 3, 20, 50,
261 0x04, 0x21, 4, 15, 50,
262 0x05, 0x20, 20, 15, 30,
263 0x06, 0x20, 21, 8, 20,
264 0x07, 0x20, 22, 8, 20,
265 0x08, 0x20, 23, 8, 25,
266 0x09, 0x22, 23, 8, 25,
269 UCHAR RateSwitchTable11BGN2SForABand[] = {
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 0x0b, 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, 0x20, 12, 15, 30,
279 0x07, 0x20, 13, 8, 20,
280 0x08, 0x20, 14, 8, 20,
281 0x09, 0x20, 15, 8, 25,
282 0x0a, 0x22, 15, 8, 25,
285 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
286 // 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)
287 0x0c, 0x09, 0, 0, 0, // Initial used item after association
288 0x00, 0x21, 0, 30,101, //50
289 0x01, 0x21, 1, 20, 50,
290 0x02, 0x21, 2, 20, 50,
291 0x03, 0x21, 3, 15, 50,
292 0x04, 0x21, 4, 15, 30,
293 0x05, 0x21, 5, 15, 30,
294 0x06, 0x21, 12, 15, 30,
295 0x07, 0x20, 20, 15, 30,
296 0x08, 0x20, 21, 8, 20,
297 0x09, 0x20, 22, 8, 20,
298 0x0a, 0x20, 23, 8, 25,
299 0x0b, 0x22, 23, 8, 25,
301 #endif // DOT11_N_SUPPORT //
304 extern UCHAR OfdmRateToRxwiMCS[];
305 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
306 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
307 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
308 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
309 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
311 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
312 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
314 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
315 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
316 // clean environment.
317 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
318 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
320 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
321 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
323 UCHAR SsidIe = IE_SSID;
324 UCHAR SupRateIe = IE_SUPP_RATES;
325 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
326 #ifdef DOT11_N_SUPPORT
327 UCHAR HtCapIe = IE_HT_CAP;
328 UCHAR AddHtInfoIe = IE_ADD_HT;
329 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
330 #ifdef DOT11N_DRAFT3
331 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
332 #endif // DOT11N_DRAFT3 //
333 #endif // DOT11_N_SUPPORT //
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 UCHAR WapiIe = IE_WAPI;
343 extern UCHAR WPA_OUI[];
345 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
347 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
348 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
352 ==========================================================================
353 Description:
354 initialize the MLME task and its data structure (queue, spinlock,
355 timer, state machines).
357 IRQL = PASSIVE_LEVEL
359 Return:
360 always return NDIS_STATUS_SUCCESS
362 ==========================================================================
364 NDIS_STATUS MlmeInit(
365 IN PRTMP_ADAPTER pAd)
367 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
369 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
373 Status = MlmeQueueInit(&pAd->Mlme.Queue);
374 if(Status != NDIS_STATUS_SUCCESS)
375 break;
377 pAd->Mlme.bRunning = FALSE;
378 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
380 #ifdef CONFIG_STA_SUPPORT
381 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
383 BssTableInit(&pAd->ScanTab);
385 // init STA state machines
386 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
387 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
388 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
389 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
391 #ifdef QOS_DLS_SUPPORT
392 DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
393 #endif // QOS_DLS_SUPPORT //
397 // Since we are using switch/case to implement it, the init is different from the above
398 // state machine init
399 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
401 #endif // CONFIG_STA_SUPPORT //
404 WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, pAd->Mlme.WpaFunc);
407 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
409 // Init mlme periodic timer
410 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
412 // Set mlme periodic timer
413 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
415 // software-based RX Antenna diversity
416 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
419 #ifdef CONFIG_STA_SUPPORT
420 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
422 #ifdef RTMP_PCI_SUPPORT
423 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
425 // only PCIe cards need these two timers
426 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
427 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
429 #endif // RTMP_PCI_SUPPORT //
431 RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer, GET_TIMER_FUNCTION(LinkDownExec), pAd, FALSE);
434 #endif // CONFIG_STA_SUPPORT //
436 } while (FALSE);
438 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
440 return Status;
444 ==========================================================================
445 Description:
446 main loop of the MLME
447 Pre:
448 Mlme has to be initialized, and there are something inside the queue
449 Note:
450 This function is invoked from MPSetInformation and MPReceive;
451 This task guarantee only one MlmeHandler will run.
453 IRQL = DISPATCH_LEVEL
455 ==========================================================================
457 VOID MlmeHandler(
458 IN PRTMP_ADAPTER pAd)
460 MLME_QUEUE_ELEM *Elem = NULL;
461 #ifdef APCLI_SUPPORT
462 SHORT apcliIfIndex;
463 #endif // APCLI_SUPPORT //
465 // Only accept MLME and Frame from peer side, no other (control/data) frame should
466 // get into this state machine
468 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
469 if(pAd->Mlme.bRunning)
471 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
472 return;
474 else
476 pAd->Mlme.bRunning = TRUE;
478 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
480 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
482 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
483 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
484 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
486 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
487 break;
490 #ifdef RALINK_ATE
491 if(ATE_ON(pAd))
493 DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
494 break;
496 #endif // RALINK_ATE //
498 //From message type, determine which state machine I should drive
499 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
502 // if dequeue success
503 switch (Elem->Machine)
505 // STA state machines
506 #ifdef CONFIG_STA_SUPPORT
507 case ASSOC_STATE_MACHINE:
508 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
509 break;
510 case AUTH_STATE_MACHINE:
511 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
512 break;
513 case AUTH_RSP_STATE_MACHINE:
514 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
515 break;
516 case SYNC_STATE_MACHINE:
517 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
518 break;
519 case MLME_CNTL_STATE_MACHINE:
520 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
521 break;
522 case WPA_PSK_STATE_MACHINE:
523 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
524 break;
526 #ifdef QOS_DLS_SUPPORT
527 case DLS_STATE_MACHINE:
528 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
529 break;
530 #endif // QOS_DLS_SUPPORT //
532 #endif // CONFIG_STA_SUPPORT //
534 case ACTION_STATE_MACHINE:
535 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
536 break;
538 case WPA_STATE_MACHINE:
539 StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem);
540 break;
543 default:
544 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
545 break;
546 } // end of switch
548 // free MLME element
549 Elem->Occupied = FALSE;
550 Elem->MsgLen = 0;
553 else {
554 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
558 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
559 pAd->Mlme.bRunning = FALSE;
560 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
564 ==========================================================================
565 Description:
566 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
567 Parameters:
568 Adapter - NIC Adapter pointer
569 Post:
570 The MLME task will no longer work properly
572 IRQL = PASSIVE_LEVEL
574 ==========================================================================
576 VOID MlmeHalt(
577 IN PRTMP_ADAPTER pAd)
579 BOOLEAN Cancelled;
581 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
583 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
585 // disable BEACON generation and other BEACON related hardware timers
586 AsicDisableSync(pAd);
589 #ifdef CONFIG_STA_SUPPORT
590 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
592 #ifdef QOS_DLS_SUPPORT
593 UCHAR i;
594 #endif // QOS_DLS_SUPPORT //
595 // Cancel pending timers
596 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
597 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
598 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
599 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
600 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
601 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
604 #ifdef RTMP_MAC_PCI
605 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
606 &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
608 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
609 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
611 #endif // RTMP_MAC_PCI //
613 #ifdef QOS_DLS_SUPPORT
614 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
616 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
618 #endif // QOS_DLS_SUPPORT //
619 RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
622 #endif // CONFIG_STA_SUPPORT //
624 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
625 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
629 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
631 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
633 // Set LED
634 RTMPSetLED(pAd, LED_HALT);
635 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
637 if (pChipOps->AsicHaltAction)
638 pChipOps->AsicHaltAction(pAd);
641 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
643 MlmeQueueDestroy(&pAd->Mlme.Queue);
644 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
646 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
649 VOID MlmeResetRalinkCounters(
650 IN PRTMP_ADAPTER pAd)
652 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
653 // clear all OneSecxxx counters.
654 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
655 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
656 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
657 pAd->RalinkCounters.OneSecRxOkCnt = 0;
658 pAd->RalinkCounters.OneSecTxFailCount = 0;
659 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
660 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
661 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
662 pAd->RalinkCounters.OneSecReceivedByteCount = 0;
663 pAd->RalinkCounters.OneSecTransmittedByteCount = 0;
665 // TODO: for debug only. to be removed
666 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
667 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
668 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
669 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
670 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
671 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
672 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
673 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
674 pAd->RalinkCounters.OneSecTxDoneCount = 0;
675 pAd->RalinkCounters.OneSecRxCount = 0;
676 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
677 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
679 return;
684 ==========================================================================
685 Description:
686 This routine is executed periodically to -
687 1. Decide if it's a right time to turn on PwrMgmt bit of all
688 outgoiing frames
689 2. Calculate ChannelQuality based on statistics of the last
690 period, so that TX rate won't toggling very frequently between a
691 successful TX and a failed TX.
692 3. If the calculated ChannelQuality indicated current connection not
693 healthy, then a ROAMing attempt is tried here.
695 IRQL = DISPATCH_LEVEL
697 ==========================================================================
699 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
700 VOID MlmePeriodicExec(
701 IN PVOID SystemSpecific1,
702 IN PVOID FunctionContext,
703 IN PVOID SystemSpecific2,
704 IN PVOID SystemSpecific3)
706 ULONG TxTotalCnt;
707 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
708 SHORT realavgrssi;
710 #ifdef CONFIG_STA_SUPPORT
711 #ifdef RTMP_MAC_PCI
712 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
714 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
715 // Move code to here, because following code will return when radio is off
716 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && (pAd->StaCfg.bHardwareRadio == TRUE) &&
717 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
718 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
719 /*&&(pAd->bPCIclkOff == FALSE)*/)
721 UINT32 data = 0;
723 // Read GPIO pin2 as Hardware controlled radio state
724 #ifndef RT3090
725 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
726 #endif // RT3090 //
727 //KH(PCIE PS):Added based on Jane<--
728 #ifdef RT3090
729 // Read GPIO pin2 as Hardware controlled radio state
730 // We need to Read GPIO if HW said so no mater what advance power saving
731 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
732 && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
733 && (pAd->StaCfg.PSControl.field.EnablePSinIdle == TRUE))
735 // Want to make sure device goes to L0 state before reading register.
736 RTMPPCIeLinkCtrlValueRestore(pAd, 0);
737 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
738 RTMPPCIeLinkCtrlSetting(pAd, 3);
740 else
741 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
742 #endif // RT3090 //
743 //KH(PCIE PS):Added based on Jane-->
745 if (data & 0x04)
747 pAd->StaCfg.bHwRadio = TRUE;
749 else
751 pAd->StaCfg.bHwRadio = FALSE;
753 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
755 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
756 if (pAd->StaCfg.bRadio == TRUE)
758 MlmeRadioOn(pAd);
759 // Update extra information
760 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
762 else
764 MlmeRadioOff(pAd);
765 // Update extra information
766 pAd->ExtraInfo = HW_RADIO_OFF;
771 #endif // RTMP_MAC_PCI //
772 #endif // CONFIG_STA_SUPPORT //
774 // Do nothing if the driver is starting halt state.
775 // This might happen when timer already been fired before cancel timer with mlmehalt
776 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
777 fRTMP_ADAPTER_RADIO_OFF |
778 fRTMP_ADAPTER_RADIO_MEASUREMENT |
779 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
780 return;
782 RTMP_MLME_PRE_SANITY_CHECK(pAd);
784 #ifdef RALINK_ATE
785 /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
786 if (ATE_ON(pAd))
788 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
790 pAd->Mlme.PeriodicRound ++;
791 return;
794 #endif // RALINK_ATE //
796 #ifdef CONFIG_STA_SUPPORT
797 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
799 // Do nothing if monitor mode is on
800 if (MONITOR_ON(pAd))
801 return;
803 if (pAd->Mlme.PeriodicRound & 0x1)
805 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
806 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
807 (STA_TGN_WIFI_ON(pAd)) &&
808 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
811 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
812 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
814 else if ((STA_TGN_WIFI_ON(pAd)) &&
815 ((pAd->MACVersion & 0xffff) == 0x0101))
817 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
818 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
822 #endif // CONFIG_STA_SUPPORT //
824 pAd->bUpdateBcnCntDone = FALSE;
826 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
827 pAd->Mlme.PeriodicRound ++;
830 // execute every 500ms
831 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
833 #ifdef CONFIG_STA_SUPPORT
834 // perform dynamic tx rate switching based on past TX history
835 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
837 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
839 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
840 MlmeDynamicTxRateSwitching(pAd);
842 #endif // CONFIG_STA_SUPPORT //
845 // Normal 1 second Mlme PeriodicExec.
846 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
848 pAd->Mlme.OneSecPeriodicRound ++;
850 #ifdef RALINK_ATE
851 if (ATE_ON(pAd))
853 /* request from Baron : move this routine from later to here */
854 /* for showing Rx error count in ATE RXFRAME */
855 NICUpdateRawCounters(pAd);
856 if (pAd->ate.bRxFER == 1)
858 pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
859 ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
860 pAd->ate.RxCntPerSec = 0;
862 if (pAd->ate.RxAntennaSel == 0)
863 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
864 pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
865 else
866 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
868 MlmeResetRalinkCounters(pAd);
872 return;
874 #endif // RALINK_ATE //
878 //ORIBATimerTimeout(pAd);
880 // Media status changed, report to NDIS
881 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
883 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
884 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
886 pAd->IndicateMediaState = NdisMediaStateConnected;
887 RTMP_IndicateMediaState(pAd);
889 else
891 pAd->IndicateMediaState = NdisMediaStateDisconnected;
892 RTMP_IndicateMediaState(pAd);
896 NdisGetSystemUpTime(&pAd->Mlme.Now32);
898 // add the most up-to-date h/w raw counters into software variable, so that
899 // the dynamic tuning mechanism below are based on most up-to-date information
900 NICUpdateRawCounters(pAd);
903 #ifdef DOT11_N_SUPPORT
904 // Need statistics after read counter. So put after NICUpdateRawCounters
905 ORIBATimerTimeout(pAd);
906 #endif // DOT11_N_SUPPORT //
908 // if MGMT RING is full more than twice within 1 second, we consider there's
909 // a hardware problem stucking the TX path. In this case, try a hardware reset
910 // to recover the system
911 // if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
912 // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
913 // else
914 // pAd->RalinkCounters.MgmtRingFullCount = 0;
916 // The time period for checking antenna is according to traffic
917 #ifdef ANT_DIVERSITY_SUPPORT
918 if ((pAd->NicConfig2.field.AntDiversity) &&
919 (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_ENABLE) &&
920 (!pAd->EepromAccess))
921 AsicAntennaSelect(pAd, pAd->MlmeAux.Channel);
922 else if(pAd->CommonCfg.bRxAntDiversity == ANT_FIX_ANT1 || pAd->CommonCfg.bRxAntDiversity == ANT_FIX_ANT2)
924 #ifdef CONFIG_STA_SUPPORT
925 realavgrssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
926 #endif // CONFIG_STA_SUPPORT //
927 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
929 else
930 #endif // ANT_DIVERSITY_SUPPORT //
932 if (pAd->Mlme.bEnableAutoAntennaCheck)
934 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
935 pAd->RalinkCounters.OneSecTxRetryOkCount +
936 pAd->RalinkCounters.OneSecTxFailCount;
938 // dynamic adjust antenna evaluation period according to the traffic
939 if (TxTotalCnt > 50)
941 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
943 AsicEvaluateRxAnt(pAd);
946 else
948 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
950 AsicEvaluateRxAnt(pAd);
956 #ifdef CONFIG_STA_SUPPORT
957 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
958 STAMlmePeriodicExec(pAd);
959 #endif // CONFIG_STA_SUPPORT //
961 MlmeResetRalinkCounters(pAd);
963 #ifdef CONFIG_STA_SUPPORT
964 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
966 #ifdef RTMP_MAC_PCI
967 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
968 #endif // RTMP_MAC_PCI //
970 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
971 // and sending CTS-to-self over and over.
972 // Software Patch Solution:
973 // 1. Polling debug state register 0x10F4 every one second.
974 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
975 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
977 UINT32 MacReg = 0;
979 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
980 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
982 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
983 RTMPusecDelay(1);
984 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
986 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
990 #endif // CONFIG_STA_SUPPORT //
992 RTMP_MLME_HANDLER(pAd);
996 pAd->bUpdateBcnCntDone = FALSE;
1001 ==========================================================================
1002 Validate SSID for connection try and rescan purpose
1003 Valid SSID will have visible chars only.
1004 The valid length is from 0 to 32.
1005 IRQL = DISPATCH_LEVEL
1006 ==========================================================================
1008 BOOLEAN MlmeValidateSSID(
1009 IN PUCHAR pSsid,
1010 IN UCHAR SsidLen)
1012 int index;
1014 if (SsidLen > MAX_LEN_OF_SSID)
1015 return (FALSE);
1017 // Check each character value
1018 for (index = 0; index < SsidLen; index++)
1020 if (pSsid[index] < 0x20)
1021 return (FALSE);
1024 // All checked
1025 return (TRUE);
1028 VOID MlmeSelectTxRateTable(
1029 IN PRTMP_ADAPTER pAd,
1030 IN PMAC_TABLE_ENTRY pEntry,
1031 IN PUCHAR *ppTable,
1032 IN PUCHAR pTableSize,
1033 IN PUCHAR pInitTxRateIdx)
1037 // decide the rate table for tuning
1038 if (pAd->CommonCfg.TxRateTableSize > 0)
1040 *ppTable = RateSwitchTable;
1041 *pTableSize = RateSwitchTable[0];
1042 *pInitTxRateIdx = RateSwitchTable[1];
1044 break;
1047 #ifdef CONFIG_STA_SUPPORT
1048 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1050 #ifdef DOT11_N_SUPPORT
1051 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1052 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1053 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1054 {// 11N 1S Adhoc
1055 *ppTable = RateSwitchTable11N1S;
1056 *pTableSize = RateSwitchTable11N1S[0];
1057 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1060 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1061 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1062 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1063 (pAd->Antenna.field.TxPath == 2))
1064 {// 11N 2S Adhoc
1065 if (pAd->LatchRfRegs.Channel <= 14)
1067 *ppTable = RateSwitchTable11N2S;
1068 *pTableSize = RateSwitchTable11N2S[0];
1069 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1071 else
1073 *ppTable = RateSwitchTable11N2SForABand;
1074 *pTableSize = RateSwitchTable11N2SForABand[0];
1075 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1079 else
1080 #endif // DOT11_N_SUPPORT //
1081 if ((pEntry->RateLen == 4)
1082 #ifdef DOT11_N_SUPPORT
1083 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1084 #endif // DOT11_N_SUPPORT //
1087 *ppTable = RateSwitchTable11B;
1088 *pTableSize = RateSwitchTable11B[0];
1089 *pInitTxRateIdx = RateSwitchTable11B[1];
1092 else if (pAd->LatchRfRegs.Channel <= 14)
1094 *ppTable = RateSwitchTable11BG;
1095 *pTableSize = RateSwitchTable11BG[0];
1096 *pInitTxRateIdx = RateSwitchTable11BG[1];
1099 else
1101 *ppTable = RateSwitchTable11G;
1102 *pTableSize = RateSwitchTable11G[0];
1103 *pInitTxRateIdx = RateSwitchTable11G[1];
1106 break;
1108 #endif // CONFIG_STA_SUPPORT //
1110 #ifdef DOT11_N_SUPPORT
1111 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1112 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1113 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1114 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1115 {// 11BGN 1S AP
1116 *ppTable = RateSwitchTable11BGN1S;
1117 *pTableSize = RateSwitchTable11BGN1S[0];
1118 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1120 break;
1123 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1124 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1125 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1126 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1127 {// 11BGN 2S AP
1128 if (pAd->LatchRfRegs.Channel <= 14)
1130 *ppTable = RateSwitchTable11BGN2S;
1131 *pTableSize = RateSwitchTable11BGN2S[0];
1132 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1135 else
1137 *ppTable = RateSwitchTable11BGN2SForABand;
1138 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1139 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1142 break;
1145 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1146 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1147 {// 11N 1S AP
1148 *ppTable = RateSwitchTable11N1S;
1149 *pTableSize = RateSwitchTable11N1S[0];
1150 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1152 break;
1155 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1156 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1157 {// 11N 2S AP
1158 if (pAd->LatchRfRegs.Channel <= 14)
1160 *ppTable = RateSwitchTable11N2S;
1161 *pTableSize = RateSwitchTable11N2S[0];
1162 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1164 else
1166 *ppTable = RateSwitchTable11N2SForABand;
1167 *pTableSize = RateSwitchTable11N2SForABand[0];
1168 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1171 break;
1173 #endif // DOT11_N_SUPPORT //
1174 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1175 if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode==PHY_11B)
1176 #ifdef DOT11_N_SUPPORT
1177 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1178 /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)*/
1179 #endif // DOT11_N_SUPPORT //
1181 {// B only AP
1182 *ppTable = RateSwitchTable11B;
1183 *pTableSize = RateSwitchTable11B[0];
1184 *pInitTxRateIdx = RateSwitchTable11B[1];
1186 break;
1189 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1190 if ((pEntry->RateLen > 8)
1191 #ifdef DOT11_N_SUPPORT
1192 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1193 #endif // DOT11_N_SUPPORT //
1195 {// B/G mixed AP
1196 *ppTable = RateSwitchTable11BG;
1197 *pTableSize = RateSwitchTable11BG[0];
1198 *pInitTxRateIdx = RateSwitchTable11BG[1];
1200 break;
1203 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1204 if ((pEntry->RateLen == 8)
1205 #ifdef DOT11_N_SUPPORT
1206 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1207 #endif // DOT11_N_SUPPORT //
1209 {// G only AP
1210 *ppTable = RateSwitchTable11G;
1211 *pTableSize = RateSwitchTable11G[0];
1212 *pInitTxRateIdx = RateSwitchTable11G[1];
1214 break;
1216 #ifdef DOT11_N_SUPPORT
1217 #endif // DOT11_N_SUPPORT //
1219 #ifdef CONFIG_STA_SUPPORT
1220 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1222 #ifdef DOT11_N_SUPPORT
1223 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1224 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1225 #endif // DOT11_N_SUPPORT //
1226 { // Legacy mode
1227 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1229 *ppTable = RateSwitchTable11B;
1230 *pTableSize = RateSwitchTable11B[0];
1231 *pInitTxRateIdx = RateSwitchTable11B[1];
1233 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1235 *ppTable = RateSwitchTable11G;
1236 *pTableSize = RateSwitchTable11G[0];
1237 *pInitTxRateIdx = RateSwitchTable11G[1];
1240 else
1242 *ppTable = RateSwitchTable11BG;
1243 *pTableSize = RateSwitchTable11BG[0];
1244 *pInitTxRateIdx = RateSwitchTable11BG[1];
1246 break;
1248 #ifdef DOT11_N_SUPPORT
1249 if (pAd->LatchRfRegs.Channel <= 14)
1251 if (pAd->CommonCfg.TxStream == 1)
1253 *ppTable = RateSwitchTable11N1S;
1254 *pTableSize = RateSwitchTable11N1S[0];
1255 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1256 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1258 else
1260 *ppTable = RateSwitchTable11N2S;
1261 *pTableSize = RateSwitchTable11N2S[0];
1262 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1263 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1266 else
1268 if (pAd->CommonCfg.TxStream == 1)
1270 *ppTable = RateSwitchTable11N1S;
1271 *pTableSize = RateSwitchTable11N1S[0];
1272 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1273 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1275 else
1277 *ppTable = RateSwitchTable11N2SForABand;
1278 *pTableSize = RateSwitchTable11N2SForABand[0];
1279 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1280 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1283 #endif // DOT11_N_SUPPORT //
1284 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1285 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1287 #endif // CONFIG_STA_SUPPORT //
1288 } while(FALSE);
1292 #ifdef CONFIG_STA_SUPPORT
1293 VOID STAMlmePeriodicExec(
1294 PRTMP_ADAPTER pAd)
1296 ULONG TxTotalCnt;
1297 int i;
1303 We return here in ATE mode, because the statistics
1304 that ATE need are not collected via this routine.
1306 #ifdef RALINK_ATE
1307 if (ATE_ON(pAd))
1308 return;
1309 #endif // RALINK_ATE //
1311 #ifdef RALINK_ATE
1312 // It is supposed that we will never reach here in ATE mode.
1313 ASSERT(!(ATE_ON(pAd)));
1314 if (ATE_ON(pAd))
1315 return;
1316 #endif // RALINK_ATE //
1318 #ifdef PCIE_PS_SUPPORT
1319 // don't perform idle-power-save mechanism within 3 min after driver initialization.
1320 // This can make rebooter test more robust
1321 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1323 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
1324 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1325 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1326 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1328 if (IS_RT3090(pAd)|| IS_RT3572(pAd) || IS_RT3390(pAd))
1330 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1332 DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__));
1334 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1336 else
1338 DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__));
1339 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x2);
1340 // Wait command success
1341 AsicCheckCommanOk(pAd, PowerSafeCID);
1342 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1343 DBGPRINT(RT_DEBUG_TRACE, ("PSM - rt30xx Issue Sleep command)\n"));
1346 else if (pAd->Mlme.OneSecPeriodicRound > 180)
1348 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1350 DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__));
1351 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1353 else
1355 DBGPRINT(RT_DEBUG_TRACE, ("%s::%d\n",__FUNCTION__,__LINE__));
1356 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x02);
1357 // Wait command success
1358 AsicCheckCommanOk(pAd, PowerSafeCID);
1359 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1360 DBGPRINT(RT_DEBUG_TRACE, ("PSM - rt28xx Issue Sleep command)\n"));
1364 else
1366 DBGPRINT(RT_DEBUG_TRACE,("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1367 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid[0], pAd->CommonCfg.Ssid[1], pAd->CommonCfg.Ssid[2], pAd->CommonCfg.Ssid[3],
1368 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1], pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
1371 #endif // PCIE_PS_SUPPORT //
1374 #ifdef WPA_SUPPLICANT_SUPPORT
1375 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1376 #endif // WPA_SUPPLICANT_SUPPORT //
1378 // WPA MIC error should block association attempt for 60 seconds
1379 if (pAd->StaCfg.bBlockAssoc &&
1380 RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastMicErrorTime + (60*OS_HZ)))
1381 pAd->StaCfg.bBlockAssoc = FALSE;
1384 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1386 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1388 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1390 pAd->PreMediaState = pAd->IndicateMediaState;
1396 if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd))
1399 else
1401 AsicStaBbpTuning(pAd);
1404 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1405 pAd->RalinkCounters.OneSecTxRetryOkCount +
1406 pAd->RalinkCounters.OneSecTxFailCount;
1408 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1410 // update channel quality for Roaming and UI LinkQuality display
1411 MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32);
1414 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1415 // Radio is currently in noisy environment
1416 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1417 AsicAdjustTxPower(pAd);
1419 if (INFRA_ON(pAd))
1421 #ifdef QOS_DLS_SUPPORT
1422 // Check DLS time out, then tear down those session
1423 RTMPCheckDLSTimeOut(pAd);
1424 #endif // QOS_DLS_SUPPORT //
1426 // Is PSM bit consistent with user power management policy?
1427 // This is the only place that will set PSM bit ON.
1428 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1429 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1431 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1433 if ((RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (1*OS_HZ))) &&
1434 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1435 (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < 600)))
1437 RTMPSetAGCInitValue(pAd, BW_20);
1438 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1441 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1442 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1444 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1446 // When APSD is enabled, the period changes as 20 sec
1447 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1448 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1450 else
1452 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1453 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1455 if (pAd->CommonCfg.bWmmCapable)
1456 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1457 else
1458 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1463 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1465 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1467 // Lost AP, send disconnect & link down event
1468 LinkDown(pAd, FALSE);
1470 #ifdef WPA_SUPPLICANT_SUPPORT
1471 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1472 //send disassociate event to wpa_supplicant
1473 if (pAd->StaCfg.WpaSupplicantUP) {
1474 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0);
1476 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1477 #endif // WPA_SUPPLICANT_SUPPORT //
1479 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1480 RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0);
1481 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1483 // RTMPPatchMacBbpBug(pAd);
1484 MlmeAutoReconnectLastSSID(pAd);
1486 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1488 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1489 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1490 MlmeAutoReconnectLastSSID(pAd);
1493 if (pAd->StaCfg.bAutoRoaming)
1495 BOOLEAN rv = FALSE;
1496 CHAR dBmToRoam = pAd->StaCfg.dBmToRoam;
1497 CHAR MaxRssi = RTMPMaxRssi(pAd,
1498 pAd->StaCfg.RssiSample.LastRssi0,
1499 pAd->StaCfg.RssiSample.LastRssi1,
1500 pAd->StaCfg.RssiSample.LastRssi2);
1502 // Scanning, ignore Roaming
1503 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) &&
1504 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1505 (MaxRssi <= dBmToRoam))
1507 DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", MaxRssi, (CHAR)dBmToRoam));
1510 // Add auto seamless roaming
1511 if (rv == FALSE)
1512 rv = MlmeCheckForFastRoaming(pAd);
1514 if (rv == FALSE)
1516 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1518 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1519 pAd->StaCfg.ScanCnt = 2;
1520 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1521 MlmeAutoScan(pAd);
1527 else if (ADHOC_ON(pAd))
1530 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1531 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1532 // join later.
1533 if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME) &&
1534 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1536 MLME_START_REQ_STRUCT StartReq;
1538 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1539 LinkDown(pAd, FALSE);
1541 StartParmFill(pAd, &StartReq, (CHAR *)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1542 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1543 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1546 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1548 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1550 if (pEntry->ValidAsCLI == FALSE)
1551 continue;
1553 if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1554 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1557 else // no INFRA nor ADHOC connection
1560 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1561 RTMP_TIME_BEFORE(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
1562 goto SKIP_AUTO_SCAN_CONN;
1563 else
1564 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1566 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1567 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1568 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1570 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1572 MLME_SCAN_REQ_STRUCT ScanReq;
1574 if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (10 * OS_HZ)))
1576 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1577 ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1578 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1579 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1580 // Reset Missed scan number
1581 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1583 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1584 MlmeAutoReconnectLastSSID(pAd);
1586 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1588 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1590 MlmeAutoScan(pAd);
1591 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1593 else
1595 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1596 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1598 if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
1599 MlmeAutoReconnectLastSSID(pAd);
1601 else
1602 #endif // CARRIER_DETECTION_SUPPORT //
1603 MlmeAutoReconnectLastSSID(pAd);
1609 SKIP_AUTO_SCAN_CONN:
1611 #ifdef DOT11_N_SUPPORT
1612 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1614 pAd->MacTab.fAnyBASession = TRUE;
1615 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1617 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1619 pAd->MacTab.fAnyBASession = FALSE;
1620 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1622 #endif // DOT11_N_SUPPORT //
1625 #ifdef DOT11_N_SUPPORT
1626 #ifdef DOT11N_DRAFT3
1627 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1628 TriEventCounterMaintenance(pAd);
1629 #endif // DOT11N_DRAFT3 //
1630 #endif // DOT11_N_SUPPORT //
1632 return;
1635 // Link down report
1636 VOID LinkDownExec(
1637 IN PVOID SystemSpecific1,
1638 IN PVOID FunctionContext,
1639 IN PVOID SystemSpecific2,
1640 IN PVOID SystemSpecific3)
1642 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1644 if (pAd != NULL)
1646 MLME_DISASSOC_REQ_STRUCT DisassocReq;
1648 if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
1649 (INFRA_ON(pAd)))
1651 DBGPRINT(RT_DEBUG_TRACE, ("LinkDownExec(): disassociate with current AP...\n"));
1652 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
1653 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
1654 sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
1655 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1657 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1658 RTMP_IndicateMediaState(pAd);
1659 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1664 // IRQL = DISPATCH_LEVEL
1665 VOID MlmeAutoScan(
1666 IN PRTMP_ADAPTER pAd)
1668 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1669 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1671 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1672 MlmeEnqueue(pAd,
1673 MLME_CNTL_STATE_MACHINE,
1674 OID_802_11_BSSID_LIST_SCAN,
1675 pAd->MlmeAux.AutoReconnectSsidLen,
1676 pAd->MlmeAux.AutoReconnectSsid);
1677 RTMP_MLME_HANDLER(pAd);
1681 // IRQL = DISPATCH_LEVEL
1682 VOID MlmeAutoReconnectLastSSID(
1683 IN PRTMP_ADAPTER pAd)
1685 if (pAd->StaCfg.bAutoConnectByBssid)
1687 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n",
1688 pAd->MlmeAux.Bssid[0],
1689 pAd->MlmeAux.Bssid[1],
1690 pAd->MlmeAux.Bssid[2],
1691 pAd->MlmeAux.Bssid[3],
1692 pAd->MlmeAux.Bssid[4],
1693 pAd->MlmeAux.Bssid[5]));
1695 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1696 MlmeEnqueue(pAd,
1697 MLME_CNTL_STATE_MACHINE,
1698 OID_802_11_BSSID,
1699 MAC_ADDR_LEN,
1700 pAd->MlmeAux.Bssid);
1702 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1704 RTMP_MLME_HANDLER(pAd);
1706 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1707 else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1708 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1710 NDIS_802_11_SSID OidSsid;
1711 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1712 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1714 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1715 MlmeEnqueue(pAd,
1716 MLME_CNTL_STATE_MACHINE,
1717 OID_802_11_SSID,
1718 sizeof(NDIS_802_11_SSID),
1719 &OidSsid);
1720 RTMP_MLME_HANDLER(pAd);
1726 ==========================================================================
1727 Description:
1728 This routine checks if there're other APs out there capable for
1729 roaming. Caller should call this routine only when Link up in INFRA mode
1730 and channel quality is below CQI_GOOD_THRESHOLD.
1732 IRQL = DISPATCH_LEVEL
1734 Output:
1735 ==========================================================================
1737 VOID MlmeCheckForRoaming(
1738 IN PRTMP_ADAPTER pAd,
1739 IN ULONG Now32)
1741 USHORT i;
1742 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1743 BSS_ENTRY *pBss;
1745 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1746 // put all roaming candidates into RoamTab, and sort in RSSI order
1747 BssTableInit(pRoamTab);
1748 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1750 pBss = &pAd->ScanTab.BssEntry[i];
1752 if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) < Now32)
1753 continue; // AP disappear
1754 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1755 continue; // RSSI too weak. forget it.
1756 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1757 continue; // skip current AP
1758 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1759 continue; // only AP with stronger RSSI is eligible for roaming
1761 // AP passing all above rules is put into roaming candidate table
1762 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1763 pRoamTab->BssNr += 1;
1766 if (pRoamTab->BssNr > 0)
1768 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1769 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1771 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1772 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1773 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1774 RTMP_MLME_HANDLER(pAd);
1777 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1781 ==========================================================================
1782 Description:
1783 This routine checks if there're other APs out there capable for
1784 roaming. Caller should call this routine only when link up in INFRA mode
1785 and channel quality is below CQI_GOOD_THRESHOLD.
1787 IRQL = DISPATCH_LEVEL
1789 Output:
1790 ==========================================================================
1792 BOOLEAN MlmeCheckForFastRoaming(
1793 IN PRTMP_ADAPTER pAd)
1795 USHORT i;
1796 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1797 BSS_ENTRY *pBss;
1799 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1800 // put all roaming candidates into RoamTab, and sort in RSSI order
1801 BssTableInit(pRoamTab);
1802 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1804 pBss = &pAd->ScanTab.BssEntry[i];
1806 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1807 continue; // RSSI too weak. forget it.
1808 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1809 continue; // skip current AP
1810 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1811 continue; // skip different SSID
1812 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1813 continue; // skip AP without better RSSI
1815 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));
1816 // AP passing all above rules is put into roaming candidate table
1817 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1818 pRoamTab->BssNr += 1;
1821 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1822 if (pRoamTab->BssNr > 0)
1824 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1825 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1827 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1828 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1829 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1830 RTMP_MLME_HANDLER(pAd);
1831 return TRUE;
1835 return FALSE;
1838 VOID MlmeSetTxRate(
1839 IN PRTMP_ADAPTER pAd,
1840 IN PMAC_TABLE_ENTRY pEntry,
1841 IN PRTMP_TX_RATE_SWITCH pTxRate)
1843 UCHAR MaxMode = MODE_OFDM;
1845 #ifdef DOT11_N_SUPPORT
1846 MaxMode = MODE_HTGREENFIELD;
1848 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1849 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1850 else
1851 #endif // DOT11_N_SUPPORT //
1852 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1854 if (pTxRate->CurrMCS < MCS_AUTO)
1855 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1857 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1858 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1860 if (ADHOC_ON(pAd))
1862 // If peer adhoc is b-only mode, we can't send 11g rate.
1863 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1864 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1867 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1869 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1870 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1871 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1873 // Patch speed error in status page
1874 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1876 else
1878 if (pTxRate->Mode <= MaxMode)
1879 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1881 #ifdef DOT11_N_SUPPORT
1882 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1883 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1884 else
1885 #endif // DOT11_N_SUPPORT //
1886 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1888 #ifdef DOT11_N_SUPPORT
1889 // Reexam each bandwidth's SGI support.
1890 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1892 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1893 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1894 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1895 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1898 // Turn RTS/CTS rate to 6Mbps.
1899 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1901 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1902 if (pAd->MacTab.fAnyBASession)
1904 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1906 else
1908 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1911 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1913 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1914 if (pAd->MacTab.fAnyBASession)
1916 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1918 else
1920 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1923 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1925 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1928 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1930 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1932 #endif // DOT11_N_SUPPORT //
1934 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1935 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1936 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1937 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1938 #ifdef DOT11_N_SUPPORT
1939 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1940 pAd->WIFItestbed.bGreenField)
1941 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1942 #endif // DOT11_N_SUPPORT //
1945 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1949 ==========================================================================
1950 Description:
1951 This routine calculates the acumulated TxPER of eaxh TxRate. And
1952 according to the calculation result, change CommonCfg.TxRate which
1953 is the stable TX Rate we expect the Radio situation could sustained.
1955 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1956 Output:
1957 CommonCfg.TxRate -
1959 IRQL = DISPATCH_LEVEL
1961 NOTE:
1962 call this routine every second
1963 ==========================================================================
1965 VOID MlmeDynamicTxRateSwitching(
1966 IN PRTMP_ADAPTER pAd)
1968 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1969 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1970 ULONG TxErrorRatio = 0;
1971 BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
1972 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1973 PUCHAR pTable;
1974 UCHAR TableSize = 0;
1975 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1976 CHAR Rssi, RssiOffset = 0;
1977 TX_STA_CNT1_STRUC StaTx1;
1978 TX_STA_CNT0_STRUC TxStaCnt0;
1979 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1980 MAC_TABLE_ENTRY *pEntry;
1981 RSSI_SAMPLE *pRssi = &pAd->StaCfg.RssiSample;
1983 #ifdef RALINK_ATE
1984 if (ATE_ON(pAd))
1986 return;
1988 #endif // RALINK_ATE //
1991 // walk through MAC table, see if need to change AP's TX rate toward each entry
1993 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1995 pEntry = &pAd->MacTab.Content[i];
1997 // check if this entry need to switch rate automatically
1998 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1999 continue;
2001 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2003 Rssi = RTMPMaxRssi(pAd,
2004 pRssi->AvgRssi0,
2005 pRssi->AvgRssi1,
2006 pRssi->AvgRssi2);
2008 // Update statistic counter
2009 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2010 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2011 pAd->bUpdateBcnCntDone = TRUE;
2012 TxRetransmit = StaTx1.field.TxRetransmit;
2013 TxSuccess = StaTx1.field.TxSuccess;
2014 TxFailCount = TxStaCnt0.field.TxFailCount;
2015 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2017 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2018 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2019 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2020 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2021 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2022 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2024 // if no traffic in the past 1-sec period, don't change TX rate,
2025 // but clear all bad history. because the bad history may affect the next
2026 // Chariot throughput test
2027 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2028 pAd->RalinkCounters.OneSecTxRetryOkCount +
2029 pAd->RalinkCounters.OneSecTxFailCount;
2031 if (TxTotalCnt)
2032 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2034 else
2036 if (INFRA_ON(pAd) && (i == 1))
2037 Rssi = RTMPMaxRssi(pAd,
2038 pRssi->AvgRssi0,
2039 pRssi->AvgRssi1,
2040 pRssi->AvgRssi2);
2041 else
2042 Rssi = RTMPMaxRssi(pAd,
2043 pEntry->RssiSample.AvgRssi0,
2044 pEntry->RssiSample.AvgRssi1,
2045 pEntry->RssiSample.AvgRssi2);
2047 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2048 pEntry->OneSecTxRetryOkCount +
2049 pEntry->OneSecTxFailCount;
2051 if (TxTotalCnt)
2052 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2055 if (TxTotalCnt)
2058 Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
2059 We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
2061 if (TxErrorRatio == 100)
2063 TX_RTY_CFG_STRUC TxRtyCfg,TxRtyCfgtmp;
2064 ULONG Index;
2065 ULONG MACValue;
2067 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
2068 TxRtyCfgtmp.word = TxRtyCfg.word;
2069 TxRtyCfg.field.LongRtyLimit = 0x0;
2070 TxRtyCfg.field.ShortRtyLimit = 0x0;
2071 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
2073 RTMPusecDelay(1);
2075 Index = 0;
2076 MACValue = 0;
2079 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
2080 if ((MACValue & 0xffffff) == 0)
2081 break;
2082 Index++;
2083 RTMPusecDelay(1000);
2084 }while((Index < 330)&&(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)));
2086 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
2087 TxRtyCfg.field.LongRtyLimit = TxRtyCfgtmp.field.LongRtyLimit;
2088 TxRtyCfg.field.ShortRtyLimit = TxRtyCfgtmp.field.ShortRtyLimit;
2089 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
2093 CurrRateIdx = pEntry->CurrTxRateIndex;
2095 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2097 if (CurrRateIdx >= TableSize)
2099 CurrRateIdx = TableSize - 1;
2102 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2103 // So need to sync here.
2104 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2105 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2106 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2110 // Need to sync Real Tx rate and our record.
2111 // Then return for next DRS.
2112 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2113 pEntry->CurrTxRateIndex = InitTxRateIdx;
2114 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2116 // reset all OneSecTx counters
2117 RESET_ONE_SEC_TX_CNT(pEntry);
2118 continue;
2121 // decide the next upgrade rate and downgrade rate, if any
2122 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2124 UpRateIdx = CurrRateIdx + 1;
2125 DownRateIdx = CurrRateIdx -1;
2127 else if (CurrRateIdx == 0)
2129 UpRateIdx = CurrRateIdx + 1;
2130 DownRateIdx = CurrRateIdx;
2132 else if (CurrRateIdx == (TableSize - 1))
2134 UpRateIdx = CurrRateIdx;
2135 DownRateIdx = CurrRateIdx - 1;
2138 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2140 #ifdef DOT11_N_SUPPORT
2141 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2143 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2144 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2146 else
2147 #endif // DOT11_N_SUPPORT //
2149 TrainUp = pCurrTxRate->TrainUp;
2150 TrainDown = pCurrTxRate->TrainDown;
2153 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2156 // Keep the last time TxRateChangeAction status.
2158 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2163 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2164 // (criteria copied from RT2500 for Netopia case)
2166 if (TxTotalCnt <= 15)
2168 CHAR idx = 0;
2169 UCHAR TxRateIdx;
2170 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2171 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2172 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2174 // check the existence and index of each needed MCS
2175 while (idx < pTable[0])
2177 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2179 if (pCurrTxRate->CurrMCS == MCS_0)
2181 MCS0 = idx;
2183 else if (pCurrTxRate->CurrMCS == MCS_1)
2185 MCS1 = idx;
2187 else if (pCurrTxRate->CurrMCS == MCS_2)
2189 MCS2 = idx;
2191 else if (pCurrTxRate->CurrMCS == MCS_3)
2193 MCS3 = idx;
2195 else if (pCurrTxRate->CurrMCS == MCS_4)
2197 MCS4 = idx;
2199 else if (pCurrTxRate->CurrMCS == MCS_5)
2201 MCS5 = idx;
2203 else if (pCurrTxRate->CurrMCS == MCS_6)
2205 MCS6 = idx;
2207 //else if (pCurrTxRate->CurrMCS == MCS_7)
2208 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2210 MCS7 = idx;
2212 else if (pCurrTxRate->CurrMCS == MCS_12)
2214 MCS12 = idx;
2216 else if (pCurrTxRate->CurrMCS == MCS_13)
2218 MCS13 = idx;
2220 else if (pCurrTxRate->CurrMCS == MCS_14)
2222 MCS14 = idx;
2224 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2225 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
2227 MCS15 = idx;
2229 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2231 MCS20 = idx;
2233 else if (pCurrTxRate->CurrMCS == MCS_21)
2235 MCS21 = idx;
2237 else if (pCurrTxRate->CurrMCS == MCS_22)
2239 MCS22 = idx;
2241 else if (pCurrTxRate->CurrMCS == MCS_23)
2243 MCS23 = idx;
2245 idx ++;
2248 if (pAd->LatchRfRegs.Channel <= 14)
2250 if (pAd->NicConfig2.field.ExternalLNAForG)
2252 RssiOffset = 2;
2254 else
2256 RssiOffset = 5;
2259 else
2261 if (pAd->NicConfig2.field.ExternalLNAForA)
2263 RssiOffset = 5;
2265 else
2267 RssiOffset = 8;
2270 #ifdef DOT11_N_SUPPORT
2271 /*if (MCS15)*/
2272 if ((pTable == RateSwitchTable11BGN3S) ||
2273 (pTable == RateSwitchTable11N3S) ||
2274 (pTable == RateSwitchTable))
2275 {// N mode with 3 stream // 3*3
2276 if (MCS23 && (Rssi >= -70))
2277 TxRateIdx = MCS23;
2278 else if (MCS22 && (Rssi >= -72))
2279 TxRateIdx = MCS22;
2280 else if (MCS21 && (Rssi >= -76))
2281 TxRateIdx = MCS21;
2282 else if (MCS20 && (Rssi >= -78))
2283 TxRateIdx = MCS20;
2284 else if (MCS4 && (Rssi >= -82))
2285 TxRateIdx = MCS4;
2286 else if (MCS3 && (Rssi >= -84))
2287 TxRateIdx = MCS3;
2288 else if (MCS2 && (Rssi >= -86))
2289 TxRateIdx = MCS2;
2290 else if (MCS1 && (Rssi >= -88))
2291 TxRateIdx = MCS1;
2292 else
2293 TxRateIdx = MCS0;
2295 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2296 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2297 {// N mode with 2 stream
2298 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2299 TxRateIdx = MCS15;
2300 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2301 TxRateIdx = MCS14;
2302 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2303 TxRateIdx = MCS13;
2304 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2305 TxRateIdx = MCS12;
2306 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2307 TxRateIdx = MCS4;
2308 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2309 TxRateIdx = MCS3;
2310 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2311 TxRateIdx = MCS2;
2312 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2313 TxRateIdx = MCS1;
2314 else
2315 TxRateIdx = MCS0;
2317 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2318 {// N mode with 1 stream
2319 if (MCS7 && (Rssi > (-72+RssiOffset)))
2320 TxRateIdx = MCS7;
2321 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2322 TxRateIdx = MCS6;
2323 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2324 TxRateIdx = MCS5;
2325 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2326 TxRateIdx = MCS4;
2327 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2328 TxRateIdx = MCS3;
2329 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2330 TxRateIdx = MCS2;
2331 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2332 TxRateIdx = MCS1;
2333 else
2334 TxRateIdx = MCS0;
2336 else
2337 #endif // DOT11_N_SUPPORT //
2338 {// Legacy mode
2339 if (MCS7 && (Rssi > -70))
2340 TxRateIdx = MCS7;
2341 else if (MCS6 && (Rssi > -74))
2342 TxRateIdx = MCS6;
2343 else if (MCS5 && (Rssi > -78))
2344 TxRateIdx = MCS5;
2345 else if (MCS4 && (Rssi > -82))
2346 TxRateIdx = MCS4;
2347 else if (MCS4 == 0) // for B-only mode
2348 TxRateIdx = MCS3;
2349 else if (MCS3 && (Rssi > -85))
2350 TxRateIdx = MCS3;
2351 else if (MCS2 && (Rssi > -87))
2352 TxRateIdx = MCS2;
2353 else if (MCS1 && (Rssi > -90))
2354 TxRateIdx = MCS1;
2355 else
2356 TxRateIdx = MCS0;
2359 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2361 pEntry->CurrTxRateIndex = TxRateIdx;
2362 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2363 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2366 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2367 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2368 pEntry->fLastSecAccordingRSSI = TRUE;
2369 // reset all OneSecTx counters
2370 RESET_ONE_SEC_TX_CNT(pEntry);
2372 continue;
2375 if (pEntry->fLastSecAccordingRSSI == TRUE)
2377 pEntry->fLastSecAccordingRSSI = FALSE;
2378 pEntry->LastSecTxRateChangeAction = 0;
2379 // reset all OneSecTx counters
2380 RESET_ONE_SEC_TX_CNT(pEntry);
2382 continue;
2387 BOOLEAN bTrainUpDown = FALSE;
2389 pEntry->CurrTxRateStableTime ++;
2391 // downgrade TX quality if PER >= Rate-Down threshold
2392 if (TxErrorRatio >= TrainDown)
2394 bTrainUpDown = TRUE;
2395 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2397 // upgrade TX quality if PER <= Rate-Up threshold
2398 else if (TxErrorRatio <= TrainUp)
2400 bTrainUpDown = TRUE;
2401 bUpgradeQuality = TRUE;
2402 if (pEntry->TxQuality[CurrRateIdx])
2403 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2405 if (pEntry->TxRateUpPenalty)
2406 pEntry->TxRateUpPenalty --;
2407 else if (pEntry->TxQuality[UpRateIdx])
2408 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2411 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2413 if (bTrainUpDown)
2415 // perform DRS - consider TxRate Down first, then rate up.
2416 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2418 pEntry->CurrTxRateIndex = DownRateIdx;
2420 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2422 pEntry->CurrTxRateIndex = UpRateIdx;
2425 } while (FALSE);
2427 // if rate-up happen, clear all bad history of all TX rates
2428 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2430 pEntry->CurrTxRateStableTime = 0;
2431 pEntry->TxRateUpPenalty = 0;
2432 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2433 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2434 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2437 // For TxRate fast train up
2439 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2441 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2443 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2445 bTxRateChanged = TRUE;
2447 // if rate-down happen, only clear DownRate's bad history
2448 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2450 pEntry->CurrTxRateStableTime = 0;
2451 pEntry->TxRateUpPenalty = 0; // no penalty
2452 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2453 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2454 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2457 // For TxRate fast train down
2459 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2461 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2463 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2465 bTxRateChanged = TRUE;
2467 else
2469 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2470 bTxRateChanged = FALSE;
2473 pEntry->LastTxOkCount = TxSuccess;
2476 UCHAR tmpTxRate;
2478 // to fix tcp ack issue
2479 if (!bTxRateChanged && (pAd->RalinkCounters.OneSecReceivedByteCount > (pAd->RalinkCounters.OneSecTransmittedByteCount * 5)))
2481 tmpTxRate = DownRateIdx;
2482 DBGPRINT_RAW(RT_DEBUG_TRACE,("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2483 pAd->RalinkCounters.OneSecReceivedByteCount, pAd->RalinkCounters.OneSecTransmittedByteCount, pEntry->CurrTxRateIndex, tmpTxRate));
2485 else
2487 tmpTxRate = pEntry->CurrTxRateIndex;
2490 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(tmpTxRate+1)*5];
2491 if (bTxRateChanged && pNextTxRate)
2493 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2496 // reset all OneSecTx counters
2497 RESET_ONE_SEC_TX_CNT(pEntry);
2502 ========================================================================
2503 Routine Description:
2504 Station side, Auto TxRate faster train up timer call back function.
2506 Arguments:
2507 SystemSpecific1 - Not used.
2508 FunctionContext - Pointer to our Adapter context.
2509 SystemSpecific2 - Not used.
2510 SystemSpecific3 - Not used.
2512 Return Value:
2513 None
2515 ========================================================================
2517 VOID StaQuickResponeForRateUpExec(
2518 IN PVOID SystemSpecific1,
2519 IN PVOID FunctionContext,
2520 IN PVOID SystemSpecific2,
2521 IN PVOID SystemSpecific3)
2523 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2524 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2525 ULONG TxTotalCnt;
2526 ULONG TxErrorRatio = 0;
2527 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2528 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2529 PUCHAR pTable;
2530 UCHAR TableSize = 0;
2531 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2532 TX_STA_CNT1_STRUC StaTx1;
2533 TX_STA_CNT0_STRUC TxStaCnt0;
2534 CHAR Rssi, ratio;
2535 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2536 MAC_TABLE_ENTRY *pEntry;
2537 ULONG i;
2539 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2542 // walk through MAC table, see if need to change AP's TX rate toward each entry
2544 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2546 pEntry = &pAd->MacTab.Content[i];
2548 // check if this entry need to switch rate automatically
2549 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2550 continue;
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);
2563 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2565 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2567 // decide the next upgrade rate and downgrade rate, if any
2568 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2570 UpRateIdx = CurrRateIdx + 1;
2571 DownRateIdx = CurrRateIdx -1;
2573 else if (CurrRateIdx == 0)
2575 UpRateIdx = CurrRateIdx + 1;
2576 DownRateIdx = CurrRateIdx;
2578 else if (CurrRateIdx == (TableSize - 1))
2580 UpRateIdx = CurrRateIdx;
2581 DownRateIdx = CurrRateIdx - 1;
2584 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2586 #ifdef DOT11_N_SUPPORT
2587 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2589 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2590 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2592 else
2593 #endif // DOT11_N_SUPPORT //
2595 TrainUp = pCurrTxRate->TrainUp;
2596 TrainDown = pCurrTxRate->TrainDown;
2599 if (pAd->MacTab.Size == 1)
2601 // Update statistic counter
2602 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2603 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2605 TxRetransmit = StaTx1.field.TxRetransmit;
2606 TxSuccess = StaTx1.field.TxSuccess;
2607 TxFailCount = TxStaCnt0.field.TxFailCount;
2608 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2610 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2611 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2612 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2613 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2614 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2615 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2617 if (TxTotalCnt)
2618 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2620 else
2622 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2623 pEntry->OneSecTxRetryOkCount +
2624 pEntry->OneSecTxFailCount;
2626 if (TxTotalCnt)
2627 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2632 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2633 // (criteria copied from RT2500 for Netopia case)
2635 if (TxTotalCnt <= 12)
2637 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2638 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2640 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2642 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2643 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2645 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2647 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2650 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2651 return;
2656 ULONG OneSecTxNoRetryOKRationCount;
2658 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2659 ratio = 5;
2660 else
2661 ratio = 4;
2663 // downgrade TX quality if PER >= Rate-Down threshold
2664 if (TxErrorRatio >= TrainDown)
2666 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2669 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2671 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2673 // perform DRS - consider TxRate Down first, then rate up.
2674 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2676 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2678 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2679 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2684 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2686 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2690 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2692 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2695 }while (FALSE);
2697 // if rate-up happen, clear all bad history of all TX rates
2698 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2700 pAd->DrsCounters.TxRateUpPenalty = 0;
2701 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2702 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2703 bTxRateChanged = TRUE;
2705 // if rate-down happen, only clear DownRate's bad history
2706 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2708 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2710 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2711 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2712 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2713 bTxRateChanged = TRUE;
2715 else
2717 bTxRateChanged = FALSE;
2720 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2721 if (bTxRateChanged && pNextTxRate)
2723 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2729 ==========================================================================
2730 Description:
2731 This routine is executed periodically inside MlmePeriodicExec() after
2732 association with an AP.
2733 It checks if StaCfg.Psm is consistent with user policy (recorded in
2734 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2735 there're some conditions to consider:
2736 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2737 the time when Mibss==TRUE
2738 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2739 if outgoing traffic available in TxRing or MgmtRing.
2740 Output:
2741 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2743 IRQL = DISPATCH_LEVEL
2745 ==========================================================================
2747 VOID MlmeCheckPsmChange(
2748 IN PRTMP_ADAPTER pAd,
2749 IN ULONG Now32)
2751 ULONG PowerMode;
2753 // condition -
2754 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2755 // 2. user wants either MAX_PSP or FAST_PSP
2756 // 3. but current psm is not in PWR_SAVE
2757 // 4. CNTL state machine is not doing SCANning
2758 // 5. no TX SUCCESS event for the past 1-sec period
2759 PowerMode = pAd->StaCfg.WindowsPowerMode;
2761 if (INFRA_ON(pAd) &&
2762 (PowerMode != Ndis802_11PowerModeCAM) &&
2763 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2764 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2765 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)&&
2766 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2767 /*&&
2768 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2769 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2771 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2772 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2773 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
2774 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2776 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2778 else
2780 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2785 // IRQL = PASSIVE_LEVEL
2786 // IRQL = DISPATCH_LEVEL
2787 VOID MlmeSetPsmBit(
2788 IN PRTMP_ADAPTER pAd,
2789 IN USHORT psm)
2791 AUTO_RSP_CFG_STRUC csr4;
2793 pAd->StaCfg.Psm = psm;
2794 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2795 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2796 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2797 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2799 #endif // CONFIG_STA_SUPPORT //
2802 ==========================================================================
2803 Description:
2804 This routine calculates TxPER, RxPER of the past N-sec period. And
2805 according to the calculation result, ChannelQuality is calculated here
2806 to decide if current AP is still doing the job.
2808 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2809 Output:
2810 StaCfg.ChannelQuality - 0..100
2812 IRQL = DISPATCH_LEVEL
2814 NOTE: This routine decide channle quality based on RX CRC error ratio.
2815 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2816 is performed right before this routine, so that this routine can decide
2817 channel quality based on the most up-to-date information
2818 ==========================================================================
2820 VOID MlmeCalculateChannelQuality(
2821 IN PRTMP_ADAPTER pAd,
2822 IN PMAC_TABLE_ENTRY pMacEntry,
2823 IN ULONG Now32)
2825 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
2826 ULONG RxCnt, RxPER;
2827 UCHAR NorRssi;
2828 CHAR MaxRssi;
2829 RSSI_SAMPLE *pRssiSample = NULL;
2830 UINT32 OneSecTxNoRetryOkCount = 0;
2831 UINT32 OneSecTxRetryOkCount = 0;
2832 UINT32 OneSecTxFailCount = 0;
2833 UINT32 OneSecRxOkCnt = 0;
2834 UINT32 OneSecRxFcsErrCnt = 0;
2835 ULONG ChannelQuality = 0; // 0..100, Channel Quality Indication for Roaming
2836 #ifdef CONFIG_STA_SUPPORT
2837 ULONG BeaconLostTime = pAd->StaCfg.BeaconLostTime;
2838 #endif // CONFIG_STA_SUPPORT //
2840 #ifdef CONFIG_STA_SUPPORT
2841 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2842 // longer beacon lost time when carrier detection enabled
2843 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
2845 BeaconLostTime = pAd->StaCfg.BeaconLostTime + (pAd->StaCfg.BeaconLostTime/2);
2847 #endif // CARRIER_DETECTION_SUPPORT //
2848 #endif // CONFIG_STA_SUPPORT //
2850 #ifdef CONFIG_STA_SUPPORT
2851 if (pAd->OpMode == OPMODE_STA)
2853 pRssiSample = &pAd->StaCfg.RssiSample;
2854 OneSecTxNoRetryOkCount = pAd->RalinkCounters.OneSecTxNoRetryOkCount;
2855 OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2856 OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2857 OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2858 OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
2860 #endif // CONFIG_STA_SUPPORT //
2862 MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
2863 pRssiSample->LastRssi1,
2864 pRssiSample->LastRssi2);
2867 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
2869 TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2870 TxCnt = TxOkCnt + OneSecTxFailCount;
2871 if (TxCnt < 5)
2873 TxPER = 0;
2874 TxPRR = 0;
2876 else
2878 TxPER = (OneSecTxFailCount * 100) / TxCnt;
2879 TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2883 // calculate RX PER - don't take RxPER into consideration if too few sample
2885 RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2886 if (RxCnt < 5)
2887 RxPER = 0;
2888 else
2889 RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
2892 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
2894 #ifdef CONFIG_STA_SUPPORT
2895 if ((pAd->OpMode == OPMODE_STA) &&
2896 INFRA_ON(pAd) &&
2897 (OneSecTxNoRetryOkCount < 2) && // no heavy traffic
2898 ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32))
2900 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
2901 ChannelQuality = 0;
2903 else
2904 #endif // CONFIG_STA_SUPPORT //
2906 // Normalize Rssi
2907 if (MaxRssi > -40)
2908 NorRssi = 100;
2909 else if (MaxRssi < -90)
2910 NorRssi = 0;
2911 else
2912 NorRssi = (MaxRssi + 90) * 2;
2914 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
2915 ChannelQuality = (RSSI_WEIGHTING * NorRssi +
2916 TX_WEIGHTING * (100 - TxPRR) +
2917 RX_WEIGHTING* (100 - RxPER)) / 100;
2921 #ifdef CONFIG_STA_SUPPORT
2922 if (pAd->OpMode == OPMODE_STA)
2923 pAd->Mlme.ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality;
2924 #endif // CONFIG_STA_SUPPORT //
2930 // IRQL = DISPATCH_LEVEL
2931 VOID MlmeSetTxPreamble(
2932 IN PRTMP_ADAPTER pAd,
2933 IN USHORT TxPreamble)
2935 AUTO_RSP_CFG_STRUC csr4;
2938 // Always use Long preamble before verifiation short preamble functionality works well.
2939 // Todo: remove the following line if short preamble functionality works
2941 //TxPreamble = Rt802_11PreambleLong;
2943 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2944 if (TxPreamble == Rt802_11PreambleLong)
2946 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2947 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2948 csr4.field.AutoResponderPreamble = 0;
2950 else
2952 // NOTE: 1Mbps should always use long preamble
2953 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2954 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2955 csr4.field.AutoResponderPreamble = 1;
2958 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2962 ==========================================================================
2963 Description:
2964 Update basic rate bitmap
2965 ==========================================================================
2968 VOID UpdateBasicRateBitmap(
2969 IN PRTMP_ADAPTER pAdapter)
2971 INT i, j;
2972 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2973 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2974 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2975 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2976 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2979 /* if A mode, always use fix BasicRateBitMap */
2980 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2981 if (pAdapter->CommonCfg.Channel > 14)
2982 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2983 /* End of if */
2985 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2987 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2988 return;
2989 } /* End of if */
2991 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2993 sup_p[i] &= 0x7f;
2994 ext_p[i] &= 0x7f;
2995 } /* End of for */
2997 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2999 if (bitmap & (1 << i))
3001 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
3003 if (sup_p[j] == rate[i])
3004 sup_p[j] |= 0x80;
3005 /* End of if */
3006 } /* End of for */
3008 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
3010 if (ext_p[j] == rate[i])
3011 ext_p[j] |= 0x80;
3012 /* End of if */
3013 } /* End of for */
3014 } /* End of if */
3015 } /* End of for */
3016 } /* End of UpdateBasicRateBitmap */
3018 // IRQL = PASSIVE_LEVEL
3019 // IRQL = DISPATCH_LEVEL
3020 // bLinkUp is to identify the inital link speed.
3021 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
3022 VOID MlmeUpdateTxRates(
3023 IN PRTMP_ADAPTER pAd,
3024 IN BOOLEAN bLinkUp,
3025 IN UCHAR apidx)
3027 int i, num;
3028 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
3029 UCHAR MinSupport = RATE_54;
3030 ULONG BasicRateBitmap = 0;
3031 UCHAR CurrBasicRate = RATE_1;
3032 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
3033 PHTTRANSMIT_SETTING pHtPhy = NULL;
3034 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3035 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3036 BOOLEAN *auto_rate_cur_p;
3037 UCHAR HtMcs = MCS_AUTO;
3039 // find max desired rate
3040 UpdateBasicRateBitmap(pAd);
3042 num = 0;
3043 auto_rate_cur_p = NULL;
3044 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3046 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
3048 case 2: Rate = RATE_1; num++; break;
3049 case 4: Rate = RATE_2; num++; break;
3050 case 11: Rate = RATE_5_5; num++; break;
3051 case 22: Rate = RATE_11; num++; break;
3052 case 12: Rate = RATE_6; num++; break;
3053 case 18: Rate = RATE_9; num++; break;
3054 case 24: Rate = RATE_12; num++; break;
3055 case 36: Rate = RATE_18; num++; break;
3056 case 48: Rate = RATE_24; num++; break;
3057 case 72: Rate = RATE_36; num++; break;
3058 case 96: Rate = RATE_48; num++; break;
3059 case 108: Rate = RATE_54; num++; break;
3060 //default: Rate = RATE_1; break;
3062 if (MaxDesire < Rate) MaxDesire = Rate;
3065 //===========================================================================
3066 //===========================================================================
3068 #ifdef CONFIG_STA_SUPPORT
3069 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3071 pHtPhy = &pAd->StaCfg.HTPhyMode;
3072 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3073 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3075 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3076 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
3078 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
3079 (pAd->CommonCfg.PhyMode == PHY_11B) &&
3080 (MaxDesire > RATE_11))
3082 MaxDesire = RATE_11;
3085 #endif // CONFIG_STA_SUPPORT //
3087 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
3088 pMinHtPhy->word = 0;
3089 pMaxHtPhy->word = 0;
3090 pHtPhy->word = 0;
3092 // Auto rate switching is enabled only if more than one DESIRED RATES are
3093 // specified; otherwise disabled
3094 if (num <= 1)
3096 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
3097 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
3098 *auto_rate_cur_p = FALSE;
3100 else
3102 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
3103 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
3104 *auto_rate_cur_p = TRUE;
3107 if (HtMcs != MCS_AUTO)
3109 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
3110 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
3111 *auto_rate_cur_p = FALSE;
3113 else
3115 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
3116 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
3117 *auto_rate_cur_p = TRUE;
3120 #ifdef CONFIG_STA_SUPPORT
3121 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3123 pSupRate = &pAd->StaActive.SupRate[0];
3124 pExtRate = &pAd->StaActive.ExtRate[0];
3125 SupRateLen = pAd->StaActive.SupRateLen;
3126 ExtRateLen = pAd->StaActive.ExtRateLen;
3128 else
3129 #endif // CONFIG_STA_SUPPORT //
3131 pSupRate = &pAd->CommonCfg.SupRate[0];
3132 pExtRate = &pAd->CommonCfg.ExtRate[0];
3133 SupRateLen = pAd->CommonCfg.SupRateLen;
3134 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3137 // find max supported rate
3138 for (i=0; i<SupRateLen; i++)
3140 switch (pSupRate[i] & 0x7f)
3142 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3143 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3144 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3145 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3146 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3147 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3148 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3149 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3150 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3151 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3152 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3153 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3154 default: Rate = RATE_1; break;
3156 if (MaxSupport < Rate) MaxSupport = Rate;
3158 if (MinSupport > Rate) MinSupport = Rate;
3161 for (i=0; i<ExtRateLen; i++)
3163 switch (pExtRate[i] & 0x7f)
3165 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3166 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3167 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3168 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3169 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3170 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3171 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3172 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3173 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3174 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3175 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3176 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3177 default: Rate = RATE_1; break;
3179 if (MaxSupport < Rate) MaxSupport = Rate;
3181 if (MinSupport > Rate) MinSupport = Rate;
3184 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3186 // bug fix
3187 // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
3189 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3190 // the DURATION field of outgoing uniicast DATA/MGMT frame
3191 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3193 if (BasicRateBitmap & (0x01 << i))
3194 CurrBasicRate = (UCHAR)i;
3195 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3198 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3199 // max tx rate = min {max desire rate, max supported rate}
3200 if (MaxSupport < MaxDesire)
3201 pAd->CommonCfg.MaxTxRate = MaxSupport;
3202 else
3203 pAd->CommonCfg.MaxTxRate = MaxDesire;
3205 pAd->CommonCfg.MinTxRate = MinSupport;
3206 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
3207 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
3208 // on average RSSI
3209 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
3210 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
3211 // 3. -75 > RSSI, start at 11 Mbps (long distance)
3212 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
3213 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
3214 if (*auto_rate_cur_p)
3216 short dbm = 0;
3217 #ifdef CONFIG_STA_SUPPORT
3218 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3219 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3220 #endif // CONFIG_STA_SUPPORT //
3221 if (bLinkUp == TRUE)
3222 pAd->CommonCfg.TxRate = RATE_24;
3223 else
3224 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3226 if (dbm < -75)
3227 pAd->CommonCfg.TxRate = RATE_11;
3228 else if (dbm < -70)
3229 pAd->CommonCfg.TxRate = RATE_24;
3231 // should never exceed MaxTxRate (consider 11B-only mode)
3232 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3233 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3235 pAd->CommonCfg.TxRateIndex = 0;
3237 else
3239 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3240 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3241 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3243 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3244 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3245 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3246 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3249 if (pAd->CommonCfg.TxRate <= RATE_11)
3251 pMaxHtPhy->field.MODE = MODE_CCK;
3252 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3253 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3255 else
3257 pMaxHtPhy->field.MODE = MODE_OFDM;
3258 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3259 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3260 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3261 else
3262 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3265 pHtPhy->word = (pMaxHtPhy->word);
3266 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3268 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3269 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3270 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3272 else
3274 switch (pAd->CommonCfg.PhyMode)
3276 case PHY_11BG_MIXED:
3277 case PHY_11B:
3278 #ifdef DOT11_N_SUPPORT
3279 case PHY_11BGN_MIXED:
3280 #endif // DOT11_N_SUPPORT //
3281 pAd->CommonCfg.MlmeRate = RATE_1;
3282 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3283 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3285 //#ifdef WIFI_TEST
3286 pAd->CommonCfg.RtsRate = RATE_11;
3287 //#else
3288 // pAd->CommonCfg.RtsRate = RATE_1;
3289 //#endif
3290 break;
3291 case PHY_11G:
3292 case PHY_11A:
3293 #ifdef DOT11_N_SUPPORT
3294 case PHY_11AGN_MIXED:
3295 case PHY_11GN_MIXED:
3296 case PHY_11N_2_4G:
3297 case PHY_11AN_MIXED:
3298 case PHY_11N_5G:
3299 #endif // DOT11_N_SUPPORT //
3300 pAd->CommonCfg.MlmeRate = RATE_6;
3301 pAd->CommonCfg.RtsRate = RATE_6;
3302 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3303 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3304 break;
3305 case PHY_11ABG_MIXED:
3306 #ifdef DOT11_N_SUPPORT
3307 case PHY_11ABGN_MIXED:
3308 #endif // DOT11_N_SUPPORT //
3309 if (pAd->CommonCfg.Channel <= 14)
3311 pAd->CommonCfg.MlmeRate = RATE_1;
3312 pAd->CommonCfg.RtsRate = RATE_1;
3313 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3314 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3316 else
3318 pAd->CommonCfg.MlmeRate = RATE_6;
3319 pAd->CommonCfg.RtsRate = RATE_6;
3320 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3321 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3323 break;
3324 default: // error
3325 pAd->CommonCfg.MlmeRate = RATE_6;
3326 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3327 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3328 pAd->CommonCfg.RtsRate = RATE_1;
3329 break;
3332 // Keep Basic Mlme Rate.
3334 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3335 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3336 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3337 else
3338 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3339 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3342 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3343 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3344 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3345 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3346 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3347 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3348 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 ));
3351 #ifdef DOT11_N_SUPPORT
3353 ==========================================================================
3354 Description:
3355 This function update HT Rate setting.
3356 Input Wcid value is valid for 2 case :
3357 1. it's used for Station in infra mode that copy AP rate to Mactable.
3358 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3360 IRQL = DISPATCH_LEVEL
3362 ==========================================================================
3364 VOID MlmeUpdateHtTxRates(
3365 IN PRTMP_ADAPTER pAd,
3366 IN UCHAR apidx)
3368 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3369 CHAR i; // 3*3
3370 RT_HT_CAPABILITY *pRtHtCap = NULL;
3371 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3372 ULONG BasicMCS;
3373 UCHAR j, bitmask;
3374 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3375 PHTTRANSMIT_SETTING pHtPhy = NULL;
3376 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3377 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3378 BOOLEAN *auto_rate_cur_p;
3380 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3382 auto_rate_cur_p = NULL;
3384 #ifdef CONFIG_STA_SUPPORT
3385 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3387 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3388 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3389 pHtPhy = &pAd->StaCfg.HTPhyMode;
3390 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3391 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3393 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3395 #endif // CONFIG_STA_SUPPORT //
3397 #ifdef CONFIG_STA_SUPPORT
3398 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3400 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3401 return;
3403 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3404 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3405 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3406 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3407 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3408 pMaxHtPhy->field.STBC = STBC_USE;
3409 else
3410 pMaxHtPhy->field.STBC = STBC_NONE;
3412 else
3413 #endif // CONFIG_STA_SUPPORT //
3415 if (pDesireHtPhy->bHtEnable == FALSE)
3416 return;
3418 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3419 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3420 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3421 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3422 pMaxHtPhy->field.STBC = STBC_USE;
3423 else
3424 pMaxHtPhy->field.STBC = STBC_NONE;
3427 // Decide MAX ht rate.
3428 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3429 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3430 else
3431 pMaxHtPhy->field.MODE = MODE_HTMIX;
3433 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3434 pMaxHtPhy->field.BW = BW_40;
3435 else
3436 pMaxHtPhy->field.BW = BW_20;
3438 if (pMaxHtPhy->field.BW == BW_20)
3439 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3440 else
3441 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3443 if (pDesireHtPhy->MCSSet[4] != 0)
3445 pMaxHtPhy->field.MCS = 32;
3448 for (i=23; i>=0; i--) // 3*3
3450 j = i/8;
3451 bitmask = (1<<(i-(j*8)));
3453 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3455 pMaxHtPhy->field.MCS = i;
3456 break;
3459 if (i==0)
3460 break;
3463 // Copy MIN ht rate. rt2860???
3464 pMinHtPhy->field.BW = BW_20;
3465 pMinHtPhy->field.MCS = 0;
3466 pMinHtPhy->field.STBC = 0;
3467 pMinHtPhy->field.ShortGI = 0;
3468 //If STA assigns fixed rate. update to fixed here.
3469 #ifdef CONFIG_STA_SUPPORT
3470 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3472 if (pDesireHtPhy->MCSSet[4] != 0)
3474 pMaxHtPhy->field.MCS = 32;
3475 pMinHtPhy->field.MCS = 32;
3476 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3479 for (i=23; (CHAR)i >= 0; i--) // 3*3
3481 j = i/8;
3482 bitmask = (1<<(i-(j*8)));
3483 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3485 pMaxHtPhy->field.MCS = i;
3486 pMinHtPhy->field.MCS = i;
3487 break;
3489 if (i==0)
3490 break;
3493 #endif // CONFIG_STA_SUPPORT //
3496 // Decide ht rate
3497 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3498 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3499 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3500 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3501 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3503 // use default now. rt2860
3504 if (pDesireHtPhy->MCSSet[0] != 0xff)
3505 *auto_rate_cur_p = FALSE;
3506 else
3507 *auto_rate_cur_p = TRUE;
3509 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3510 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3511 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3512 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3516 VOID BATableInit(
3517 IN PRTMP_ADAPTER pAd,
3518 IN BA_TABLE *Tab)
3520 int i;
3522 Tab->numAsOriginator = 0;
3523 Tab->numAsRecipient = 0;
3524 Tab->numDoneOriginator = 0;
3525 NdisAllocateSpinLock(&pAd->BATabLock);
3526 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3528 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3529 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3531 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3533 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3536 #endif // DOT11_N_SUPPORT //
3538 // IRQL = DISPATCH_LEVEL
3539 VOID MlmeRadioOff(
3540 IN PRTMP_ADAPTER pAd)
3542 RTMP_MLME_RADIO_OFF(pAd);
3545 // IRQL = DISPATCH_LEVEL
3546 VOID MlmeRadioOn(
3547 IN PRTMP_ADAPTER pAd)
3549 RTMP_MLME_RADIO_ON(pAd);
3552 // ===========================================================================================
3553 // bss_table.c
3554 // ===========================================================================================
3557 /*! \brief initialize BSS table
3558 * \param p_tab pointer to the table
3559 * \return none
3560 * \pre
3561 * \post
3563 IRQL = PASSIVE_LEVEL
3564 IRQL = DISPATCH_LEVEL
3567 VOID BssTableInit(
3568 IN BSS_TABLE *Tab)
3570 int i;
3572 Tab->BssNr = 0;
3573 Tab->BssOverlapNr = 0;
3574 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3576 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3577 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3582 /*! \brief search the BSS table by SSID
3583 * \param p_tab pointer to the bss table
3584 * \param ssid SSID string
3585 * \return index of the table, BSS_NOT_FOUND if not in the table
3586 * \pre
3587 * \post
3588 * \note search by sequential search
3590 IRQL = DISPATCH_LEVEL
3593 ULONG BssTableSearch(
3594 IN BSS_TABLE *Tab,
3595 IN PUCHAR pBssid,
3596 IN UCHAR Channel)
3598 UCHAR i;
3600 for (i = 0; i < Tab->BssNr; i++)
3603 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3604 // We should distinguish this case.
3606 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3607 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3608 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3610 return i;
3613 return (ULONG)BSS_NOT_FOUND;
3616 ULONG BssSsidTableSearch(
3617 IN BSS_TABLE *Tab,
3618 IN PUCHAR pBssid,
3619 IN PUCHAR pSsid,
3620 IN UCHAR SsidLen,
3621 IN UCHAR Channel)
3623 UCHAR i;
3625 for (i = 0; i < Tab->BssNr; i++)
3628 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3629 // We should distinguish this case.
3631 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3632 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3633 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3634 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3636 return i;
3639 return (ULONG)BSS_NOT_FOUND;
3642 ULONG BssTableSearchWithSSID(
3643 IN BSS_TABLE *Tab,
3644 IN PUCHAR Bssid,
3645 IN PUCHAR pSsid,
3646 IN UCHAR SsidLen,
3647 IN UCHAR Channel)
3649 UCHAR i;
3651 for (i = 0; i < Tab->BssNr; i++)
3653 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3654 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3655 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3656 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3657 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3658 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3660 return i;
3663 return (ULONG)BSS_NOT_FOUND;
3667 ULONG BssSsidTableSearchBySSID(
3668 IN BSS_TABLE *Tab,
3669 IN PUCHAR pSsid,
3670 IN UCHAR SsidLen)
3672 UCHAR i;
3674 for (i = 0; i < Tab->BssNr; i++)
3676 if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3678 return i;
3681 return (ULONG)BSS_NOT_FOUND;
3685 // IRQL = DISPATCH_LEVEL
3686 VOID BssTableDeleteEntry(
3687 IN OUT BSS_TABLE *Tab,
3688 IN PUCHAR pBssid,
3689 IN UCHAR Channel)
3691 UCHAR i, j;
3693 for (i = 0; i < Tab->BssNr; i++)
3695 if ((Tab->BssEntry[i].Channel == Channel) &&
3696 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3698 for (j = i; j < Tab->BssNr - 1; j++)
3700 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3702 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3703 Tab->BssNr -= 1;
3704 return;
3709 #ifdef DOT11_N_SUPPORT
3711 ========================================================================
3712 Routine Description:
3713 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3715 Arguments:
3716 // IRQL = DISPATCH_LEVEL
3717 ========================================================================
3719 VOID BATableDeleteORIEntry(
3720 IN OUT PRTMP_ADAPTER pAd,
3721 IN BA_ORI_ENTRY *pBAORIEntry)
3724 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3726 NdisAcquireSpinLock(&pAd->BATabLock);
3727 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3729 pAd->BATable.numAsOriginator -= 1;
3730 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3731 // Erase Bitmap flag.
3733 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3734 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3735 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3736 pBAORIEntry->Token = 1;
3737 // Not clear Sequence here.
3738 NdisReleaseSpinLock(&pAd->BATabLock);
3741 #endif // DOT11_N_SUPPORT //
3743 /*! \brief
3744 * \param
3745 * \return
3746 * \pre
3747 * \post
3749 IRQL = DISPATCH_LEVEL
3752 VOID BssEntrySet(
3753 IN PRTMP_ADAPTER pAd,
3754 OUT BSS_ENTRY *pBss,
3755 IN PUCHAR pBssid,
3756 IN CHAR Ssid[],
3757 IN UCHAR SsidLen,
3758 IN UCHAR BssType,
3759 IN USHORT BeaconPeriod,
3760 IN PCF_PARM pCfParm,
3761 IN USHORT AtimWin,
3762 IN USHORT CapabilityInfo,
3763 IN UCHAR SupRate[],
3764 IN UCHAR SupRateLen,
3765 IN UCHAR ExtRate[],
3766 IN UCHAR ExtRateLen,
3767 IN HT_CAPABILITY_IE *pHtCapability,
3768 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3769 IN UCHAR HtCapabilityLen,
3770 IN UCHAR AddHtInfoLen,
3771 IN UCHAR NewExtChanOffset,
3772 IN UCHAR Channel,
3773 IN CHAR Rssi,
3774 IN LARGE_INTEGER TimeStamp,
3775 IN UCHAR CkipFlag,
3776 IN PEDCA_PARM pEdcaParm,
3777 IN PQOS_CAPABILITY_PARM pQosCapability,
3778 IN PQBSS_LOAD_PARM pQbssLoad,
3779 IN USHORT LengthVIE,
3780 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3782 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3783 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3784 pBss->Hidden = 1;
3785 if (SsidLen > 0)
3787 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3788 // Or send beacon /probe response with SSID len matching real SSID length,
3789 // but SSID is all zero. such as "00-00-00-00" with length 4.
3790 // We have to prevent this case overwrite correct table
3791 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3793 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3794 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3795 pBss->SsidLen = SsidLen;
3796 pBss->Hidden = 0;
3799 else
3800 pBss->SsidLen = 0;
3801 pBss->BssType = BssType;
3802 pBss->BeaconPeriod = BeaconPeriod;
3803 if (BssType == BSS_INFRA)
3805 if (pCfParm->bValid)
3807 pBss->CfpCount = pCfParm->CfpCount;
3808 pBss->CfpPeriod = pCfParm->CfpPeriod;
3809 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3810 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3813 else
3815 pBss->AtimWin = AtimWin;
3818 pBss->CapabilityInfo = CapabilityInfo;
3819 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3820 // Combine with AuthMode, they will decide the connection methods.
3821 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3822 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3823 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3824 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3825 else
3826 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3827 pBss->SupRateLen = SupRateLen;
3828 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3829 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3830 pBss->NewExtChanOffset = NewExtChanOffset;
3831 pBss->ExtRateLen = ExtRateLen;
3832 pBss->Channel = Channel;
3833 pBss->CentralChannel = Channel;
3834 pBss->Rssi = Rssi;
3835 // Update CkipFlag. if not exists, the value is 0x0
3836 pBss->CkipFlag = CkipFlag;
3838 // New for microsoft Fixed IEs
3839 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3840 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3841 pBss->FixIEs.Capabilities = CapabilityInfo;
3843 // New for microsoft Variable IEs
3844 if (LengthVIE != 0)
3846 pBss->VarIELen = LengthVIE;
3847 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3849 else
3851 pBss->VarIELen = 0;
3854 pBss->AddHtInfoLen = 0;
3855 pBss->HtCapabilityLen = 0;
3856 #ifdef DOT11_N_SUPPORT
3857 if (HtCapabilityLen> 0)
3859 pBss->HtCapabilityLen = HtCapabilityLen;
3860 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3861 if (AddHtInfoLen > 0)
3863 pBss->AddHtInfoLen = AddHtInfoLen;
3864 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3866 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3868 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3870 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3872 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3876 #endif // DOT11_N_SUPPORT //
3878 BssCipherParse(pBss);
3880 // new for QOS
3881 if (pEdcaParm)
3882 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3883 else
3884 pBss->EdcaParm.bValid = FALSE;
3885 if (pQosCapability)
3886 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3887 else
3888 pBss->QosCapability.bValid = FALSE;
3889 if (pQbssLoad)
3890 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3891 else
3892 pBss->QbssLoad.bValid = FALSE;
3894 #ifdef CONFIG_STA_SUPPORT
3895 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3897 PEID_STRUCT pEid;
3898 USHORT Length = 0;
3901 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3902 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3903 #ifdef EXT_BUILD_CHANNEL_LIST
3904 NdisZeroMemory(&pBss->CountryString[0], 3);
3905 pBss->bHasCountryIE = FALSE;
3906 #endif // EXT_BUILD_CHANNEL_LIST //
3907 pEid = (PEID_STRUCT) pVIE;
3908 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3910 switch(pEid->Eid)
3912 case IE_WPA:
3913 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3915 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3917 pBss->WpaIE.IELen = 0;
3918 break;
3920 pBss->WpaIE.IELen = pEid->Len + 2;
3921 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3923 break;
3924 case IE_RSN:
3925 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3927 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3929 pBss->RsnIE.IELen = 0;
3930 break;
3932 pBss->RsnIE.IELen = pEid->Len + 2;
3933 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3935 break;
3936 #ifdef EXT_BUILD_CHANNEL_LIST
3937 case IE_COUNTRY:
3938 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3939 pBss->bHasCountryIE = TRUE;
3940 break;
3941 #endif // EXT_BUILD_CHANNEL_LIST //
3943 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3944 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3947 #endif // CONFIG_STA_SUPPORT //
3951 * \brief insert an entry into the bss table
3952 * \param p_tab The BSS table
3953 * \param Bssid BSSID
3954 * \param ssid SSID
3955 * \param ssid_len Length of SSID
3956 * \param bss_type
3957 * \param beacon_period
3958 * \param timestamp
3959 * \param p_cf
3960 * \param atim_win
3961 * \param cap
3962 * \param rates
3963 * \param rates_len
3964 * \param channel_idx
3965 * \return none
3966 * \pre
3967 * \post
3968 * \note If SSID is identical, the old entry will be replaced by the new one
3970 IRQL = DISPATCH_LEVEL
3973 ULONG BssTableSetEntry(
3974 IN PRTMP_ADAPTER pAd,
3975 OUT BSS_TABLE *Tab,
3976 IN PUCHAR pBssid,
3977 IN CHAR Ssid[],
3978 IN UCHAR SsidLen,
3979 IN UCHAR BssType,
3980 IN USHORT BeaconPeriod,
3981 IN CF_PARM *CfParm,
3982 IN USHORT AtimWin,
3983 IN USHORT CapabilityInfo,
3984 IN UCHAR SupRate[],
3985 IN UCHAR SupRateLen,
3986 IN UCHAR ExtRate[],
3987 IN UCHAR ExtRateLen,
3988 IN HT_CAPABILITY_IE *pHtCapability,
3989 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3990 IN UCHAR HtCapabilityLen,
3991 IN UCHAR AddHtInfoLen,
3992 IN UCHAR NewExtChanOffset,
3993 IN UCHAR ChannelNo,
3994 IN CHAR Rssi,
3995 IN LARGE_INTEGER TimeStamp,
3996 IN UCHAR CkipFlag,
3997 IN PEDCA_PARM pEdcaParm,
3998 IN PQOS_CAPABILITY_PARM pQosCapability,
3999 IN PQBSS_LOAD_PARM pQbssLoad,
4000 IN USHORT LengthVIE,
4001 IN PNDIS_802_11_VARIABLE_IEs pVIE)
4003 ULONG Idx;
4005 Idx = BssTableSearchWithSSID(Tab, pBssid, (UCHAR *)Ssid, SsidLen, ChannelNo);
4006 if (Idx == BSS_NOT_FOUND)
4008 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4011 // It may happen when BSS Table was full.
4012 // The desired AP will not be added into BSS Table
4013 // In this case, if we found the desired AP then overwrite BSS Table.
4015 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
4017 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
4018 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
4020 Idx = Tab->BssOverlapNr;
4021 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
4022 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
4023 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
4024 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
4026 return Idx;
4028 else
4030 return BSS_NOT_FOUND;
4033 Idx = Tab->BssNr;
4034 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
4035 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
4036 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
4037 Tab->BssNr++;
4039 else
4041 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
4042 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
4043 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
4045 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
4046 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
4047 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
4051 return Idx;
4054 #ifdef CONFIG_STA_SUPPORT
4055 #ifdef DOT11_N_SUPPORT
4056 #ifdef DOT11N_DRAFT3
4057 VOID TriEventInit(
4058 IN PRTMP_ADAPTER pAd)
4060 UCHAR i;
4062 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
4063 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
4065 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
4066 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
4069 ULONG TriEventTableSetEntry(
4070 IN PRTMP_ADAPTER pAd,
4071 OUT TRIGGER_EVENT_TAB *Tab,
4072 IN PUCHAR pBssid,
4073 IN HT_CAPABILITY_IE *pHtCapability,
4074 IN UCHAR HtCapabilityLen,
4075 IN UCHAR RegClass,
4076 IN UCHAR ChannelNo)
4078 // Event A
4079 if (HtCapabilityLen == 0)
4081 if (Tab->EventANo < MAX_TRIGGER_EVENT)
4083 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
4084 Tab->EventA[Tab->EventANo].bValid = TRUE;
4085 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
4086 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
4087 if (RegClass != 0)
4089 // Beacon has Regulatory class IE. So use beacon's
4090 Tab->EventA[Tab->EventANo].RegClass = RegClass;
4092 else
4094 // Use Station's Regulatory class instead.
4095 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
4097 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
4099 Tab->EventA[Tab->EventANo].RegClass = 32;
4101 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
4102 Tab->EventA[Tab->EventANo].RegClass = 33;
4104 else
4105 Tab->EventA[Tab->EventANo].RegClass = ??;
4109 Tab->EventANo ++;
4112 else if (pHtCapability->HtCapInfo.Intolerant40)
4114 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
4120 ========================================================================
4121 Routine Description:
4122 Trigger Event table Maintainence called once every second.
4124 Arguments:
4125 // IRQL = DISPATCH_LEVEL
4126 ========================================================================
4128 VOID TriEventCounterMaintenance(
4129 IN PRTMP_ADAPTER pAd)
4131 UCHAR i;
4132 BOOLEAN bNotify = FALSE;
4133 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
4135 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
4137 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
4138 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
4140 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
4141 pAd->CommonCfg.TriggerEventTab.EventANo --;
4142 // Need to send 20/40 Coexistence Notify frame if has status change.
4143 bNotify = TRUE;
4147 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
4149 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
4150 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
4151 bNotify = TRUE;
4154 if (bNotify == TRUE)
4155 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
4157 #endif // DOT11N_DRAFT3 //
4158 #endif // DOT11_N_SUPPORT //
4160 // IRQL = DISPATCH_LEVEL
4161 VOID BssTableSsidSort(
4162 IN PRTMP_ADAPTER pAd,
4163 OUT BSS_TABLE *OutTab,
4164 IN CHAR Ssid[],
4165 IN UCHAR SsidLen)
4167 INT i;
4168 BssTableInit(OutTab);
4170 for (i = 0; i < pAd->ScanTab.BssNr; i++)
4172 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
4173 BOOLEAN bIsHiddenApIncluded = FALSE;
4175 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
4176 (pAd->MlmeAux.Channel > 14) &&
4177 RadarChannelCheck(pAd, pInBss->Channel))
4178 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
4179 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
4180 #endif // CARRIER_DETECTION_SUPPORT //
4183 if (pInBss->Hidden)
4184 bIsHiddenApIncluded = TRUE;
4187 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4188 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4190 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4193 #ifdef EXT_BUILD_CHANNEL_LIST
4194 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4195 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4196 (pInBss->bHasCountryIE == FALSE))
4198 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4199 continue;
4201 #endif // EXT_BUILD_CHANNEL_LIST //
4203 #ifdef DOT11_N_SUPPORT
4204 // 2.4G/5G N only mode
4205 if ((pInBss->HtCapabilityLen == 0) &&
4206 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4208 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4209 continue;
4211 #endif // DOT11_N_SUPPORT //
4213 // New for WPA2
4214 // Check the Authmode first
4215 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4217 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4218 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4219 // None matched
4220 continue;
4222 // Check cipher suite, AP must have more secured cipher than station setting
4223 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4225 // If it's not mixed mode, we should only let BSS pass with the same encryption
4226 if (pInBss->WPA.bMixMode == FALSE)
4227 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4228 continue;
4230 // check group cipher
4231 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4232 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4233 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
4234 continue;
4236 // check pairwise cipher, skip if none matched
4237 // If profile set to AES, let it pass without question.
4238 // If profile set to TKIP, we must find one mateched
4239 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4240 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4241 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4242 continue;
4244 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4246 // If it's not mixed mode, we should only let BSS pass with the same encryption
4247 if (pInBss->WPA2.bMixMode == FALSE)
4248 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4249 continue;
4251 // check group cipher
4252 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4253 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4254 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4255 continue;
4257 // check pairwise cipher, skip if none matched
4258 // If profile set to AES, let it pass without question.
4259 // If profile set to TKIP, we must find one mateched
4260 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4261 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4262 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4263 continue;
4266 // Bss Type matched, SSID matched.
4267 // We will check wepstatus for qualification Bss
4268 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4270 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4272 // For the SESv2 case, we will not qualify WepStatus.
4274 if (!pInBss->bSES)
4275 continue;
4278 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4279 // It definitely will fail. So, skip it.
4280 // CCX also require not even try to connect it!!
4281 if (SsidLen == 0)
4282 continue;
4284 #ifdef DOT11_N_SUPPORT
4285 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4286 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4287 if ((pInBss->CentralChannel != pInBss->Channel) &&
4288 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4290 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4292 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4293 SetCommonHT(pAd);
4294 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4296 else
4298 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4300 SetCommonHT(pAd);
4304 #endif // DOT11_N_SUPPORT //
4306 // copy matching BSS from InTab to OutTab
4307 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4309 OutTab->BssNr++;
4311 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4313 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4316 #ifdef DOT11_N_SUPPORT
4317 // 2.4G/5G N only mode
4318 if ((pInBss->HtCapabilityLen == 0) &&
4319 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4321 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4322 continue;
4324 #endif // DOT11_N_SUPPORT //
4326 // New for WPA2
4327 // Check the Authmode first
4328 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4330 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4331 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4332 // None matched
4333 continue;
4335 // Check cipher suite, AP must have more secured cipher than station setting
4336 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4338 // If it's not mixed mode, we should only let BSS pass with the same encryption
4339 if (pInBss->WPA.bMixMode == FALSE)
4340 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4341 continue;
4343 // check group cipher
4344 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4345 continue;
4347 // check pairwise cipher, skip if none matched
4348 // If profile set to AES, let it pass without question.
4349 // If profile set to TKIP, we must find one mateched
4350 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4351 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4352 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4353 continue;
4355 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4357 // If it's not mixed mode, we should only let BSS pass with the same encryption
4358 if (pInBss->WPA2.bMixMode == FALSE)
4359 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4360 continue;
4362 // check group cipher
4363 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4364 continue;
4366 // check pairwise cipher, skip if none matched
4367 // If profile set to AES, let it pass without question.
4368 // If profile set to TKIP, we must find one mateched
4369 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4370 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4371 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4372 continue;
4375 // Bss Type matched, SSID matched.
4376 // We will check wepstatus for qualification Bss
4377 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4378 continue;
4380 #ifdef DOT11_N_SUPPORT
4381 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4382 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4383 if ((pInBss->CentralChannel != pInBss->Channel) &&
4384 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4386 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4388 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4389 SetCommonHT(pAd);
4390 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4393 #endif // DOT11_N_SUPPORT //
4395 // copy matching BSS from InTab to OutTab
4396 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4398 OutTab->BssNr++;
4401 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4402 break;
4405 BssTableSortByRssi(OutTab);
4409 // IRQL = DISPATCH_LEVEL
4410 VOID BssTableSortByRssi(
4411 IN OUT BSS_TABLE *OutTab)
4413 INT i, j;
4414 BSS_ENTRY TmpBss;
4416 for (i = 0; i < OutTab->BssNr - 1; i++)
4418 for (j = i+1; j < OutTab->BssNr; j++)
4420 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4422 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4423 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4424 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4429 #endif // CONFIG_STA_SUPPORT //
4432 VOID BssCipherParse(
4433 IN OUT PBSS_ENTRY pBss)
4435 PEID_STRUCT pEid;
4436 PUCHAR pTmp;
4437 PRSN_IE_HEADER_STRUCT pRsnHeader;
4438 PCIPHER_SUITE_STRUCT pCipher;
4439 PAKM_SUITE_STRUCT pAKM;
4440 USHORT Count;
4441 INT Length;
4442 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4445 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4447 if (pBss->Privacy)
4449 pBss->WepStatus = Ndis802_11WEPEnabled;
4451 else
4453 pBss->WepStatus = Ndis802_11WEPDisabled;
4455 // Set default to disable & open authentication before parsing variable IE
4456 pBss->AuthMode = Ndis802_11AuthModeOpen;
4457 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4459 // Init WPA setting
4460 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4461 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4462 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4463 pBss->WPA.RsnCapability = 0;
4464 pBss->WPA.bMixMode = FALSE;
4466 // Init WPA2 setting
4467 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4468 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4469 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4470 pBss->WPA2.RsnCapability = 0;
4471 pBss->WPA2.bMixMode = FALSE;
4474 Length = (INT) pBss->VarIELen;
4476 while (Length > 0)
4478 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4479 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4480 pEid = (PEID_STRUCT) pTmp;
4481 switch (pEid->Eid)
4483 case IE_WPA:
4484 if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4486 pBss->bSES = TRUE;
4487 break;
4489 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4491 // if unsupported vendor specific IE
4492 break;
4494 // Skip OUI, version, and multicast suite
4495 // This part should be improved in the future when AP supported multiple cipher suite.
4496 // For now, it's OK since almost all APs have fixed cipher suite supported.
4497 // pTmp = (PUCHAR) pEid->Octet;
4498 pTmp += 11;
4500 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4501 // Value Meaning
4502 // 0 None
4503 // 1 WEP-40
4504 // 2 Tkip
4505 // 3 WRAP
4506 // 4 AES
4507 // 5 WEP-104
4508 // Parse group cipher
4509 switch (*pTmp)
4511 case 1:
4512 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4513 break;
4514 case 5:
4515 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4516 break;
4517 case 2:
4518 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4519 break;
4520 case 4:
4521 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4522 break;
4523 default:
4524 break;
4526 // number of unicast suite
4527 pTmp += 1;
4529 // skip all unicast cipher suites
4530 //Count = *(PUSHORT) pTmp;
4531 Count = (pTmp[1]<<8) + pTmp[0];
4532 pTmp += sizeof(USHORT);
4534 // Parsing all unicast cipher suite
4535 while (Count > 0)
4537 // Skip OUI
4538 pTmp += 3;
4539 TmpCipher = Ndis802_11WEPDisabled;
4540 switch (*pTmp)
4542 case 1:
4543 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4544 TmpCipher = Ndis802_11Encryption1Enabled;
4545 break;
4546 case 2:
4547 TmpCipher = Ndis802_11Encryption2Enabled;
4548 break;
4549 case 4:
4550 TmpCipher = Ndis802_11Encryption3Enabled;
4551 break;
4552 default:
4553 break;
4555 if (TmpCipher > pBss->WPA.PairCipher)
4557 // Move the lower cipher suite to PairCipherAux
4558 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4559 pBss->WPA.PairCipher = TmpCipher;
4561 else
4563 pBss->WPA.PairCipherAux = TmpCipher;
4565 pTmp++;
4566 Count--;
4569 // 4. get AKM suite counts
4570 //Count = *(PUSHORT) pTmp;
4571 Count = (pTmp[1]<<8) + pTmp[0];
4572 pTmp += sizeof(USHORT);
4573 pTmp += 3;
4575 switch (*pTmp)
4577 case 1:
4578 // Set AP support WPA-enterprise mode
4579 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4580 pBss->AuthMode = Ndis802_11AuthModeWPA;
4581 else
4582 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4583 break;
4584 case 2:
4585 // Set AP support WPA-PSK mode
4586 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4587 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4588 else
4589 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4590 break;
4591 default:
4592 break;
4594 pTmp += 1;
4596 // Fixed for WPA-None
4597 if (pBss->BssType == BSS_ADHOC)
4599 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4600 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4601 pBss->WepStatus = pBss->WPA.GroupCipher;
4602 // Patched bugs for old driver
4603 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4604 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4606 else
4607 pBss->WepStatus = pBss->WPA.PairCipher;
4609 // Check the Pair & Group, if different, turn on mixed mode flag
4610 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4611 pBss->WPA.bMixMode = TRUE;
4613 break;
4615 case IE_RSN:
4616 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4618 // 0. Version must be 1
4619 if (le2cpu16(pRsnHeader->Version) != 1)
4620 break;
4621 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4623 // 1. Check group cipher
4624 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4625 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4626 break;
4628 // Parse group cipher
4629 switch (pCipher->Type)
4631 case 1:
4632 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4633 break;
4634 case 5:
4635 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4636 break;
4637 case 2:
4638 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4639 break;
4640 case 4:
4641 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4642 break;
4643 default:
4644 break;
4646 // set to correct offset for next parsing
4647 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4649 // 2. Get pairwise cipher counts
4650 //Count = *(PUSHORT) pTmp;
4651 Count = (pTmp[1]<<8) + pTmp[0];
4652 pTmp += sizeof(USHORT);
4654 // 3. Get pairwise cipher
4655 // Parsing all unicast cipher suite
4656 while (Count > 0)
4658 // Skip OUI
4659 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4660 TmpCipher = Ndis802_11WEPDisabled;
4661 switch (pCipher->Type)
4663 case 1:
4664 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4665 TmpCipher = Ndis802_11Encryption1Enabled;
4666 break;
4667 case 2:
4668 TmpCipher = Ndis802_11Encryption2Enabled;
4669 break;
4670 case 4:
4671 TmpCipher = Ndis802_11Encryption3Enabled;
4672 break;
4673 default:
4674 break;
4676 if (TmpCipher > pBss->WPA2.PairCipher)
4678 // Move the lower cipher suite to PairCipherAux
4679 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4680 pBss->WPA2.PairCipher = TmpCipher;
4682 else
4684 pBss->WPA2.PairCipherAux = TmpCipher;
4686 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4687 Count--;
4690 // 4. get AKM suite counts
4691 //Count = *(PUSHORT) pTmp;
4692 Count = (pTmp[1]<<8) + pTmp[0];
4693 pTmp += sizeof(USHORT);
4695 // 5. Get AKM ciphers
4696 // Parsing all AKM ciphers
4697 while (Count > 0)
4699 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4700 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4701 break;
4703 switch (pAKM->Type)
4705 case 1:
4706 // Set AP support WPA-enterprise mode
4707 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4708 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4709 else
4710 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4711 break;
4712 case 2:
4713 // Set AP support WPA-PSK mode
4714 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4715 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4716 else
4717 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4718 break;
4719 default:
4720 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4721 pBss->AuthMode = Ndis802_11AuthModeMax;
4722 else
4723 pBss->AuthModeAux = Ndis802_11AuthModeMax;
4724 break;
4726 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4727 Count--;
4730 // Fixed for WPA-None
4731 if (pBss->BssType == BSS_ADHOC)
4733 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4734 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4735 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4736 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4737 pBss->WepStatus = pBss->WPA.GroupCipher;
4738 // Patched bugs for old driver
4739 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4740 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4742 pBss->WepStatus = pBss->WPA2.PairCipher;
4744 // 6. Get RSN capability
4745 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4746 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4747 pTmp += sizeof(USHORT);
4749 // Check the Pair & Group, if different, turn on mixed mode flag
4750 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4751 pBss->WPA2.bMixMode = TRUE;
4753 break;
4754 default:
4755 break;
4757 Length -= (pEid->Len + 2);
4761 // ===========================================================================================
4762 // mac_table.c
4763 // ===========================================================================================
4765 /*! \brief generates a random mac address value for IBSS BSSID
4766 * \param Addr the bssid location
4767 * \return none
4768 * \pre
4769 * \post
4771 VOID MacAddrRandomBssid(
4772 IN PRTMP_ADAPTER pAd,
4773 OUT PUCHAR pAddr)
4775 INT i;
4777 for (i = 0; i < MAC_ADDR_LEN; i++)
4779 pAddr[i] = RandomByte(pAd);
4782 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4785 /*! \brief init the management mac frame header
4786 * \param p_hdr mac header
4787 * \param subtype subtype of the frame
4788 * \param p_ds destination address, don't care if it is a broadcast address
4789 * \return none
4790 * \pre the station has the following information in the pAd->StaCfg
4791 * - bssid
4792 * - station address
4793 * \post
4794 * \note this function initializes the following field
4796 IRQL = PASSIVE_LEVEL
4797 IRQL = DISPATCH_LEVEL
4800 VOID MgtMacHeaderInit(
4801 IN PRTMP_ADAPTER pAd,
4802 IN OUT PHEADER_802_11 pHdr80211,
4803 IN UCHAR SubType,
4804 IN UCHAR ToDs,
4805 IN PUCHAR pDA,
4806 IN PUCHAR pBssid)
4808 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4810 pHdr80211->FC.Type = BTYPE_MGMT;
4811 pHdr80211->FC.SubType = SubType;
4812 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4813 // pHdr80211->FC.Type = BTYPE_CNTL;
4814 pHdr80211->FC.ToDs = ToDs;
4815 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4816 #ifdef CONFIG_STA_SUPPORT
4817 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4818 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4819 #endif // CONFIG_STA_SUPPORT //
4820 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4823 // ===========================================================================================
4824 // mem_mgmt.c
4825 // ===========================================================================================
4827 /*!***************************************************************************
4828 * This routine build an outgoing frame, and fill all information specified
4829 * in argument list to the frame body. The actual frame size is the summation
4830 * of all arguments.
4831 * input params:
4832 * Buffer - pointer to a pre-allocated memory segment
4833 * args - a list of <int arg_size, arg> pairs.
4834 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4835 * function will FAIL!!!
4836 * return:
4837 * Size of the buffer
4838 * usage:
4839 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4841 IRQL = PASSIVE_LEVEL
4842 IRQL = DISPATCH_LEVEL
4844 ****************************************************************************/
4845 ULONG MakeOutgoingFrame(
4846 OUT UCHAR *Buffer,
4847 OUT ULONG *FrameLen, ...)
4849 UCHAR *p;
4850 int leng;
4851 ULONG TotLeng;
4852 va_list Args;
4854 // calculates the total length
4855 TotLeng = 0;
4856 va_start(Args, FrameLen);
4859 leng = va_arg(Args, int);
4860 if (leng == END_OF_ARGS)
4862 break;
4864 p = va_arg(Args, PVOID);
4865 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4866 TotLeng = TotLeng + leng;
4867 } while(TRUE);
4869 va_end(Args); /* clean up */
4870 *FrameLen = TotLeng;
4871 return TotLeng;
4874 // ===========================================================================================
4875 // mlme_queue.c
4876 // ===========================================================================================
4878 /*! \brief Initialize The MLME Queue, used by MLME Functions
4879 * \param *Queue The MLME Queue
4880 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4881 * \pre
4882 * \post
4883 * \note Because this is done only once (at the init stage), no need to be locked
4885 IRQL = PASSIVE_LEVEL
4888 NDIS_STATUS MlmeQueueInit(
4889 IN MLME_QUEUE *Queue)
4891 INT i;
4893 NdisAllocateSpinLock(&Queue->Lock);
4895 Queue->Num = 0;
4896 Queue->Head = 0;
4897 Queue->Tail = 0;
4899 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4901 Queue->Entry[i].Occupied = FALSE;
4902 Queue->Entry[i].MsgLen = 0;
4903 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4906 return NDIS_STATUS_SUCCESS;
4909 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4910 * \param *Queue The MLME Queue
4911 * \param Machine The State Machine Id
4912 * \param MsgType The Message Type
4913 * \param MsgLen The Message length
4914 * \param *Msg The message pointer
4915 * \return TRUE if enqueue is successful, FALSE if the queue is full
4916 * \pre
4917 * \post
4918 * \note The message has to be initialized
4920 IRQL = PASSIVE_LEVEL
4921 IRQL = DISPATCH_LEVEL
4924 BOOLEAN MlmeEnqueue(
4925 IN PRTMP_ADAPTER pAd,
4926 IN ULONG Machine,
4927 IN ULONG MsgType,
4928 IN ULONG MsgLen,
4929 IN VOID *Msg)
4931 INT Tail;
4932 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4934 // Do nothing if the driver is starting halt state.
4935 // This might happen when timer already been fired before cancel timer with mlmehalt
4936 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4937 return FALSE;
4939 // First check the size, it MUST not exceed the mlme queue size
4940 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4942 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4943 return FALSE;
4946 if (MlmeQueueFull(Queue))
4948 return FALSE;
4951 NdisAcquireSpinLock(&(Queue->Lock));
4952 Tail = Queue->Tail;
4953 Queue->Tail++;
4954 Queue->Num++;
4955 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4957 Queue->Tail = 0;
4960 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4961 Queue->Entry[Tail].Occupied = TRUE;
4962 Queue->Entry[Tail].Machine = Machine;
4963 Queue->Entry[Tail].MsgType = MsgType;
4964 Queue->Entry[Tail].MsgLen = MsgLen;
4966 if (Msg != NULL)
4968 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4971 NdisReleaseSpinLock(&(Queue->Lock));
4972 return TRUE;
4975 /*! \brief This function is used when Recv gets a MLME message
4976 * \param *Queue The MLME Queue
4977 * \param TimeStampHigh The upper 32 bit of timestamp
4978 * \param TimeStampLow The lower 32 bit of timestamp
4979 * \param Rssi The receiving RSSI strength
4980 * \param MsgLen The length of the message
4981 * \param *Msg The message pointer
4982 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4983 * \pre
4984 * \post
4986 IRQL = DISPATCH_LEVEL
4989 BOOLEAN MlmeEnqueueForRecv(
4990 IN PRTMP_ADAPTER pAd,
4991 IN ULONG Wcid,
4992 IN ULONG TimeStampHigh,
4993 IN ULONG TimeStampLow,
4994 IN UCHAR Rssi0,
4995 IN UCHAR Rssi1,
4996 IN UCHAR Rssi2,
4997 IN ULONG MsgLen,
4998 IN VOID *Msg,
4999 IN UCHAR Signal)
5001 INT Tail, Machine;
5002 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
5003 INT MsgType;
5004 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
5006 #ifdef RALINK_ATE
5007 /* Nothing to do in ATE mode */
5008 if(ATE_ON(pAd))
5009 return FALSE;
5010 #endif // RALINK_ATE //
5012 // Do nothing if the driver is starting halt state.
5013 // This might happen when timer already been fired before cancel timer with mlmehalt
5014 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
5016 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
5017 return FALSE;
5020 // First check the size, it MUST not exceed the mlme queue size
5021 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
5023 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
5024 return FALSE;
5027 if (MlmeQueueFull(Queue))
5029 return FALSE;
5032 #ifdef CONFIG_STA_SUPPORT
5033 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5035 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
5037 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
5038 return FALSE;
5041 #endif // CONFIG_STA_SUPPORT //
5043 // OK, we got all the informations, it is time to put things into queue
5044 NdisAcquireSpinLock(&(Queue->Lock));
5045 Tail = Queue->Tail;
5046 Queue->Tail++;
5047 Queue->Num++;
5048 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
5050 Queue->Tail = 0;
5052 Queue->Entry[Tail].Occupied = TRUE;
5053 Queue->Entry[Tail].Machine = Machine;
5054 Queue->Entry[Tail].MsgType = MsgType;
5055 Queue->Entry[Tail].MsgLen = MsgLen;
5056 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
5057 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
5058 Queue->Entry[Tail].Rssi0 = Rssi0;
5059 Queue->Entry[Tail].Rssi1 = Rssi1;
5060 Queue->Entry[Tail].Rssi2 = Rssi2;
5061 Queue->Entry[Tail].Signal = Signal;
5062 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
5064 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
5066 if (Msg != NULL)
5068 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
5071 NdisReleaseSpinLock(&(Queue->Lock));
5073 RTMP_MLME_HANDLER(pAd);
5075 return TRUE;
5079 /*! \brief Dequeue a message from the MLME Queue
5080 * \param *Queue The MLME Queue
5081 * \param *Elem The message dequeued from MLME Queue
5082 * \return TRUE if the Elem contains something, FALSE otherwise
5083 * \pre
5084 * \post
5086 IRQL = DISPATCH_LEVEL
5089 BOOLEAN MlmeDequeue(
5090 IN MLME_QUEUE *Queue,
5091 OUT MLME_QUEUE_ELEM **Elem)
5093 NdisAcquireSpinLock(&(Queue->Lock));
5094 *Elem = &(Queue->Entry[Queue->Head]);
5095 Queue->Num--;
5096 Queue->Head++;
5097 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
5099 Queue->Head = 0;
5101 NdisReleaseSpinLock(&(Queue->Lock));
5102 return TRUE;
5105 // IRQL = DISPATCH_LEVEL
5106 VOID MlmeRestartStateMachine(
5107 IN PRTMP_ADAPTER pAd)
5109 #ifdef RTMP_MAC_PCI
5110 MLME_QUEUE_ELEM *Elem = NULL;
5111 #endif // RTMP_MAC_PCI //
5112 #ifdef CONFIG_STA_SUPPORT
5113 BOOLEAN Cancelled;
5114 #endif // CONFIG_STA_SUPPORT //
5116 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
5118 #ifdef RTMP_MAC_PCI
5119 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5120 if(pAd->Mlme.bRunning)
5122 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5123 return;
5125 else
5127 pAd->Mlme.bRunning = TRUE;
5129 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5131 // Remove all Mlme queues elements
5132 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
5134 //From message type, determine which state machine I should drive
5135 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
5137 // free MLME element
5138 Elem->Occupied = FALSE;
5139 Elem->MsgLen = 0;
5142 else {
5143 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
5146 #endif // RTMP_MAC_PCI //
5148 #ifdef CONFIG_STA_SUPPORT
5149 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5151 #ifdef QOS_DLS_SUPPORT
5152 UCHAR i;
5153 #endif // QOS_DLS_SUPPORT //
5154 // Cancel all timer events
5155 // Be careful to cancel new added timer
5156 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
5157 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
5158 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
5159 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
5160 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
5161 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
5163 #ifdef QOS_DLS_SUPPORT
5164 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
5166 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
5168 #endif // QOS_DLS_SUPPORT //
5170 #endif // CONFIG_STA_SUPPORT //
5172 // Change back to original channel in case of doing scan
5173 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
5174 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
5176 // Resume MSDU which is turned off durning scan
5177 RTMPResumeMsduTransmission(pAd);
5179 #ifdef CONFIG_STA_SUPPORT
5180 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5182 // Set all state machines back IDLE
5183 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5184 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5185 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5186 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5187 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5188 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5189 #ifdef QOS_DLS_SUPPORT
5190 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5191 #endif // QOS_DLS_SUPPORT //
5193 #endif // CONFIG_STA_SUPPORT //
5195 #ifdef RTMP_MAC_PCI
5196 // Remove running state
5197 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5198 pAd->Mlme.bRunning = FALSE;
5199 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5200 #endif // RTMP_MAC_PCI //
5203 /*! \brief test if the MLME Queue is empty
5204 * \param *Queue The MLME Queue
5205 * \return TRUE if the Queue is empty, FALSE otherwise
5206 * \pre
5207 * \post
5209 IRQL = DISPATCH_LEVEL
5212 BOOLEAN MlmeQueueEmpty(
5213 IN MLME_QUEUE *Queue)
5215 BOOLEAN Ans;
5217 NdisAcquireSpinLock(&(Queue->Lock));
5218 Ans = (Queue->Num == 0);
5219 NdisReleaseSpinLock(&(Queue->Lock));
5221 return Ans;
5224 /*! \brief test if the MLME Queue is full
5225 * \param *Queue The MLME Queue
5226 * \return TRUE if the Queue is empty, FALSE otherwise
5227 * \pre
5228 * \post
5230 IRQL = PASSIVE_LEVEL
5231 IRQL = DISPATCH_LEVEL
5234 BOOLEAN MlmeQueueFull(
5235 IN MLME_QUEUE *Queue)
5237 BOOLEAN Ans;
5239 NdisAcquireSpinLock(&(Queue->Lock));
5240 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5241 NdisReleaseSpinLock(&(Queue->Lock));
5243 return Ans;
5246 /*! \brief The destructor of MLME Queue
5247 * \param
5248 * \return
5249 * \pre
5250 * \post
5251 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5253 IRQL = PASSIVE_LEVEL
5256 VOID MlmeQueueDestroy(
5257 IN MLME_QUEUE *pQueue)
5259 NdisAcquireSpinLock(&(pQueue->Lock));
5260 pQueue->Num = 0;
5261 pQueue->Head = 0;
5262 pQueue->Tail = 0;
5263 NdisReleaseSpinLock(&(pQueue->Lock));
5264 NdisFreeSpinLock(&(pQueue->Lock));
5268 /*! \brief To substitute the message type if the message is coming from external
5269 * \param pFrame The frame received
5270 * \param *Machine The state machine
5271 * \param *MsgType the message type for the state machine
5272 * \return TRUE if the substitution is successful, FALSE otherwise
5273 * \pre
5274 * \post
5276 IRQL = DISPATCH_LEVEL
5279 #ifdef CONFIG_STA_SUPPORT
5280 BOOLEAN MsgTypeSubst(
5281 IN PRTMP_ADAPTER pAd,
5282 IN PFRAME_802_11 pFrame,
5283 OUT INT *Machine,
5284 OUT INT *MsgType)
5286 USHORT Seq, Alg;
5287 UCHAR EAPType;
5288 PUCHAR pData;
5290 // Pointer to start of data frames including SNAP header
5291 pData = (PUCHAR) pFrame + LENGTH_802_11;
5293 // The only data type will pass to this function is EAPOL frame
5294 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5297 *Machine = WPA_STATE_MACHINE;
5298 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5299 return (WpaMsgTypeSubst(EAPType, (INT *) MsgType));
5303 switch (pFrame->Hdr.FC.SubType)
5305 case SUBTYPE_ASSOC_REQ:
5306 *Machine = ASSOC_STATE_MACHINE;
5307 *MsgType = MT2_PEER_ASSOC_REQ;
5308 break;
5309 case SUBTYPE_ASSOC_RSP:
5310 *Machine = ASSOC_STATE_MACHINE;
5311 *MsgType = MT2_PEER_ASSOC_RSP;
5312 break;
5313 case SUBTYPE_REASSOC_REQ:
5314 *Machine = ASSOC_STATE_MACHINE;
5315 *MsgType = MT2_PEER_REASSOC_REQ;
5316 break;
5317 case SUBTYPE_REASSOC_RSP:
5318 *Machine = ASSOC_STATE_MACHINE;
5319 *MsgType = MT2_PEER_REASSOC_RSP;
5320 break;
5321 case SUBTYPE_PROBE_REQ:
5322 *Machine = SYNC_STATE_MACHINE;
5323 *MsgType = MT2_PEER_PROBE_REQ;
5324 break;
5325 case SUBTYPE_PROBE_RSP:
5326 *Machine = SYNC_STATE_MACHINE;
5327 *MsgType = MT2_PEER_PROBE_RSP;
5328 break;
5329 case SUBTYPE_BEACON:
5330 *Machine = SYNC_STATE_MACHINE;
5331 *MsgType = MT2_PEER_BEACON;
5332 break;
5333 case SUBTYPE_ATIM:
5334 *Machine = SYNC_STATE_MACHINE;
5335 *MsgType = MT2_PEER_ATIM;
5336 break;
5337 case SUBTYPE_DISASSOC:
5338 *Machine = ASSOC_STATE_MACHINE;
5339 *MsgType = MT2_PEER_DISASSOC_REQ;
5340 break;
5341 case SUBTYPE_AUTH:
5342 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5343 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5344 NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT));
5345 if (Seq == 1 || Seq == 3)
5347 *Machine = AUTH_RSP_STATE_MACHINE;
5348 *MsgType = MT2_PEER_AUTH_ODD;
5350 else if (Seq == 2 || Seq == 4)
5352 if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY)
5354 *Machine = AUTH_STATE_MACHINE;
5355 *MsgType = MT2_PEER_AUTH_EVEN;
5358 else
5360 return FALSE;
5362 break;
5363 case SUBTYPE_DEAUTH:
5364 *Machine = AUTH_RSP_STATE_MACHINE;
5365 *MsgType = MT2_PEER_DEAUTH;
5366 break;
5367 case SUBTYPE_ACTION:
5368 *Machine = ACTION_STATE_MACHINE;
5369 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5370 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5372 *MsgType = MT2_ACT_INVALID;
5374 else
5376 *MsgType = (pFrame->Octet[0]&0x7F);
5378 break;
5379 default:
5380 return FALSE;
5381 break;
5384 return TRUE;
5386 #endif // CONFIG_STA_SUPPORT //
5388 // ===========================================================================================
5389 // state_machine.c
5390 // ===========================================================================================
5392 /*! \brief Initialize the state machine.
5393 * \param *S pointer to the state machine
5394 * \param Trans State machine transition function
5395 * \param StNr number of states
5396 * \param MsgNr number of messages
5397 * \param DefFunc default function, when there is invalid state/message combination
5398 * \param InitState initial state of the state machine
5399 * \param Base StateMachine base, internal use only
5400 * \pre p_sm should be a legal pointer
5401 * \post
5403 IRQL = PASSIVE_LEVEL
5406 VOID StateMachineInit(
5407 IN STATE_MACHINE *S,
5408 IN STATE_MACHINE_FUNC Trans[],
5409 IN ULONG StNr,
5410 IN ULONG MsgNr,
5411 IN STATE_MACHINE_FUNC DefFunc,
5412 IN ULONG InitState,
5413 IN ULONG Base)
5415 ULONG i, j;
5417 // set number of states and messages
5418 S->NrState = StNr;
5419 S->NrMsg = MsgNr;
5420 S->Base = Base;
5422 S->TransFunc = Trans;
5424 // init all state transition to default function
5425 for (i = 0; i < StNr; i++)
5427 for (j = 0; j < MsgNr; j++)
5429 S->TransFunc[i * MsgNr + j] = DefFunc;
5433 // set the starting state
5434 S->CurrState = InitState;
5437 /*! \brief This function fills in the function pointer into the cell in the state machine
5438 * \param *S pointer to the state machine
5439 * \param St state
5440 * \param Msg incoming message
5441 * \param f the function to be executed when (state, message) combination occurs at the state machine
5442 * \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
5443 * \post
5445 IRQL = PASSIVE_LEVEL
5448 VOID StateMachineSetAction(
5449 IN STATE_MACHINE *S,
5450 IN ULONG St,
5451 IN ULONG Msg,
5452 IN STATE_MACHINE_FUNC Func)
5454 ULONG MsgIdx;
5456 MsgIdx = Msg - S->Base;
5458 if (St < S->NrState && MsgIdx < S->NrMsg)
5460 // boundary checking before setting the action
5461 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5465 /*! \brief This function does the state transition
5466 * \param *Adapter the NIC adapter pointer
5467 * \param *S the state machine
5468 * \param *Elem the message to be executed
5469 * \return None
5471 IRQL = DISPATCH_LEVEL
5474 VOID StateMachinePerformAction(
5475 IN PRTMP_ADAPTER pAd,
5476 IN STATE_MACHINE *S,
5477 IN MLME_QUEUE_ELEM *Elem)
5479 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5483 ==========================================================================
5484 Description:
5485 The drop function, when machine executes this, the message is simply
5486 ignored. This function does nothing, the message is freed in
5487 StateMachinePerformAction()
5488 ==========================================================================
5490 VOID Drop(
5491 IN PRTMP_ADAPTER pAd,
5492 IN MLME_QUEUE_ELEM *Elem)
5496 // ===========================================================================================
5497 // lfsr.c
5498 // ===========================================================================================
5501 ==========================================================================
5502 Description:
5504 IRQL = PASSIVE_LEVEL
5506 ==========================================================================
5508 VOID LfsrInit(
5509 IN PRTMP_ADAPTER pAd,
5510 IN ULONG Seed)
5512 if (Seed == 0)
5513 pAd->Mlme.ShiftReg = 1;
5514 else
5515 pAd->Mlme.ShiftReg = Seed;
5519 ==========================================================================
5520 Description:
5521 ==========================================================================
5523 UCHAR RandomByte(
5524 IN PRTMP_ADAPTER pAd)
5526 ULONG i;
5527 UCHAR R, Result;
5529 R = 0;
5531 if (pAd->Mlme.ShiftReg == 0)
5532 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5534 for (i = 0; i < 8; i++)
5536 if (pAd->Mlme.ShiftReg & 0x00000001)
5538 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5539 Result = 1;
5541 else
5543 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5544 Result = 0;
5546 R = (R << 1) | Result;
5549 return R;
5554 ========================================================================
5556 Routine Description:
5557 Verify the support rate for different PHY type
5559 Arguments:
5560 pAd Pointer to our adapter
5562 Return Value:
5563 None
5565 IRQL = PASSIVE_LEVEL
5567 ========================================================================
5569 VOID RTMPCheckRates(
5570 IN PRTMP_ADAPTER pAd,
5571 IN OUT UCHAR SupRate[],
5572 IN OUT UCHAR *SupRateLen)
5574 UCHAR RateIdx, i, j;
5575 UCHAR NewRate[12], NewRateLen;
5577 NewRateLen = 0;
5579 if (pAd->CommonCfg.PhyMode == PHY_11B)
5580 RateIdx = 4;
5581 else
5582 RateIdx = 12;
5584 // Check for support rates exclude basic rate bit
5585 for (i = 0; i < *SupRateLen; i++)
5586 for (j = 0; j < RateIdx; j++)
5587 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5588 NewRate[NewRateLen++] = SupRate[i];
5590 *SupRateLen = NewRateLen;
5591 NdisMoveMemory(SupRate, NewRate, NewRateLen);
5594 #ifdef CONFIG_STA_SUPPORT
5595 #ifdef DOT11_N_SUPPORT
5596 BOOLEAN RTMPCheckChannel(
5597 IN PRTMP_ADAPTER pAd,
5598 IN UCHAR CentralChannel,
5599 IN UCHAR Channel)
5601 UCHAR k;
5602 UCHAR UpperChannel = 0, LowerChannel = 0;
5603 UCHAR NoEffectChannelinList = 0;
5605 // Find upper and lower channel according to 40MHz current operation.
5606 if (CentralChannel < Channel)
5608 UpperChannel = Channel;
5609 if (CentralChannel > 2)
5610 LowerChannel = CentralChannel - 2;
5611 else
5612 return FALSE;
5614 else if (CentralChannel > Channel)
5616 UpperChannel = CentralChannel + 2;
5617 LowerChannel = Channel;
5620 for (k = 0;k < pAd->ChannelListNum;k++)
5622 if (pAd->ChannelList[k].Channel == UpperChannel)
5624 NoEffectChannelinList ++;
5626 if (pAd->ChannelList[k].Channel == LowerChannel)
5628 NoEffectChannelinList ++;
5632 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
5633 if (NoEffectChannelinList == 2)
5634 return TRUE;
5635 else
5636 return FALSE;
5640 ========================================================================
5642 Routine Description:
5643 Verify the support rate for HT phy type
5645 Arguments:
5646 pAd Pointer to our adapter
5648 Return Value:
5649 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
5651 IRQL = PASSIVE_LEVEL
5653 ========================================================================
5655 BOOLEAN RTMPCheckHt(
5656 IN PRTMP_ADAPTER pAd,
5657 IN UCHAR Wcid,
5658 IN HT_CAPABILITY_IE *pHtCapability,
5659 IN ADD_HT_INFO_IE *pAddHtInfo)
5661 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5662 return FALSE;
5664 // If use AMSDU, set flag.
5665 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
5666 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
5667 // Save Peer Capability
5668 if (pHtCapability->HtCapInfo.ShortGIfor20)
5669 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
5670 if (pHtCapability->HtCapInfo.ShortGIfor40)
5671 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
5672 if (pHtCapability->HtCapInfo.TxSTBC)
5673 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
5674 if (pHtCapability->HtCapInfo.RxSTBC)
5675 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
5676 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
5678 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
5681 if (Wcid < MAX_LEN_OF_MAC_TABLE)
5683 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
5686 // Will check ChannelWidth for MCSSet[4] below
5687 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
5688 switch (pAd->CommonCfg.RxStream)
5690 case 1:
5691 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5692 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5693 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5694 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5695 break;
5696 case 2:
5697 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5698 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5699 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5700 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5701 break;
5702 case 3:
5703 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5704 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5705 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5706 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5707 break;
5710 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
5712 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5713 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5714 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
5716 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
5718 // Send Assoc Req with my HT capability.
5719 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5720 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
5721 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
5722 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
5723 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
5724 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
5725 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5726 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5727 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
5728 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
5729 if (pAd->CommonCfg.bRdg)
5731 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
5732 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5735 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
5736 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
5738 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5739 return TRUE;
5741 #endif // DOT11_N_SUPPORT //
5742 #endif // CONFIG_STA_SUPPORT //
5745 ========================================================================
5747 Routine Description:
5748 Verify the support rate for different PHY type
5750 Arguments:
5751 pAd Pointer to our adapter
5753 Return Value:
5754 None
5756 IRQL = PASSIVE_LEVEL
5758 ========================================================================
5760 VOID RTMPUpdateMlmeRate(
5761 IN PRTMP_ADAPTER pAd)
5763 UCHAR MinimumRate;
5764 UCHAR ProperMlmeRate; //= RATE_54;
5765 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
5766 BOOLEAN bMatch = FALSE;
5768 switch (pAd->CommonCfg.PhyMode)
5770 case PHY_11B:
5771 ProperMlmeRate = RATE_11;
5772 MinimumRate = RATE_1;
5773 break;
5774 case PHY_11BG_MIXED:
5775 #ifdef DOT11_N_SUPPORT
5776 case PHY_11ABGN_MIXED:
5777 case PHY_11BGN_MIXED:
5778 #endif // DOT11_N_SUPPORT //
5779 if ((pAd->MlmeAux.SupRateLen == 4) &&
5780 (pAd->MlmeAux.ExtRateLen == 0))
5781 // B only AP
5782 ProperMlmeRate = RATE_11;
5783 else
5784 ProperMlmeRate = RATE_24;
5786 if (pAd->MlmeAux.Channel <= 14)
5787 MinimumRate = RATE_1;
5788 else
5789 MinimumRate = RATE_6;
5790 break;
5791 case PHY_11A:
5792 #ifdef DOT11_N_SUPPORT
5793 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
5794 case PHY_11GN_MIXED:
5795 case PHY_11AGN_MIXED:
5796 case PHY_11AN_MIXED:
5797 case PHY_11N_5G:
5798 #endif // DOT11_N_SUPPORT //
5799 ProperMlmeRate = RATE_24;
5800 MinimumRate = RATE_6;
5801 break;
5802 case PHY_11ABG_MIXED:
5803 ProperMlmeRate = RATE_24;
5804 if (pAd->MlmeAux.Channel <= 14)
5805 MinimumRate = RATE_1;
5806 else
5807 MinimumRate = RATE_6;
5808 break;
5809 default: // error
5810 ProperMlmeRate = RATE_1;
5811 MinimumRate = RATE_1;
5812 break;
5815 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
5817 for (j = 0; j < RateIdx; j++)
5819 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5821 if (j == ProperMlmeRate)
5823 bMatch = TRUE;
5824 break;
5829 if (bMatch)
5830 break;
5833 if (bMatch == FALSE)
5835 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
5837 for (j = 0; j < RateIdx; j++)
5839 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
5841 if (j == ProperMlmeRate)
5843 bMatch = TRUE;
5844 break;
5849 if (bMatch)
5850 break;
5854 if (bMatch == FALSE)
5856 ProperMlmeRate = MinimumRate;
5859 pAd->CommonCfg.MlmeRate = MinimumRate;
5860 pAd->CommonCfg.RtsRate = ProperMlmeRate;
5861 if (pAd->CommonCfg.MlmeRate >= RATE_6)
5863 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
5864 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5865 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
5866 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5868 else
5870 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5871 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
5872 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
5873 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
5876 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
5879 CHAR RTMPMaxRssi(
5880 IN PRTMP_ADAPTER pAd,
5881 IN CHAR Rssi0,
5882 IN CHAR Rssi1,
5883 IN CHAR Rssi2)
5885 CHAR larger = -127;
5887 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
5889 larger = Rssi0;
5892 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
5894 larger = max(Rssi0, Rssi1);
5897 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
5899 larger = max(larger, Rssi2);
5902 if (larger == -127)
5903 larger = 0;
5905 return larger;
5910 ========================================================================
5911 Routine Description:
5912 Periodic evaluate antenna link status
5914 Arguments:
5915 pAd - Adapter pointer
5917 Return Value:
5918 None
5920 ========================================================================
5922 VOID AsicEvaluateRxAnt(
5923 IN PRTMP_ADAPTER pAd)
5925 #ifdef CONFIG_STA_SUPPORT
5926 UCHAR BBPR3 = 0;
5927 #endif // CONFIG_STA_SUPPORT //
5929 #ifdef RALINK_ATE
5930 if (ATE_ON(pAd))
5931 return;
5932 #endif // RALINK_ATE //
5934 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5935 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5936 fRTMP_ADAPTER_RADIO_OFF |
5937 fRTMP_ADAPTER_NIC_NOT_EXIST |
5938 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5939 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5940 #ifdef RT3090
5941 || (pAd->bPCIclkOff == TRUE)
5942 #endif // RT3090 //
5943 #ifdef ANT_DIVERSITY_SUPPORT
5944 || (pAd->EepromAccess)
5945 #endif // ANT_DIVERSITY_SUPPORT //
5947 return;
5949 #ifdef ANT_DIVERSITY_SUPPORT
5950 if ((pAd->NicConfig2.field.AntDiversity) && (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_ENABLE))
5952 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
5953 // one is antenna diversity:there is only one antenna can rx and tx
5954 // the other is failed antenna remove:two physical antenna can rx and tx
5955 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
5956 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
5958 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
5960 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
5961 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
5962 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
5964 // a one-shot timer to end the evalution
5965 // dynamic adjust antenna evaluation period according to the traffic
5966 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5967 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
5968 else
5969 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
5971 else
5972 #endif // ANT_DIVERSITY_SUPPORT //
5974 #ifdef CONFIG_STA_SUPPORT
5975 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5978 if (pAd->StaCfg.Psm == PWR_SAVE)
5979 return;
5981 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5982 BBPR3 &= (~0x18);
5983 if(pAd->Antenna.field.RxPath == 3)
5985 BBPR3 |= (0x10);
5987 else if(pAd->Antenna.field.RxPath == 2)
5989 BBPR3 |= (0x8);
5991 else if(pAd->Antenna.field.RxPath == 1)
5993 BBPR3 |= (0x0);
5995 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5996 #ifdef RTMP_MAC_PCI
5997 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5998 pAd->StaCfg.BBPR3 = BBPR3;
5999 #endif // RTMP_MAC_PCI //
6000 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
6003 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
6004 pAd->RalinkCounters.OneSecTxRetryOkCount +
6005 pAd->RalinkCounters.OneSecTxFailCount;
6007 // dynamic adjust antenna evaluation period according to the traffic
6008 if (TxTotalCnt > 50)
6010 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
6011 pAd->Mlme.bLowThroughput = FALSE;
6013 else
6015 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
6016 pAd->Mlme.bLowThroughput = TRUE;
6020 #endif // CONFIG_STA_SUPPORT //
6025 ========================================================================
6026 Routine Description:
6027 After evaluation, check antenna link status
6029 Arguments:
6030 pAd - Adapter pointer
6032 Return Value:
6033 None
6035 ========================================================================
6037 VOID AsicRxAntEvalTimeout(
6038 IN PVOID SystemSpecific1,
6039 IN PVOID FunctionContext,
6040 IN PVOID SystemSpecific2,
6041 IN PVOID SystemSpecific3)
6043 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
6044 BOOLEAN bSwapAnt = FALSE;
6045 #ifdef CONFIG_STA_SUPPORT
6046 UCHAR BBPR3 = 0;
6047 CHAR larger = -127, rssi0, rssi1, rssi2;
6048 #endif // CONFIG_STA_SUPPORT //
6050 #ifdef RALINK_ATE
6051 if (ATE_ON(pAd))
6052 return;
6053 #endif // RALINK_ATE //
6055 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
6056 fRTMP_ADAPTER_HALT_IN_PROGRESS |
6057 fRTMP_ADAPTER_RADIO_OFF |
6058 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
6059 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6060 #ifdef RT3090
6061 || (pAd->bPCIclkOff == TRUE)
6062 #endif // RT3090 //
6063 #ifdef ANT_DIVERSITY_SUPPORT
6064 || (pAd->EepromAccess)
6065 #endif // ANT_DIVERSITY_SUPPORT //
6067 return;
6069 #ifdef ANT_DIVERSITY_SUPPORT
6070 if ((pAd->NicConfig2.field.AntDiversity) && (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_ENABLE))
6072 #ifdef CONFIG_STA_SUPPORT
6073 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6074 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
6075 bSwapAnt = TRUE;
6076 #endif // CONFIG_STA_SUPPORT //
6077 if (bSwapAnt == TRUE)
6079 UCHAR temp;
6082 // select PrimaryRxAntPair
6083 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
6084 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
6086 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6087 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6088 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6090 #ifdef CONFIG_STA_SUPPORT
6091 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
6092 #endif // CONFIG_STA_SUPPORT //
6093 // pAd->RxAnt.EvaluateStableCnt = 0;
6095 else
6097 // if the evaluated antenna is not better than original, switch back to original antenna
6098 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6099 pAd->RxAnt.EvaluateStableCnt ++;
6102 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
6104 #ifdef CONFIG_STA_SUPPORT
6105 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
6106 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
6107 #endif // CONFIG_STA_SUPPORT //
6109 else
6110 #endif // ANT_DIVERSITY_SUPPORT //
6112 #ifdef CONFIG_STA_SUPPORT
6113 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6115 if (pAd->StaCfg.Psm == PWR_SAVE)
6116 return;
6119 // if the traffic is low, use average rssi as the criteria
6120 if (pAd->Mlme.bLowThroughput == TRUE)
6122 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
6123 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
6124 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
6126 else
6128 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
6129 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
6130 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
6133 if(pAd->Antenna.field.RxPath == 3)
6135 larger = max(rssi0, rssi1);
6137 if (larger > (rssi2 + 20))
6138 pAd->Mlme.RealRxPath = 2;
6139 else
6140 pAd->Mlme.RealRxPath = 3;
6142 else if(pAd->Antenna.field.RxPath == 2)
6144 if (rssi0 > (rssi1 + 20))
6145 pAd->Mlme.RealRxPath = 1;
6146 else
6147 pAd->Mlme.RealRxPath = 2;
6150 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
6151 BBPR3 &= (~0x18);
6152 if(pAd->Mlme.RealRxPath == 3)
6154 BBPR3 |= (0x10);
6156 else if(pAd->Mlme.RealRxPath == 2)
6158 BBPR3 |= (0x8);
6160 else if(pAd->Mlme.RealRxPath == 1)
6162 BBPR3 |= (0x0);
6164 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
6165 #ifdef RTMP_MAC_PCI
6166 pAd->StaCfg.BBPR3 = BBPR3;
6167 #endif // RTMP_MAC_PCI //
6169 #endif // CONFIG_STA_SUPPORT //
6174 VOID APSDPeriodicExec(
6175 IN PVOID SystemSpecific1,
6176 IN PVOID FunctionContext,
6177 IN PVOID SystemSpecific2,
6178 IN PVOID SystemSpecific3)
6180 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
6182 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6183 return;
6185 pAd->CommonCfg.TriggerTimerCount++;
6187 // Driver should not send trigger frame, it should be send by application layer
6189 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
6190 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
6191 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
6193 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
6194 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
6195 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
6196 pAd->CommonCfg.TriggerTimerCount = 0;
6197 pAd->CommonCfg.bInServicePeriod = TRUE;
6202 ========================================================================
6203 Routine Description:
6204 Set/reset MAC registers according to bPiggyBack parameter
6206 Arguments:
6207 pAd - Adapter pointer
6208 bPiggyBack - Enable / Disable Piggy-Back
6210 Return Value:
6211 None
6213 ========================================================================
6215 VOID RTMPSetPiggyBack(
6216 IN PRTMP_ADAPTER pAd,
6217 IN BOOLEAN bPiggyBack)
6219 TX_LINK_CFG_STRUC TxLinkCfg;
6221 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6223 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
6224 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6228 ========================================================================
6229 Routine Description:
6230 check if this entry need to switch rate automatically
6232 Arguments:
6234 pEntry
6236 Return Value:
6237 TURE
6238 FALSE
6240 ========================================================================
6242 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
6243 IN PRTMP_ADAPTER pAd,
6244 IN PMAC_TABLE_ENTRY pEntry)
6246 BOOLEAN result = TRUE;
6249 #ifdef CONFIG_STA_SUPPORT
6250 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6252 // only associated STA counts
6253 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
6255 result = pAd->StaCfg.bAutoTxRateSwitch;
6257 else
6258 result = FALSE;
6260 #ifdef QOS_DLS_SUPPORT
6261 if (pEntry && (pEntry->ValidAsDls))
6262 result = pAd->StaCfg.bAutoTxRateSwitch;
6263 #endif // QOS_DLS_SUPPORT //
6265 #endif // CONFIG_STA_SUPPORT //
6269 return result;
6273 BOOLEAN RTMPAutoRateSwitchCheck(
6274 IN PRTMP_ADAPTER pAd)
6277 #ifdef CONFIG_STA_SUPPORT
6278 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6280 if (pAd->StaCfg.bAutoTxRateSwitch)
6281 return TRUE;
6283 #endif // CONFIG_STA_SUPPORT //
6284 return FALSE;
6289 ========================================================================
6290 Routine Description:
6291 check if this entry need to fix tx legacy rate
6293 Arguments:
6295 pEntry
6297 Return Value:
6298 TURE
6299 FALSE
6301 ========================================================================
6303 UCHAR RTMPStaFixedTxMode(
6304 IN PRTMP_ADAPTER pAd,
6305 IN PMAC_TABLE_ENTRY pEntry)
6307 UCHAR tx_mode = FIXED_TXMODE_HT;
6310 #ifdef CONFIG_STA_SUPPORT
6311 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6313 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
6315 #endif // CONFIG_STA_SUPPORT //
6317 return tx_mode;
6321 ========================================================================
6322 Routine Description:
6323 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
6325 Arguments:
6327 pEntry
6329 Return Value:
6330 TURE
6331 FALSE
6333 ========================================================================
6335 VOID RTMPUpdateLegacyTxSetting(
6336 UCHAR fixed_tx_mode,
6337 PMAC_TABLE_ENTRY pEntry)
6339 HTTRANSMIT_SETTING TransmitSetting;
6341 if (fixed_tx_mode == FIXED_TXMODE_HT)
6342 return;
6344 TransmitSetting.word = 0;
6346 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
6347 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
6349 if (fixed_tx_mode == FIXED_TXMODE_CCK)
6351 TransmitSetting.field.MODE = MODE_CCK;
6352 // CCK mode allow MCS 0~3
6353 if (TransmitSetting.field.MCS > MCS_3)
6354 TransmitSetting.field.MCS = MCS_3;
6356 else
6358 TransmitSetting.field.MODE = MODE_OFDM;
6359 // OFDM mode allow MCS 0~7
6360 if (TransmitSetting.field.MCS > MCS_7)
6361 TransmitSetting.field.MCS = MCS_7;
6364 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
6366 pEntry->HTPhyMode.word = TransmitSetting.word;
6367 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
6368 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
6372 #ifdef CONFIG_STA_SUPPORT
6374 ==========================================================================
6375 Description:
6376 dynamic tune BBP R66 to find a balance between sensibility and
6377 noise isolation
6379 IRQL = DISPATCH_LEVEL
6381 ==========================================================================
6383 VOID AsicStaBbpTuning(
6384 IN PRTMP_ADAPTER pAd)
6386 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
6387 CHAR Rssi;
6389 // 2860C did not support Fase CCA, therefore can't tune
6390 if (pAd->MACVersion == 0x28600100)
6391 return;
6394 // work as a STA
6396 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
6397 return;
6399 if ((pAd->OpMode == OPMODE_STA)
6400 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
6402 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
6403 #ifdef RTMP_MAC_PCI
6404 && (pAd->bPCIclkOff == FALSE)
6405 #endif // RTMP_MAC_PCI //
6408 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
6409 R66 = OrigR66Value;
6411 if (pAd->Antenna.field.RxPath > 1)
6412 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
6413 else
6414 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
6416 if (pAd->LatchRfRegs.Channel <= 14)
6417 { //BG band
6418 #ifdef RT30xx
6419 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
6420 // Otherwise, it will have some throughput side effect when low RSSI
6422 if (IS_RT3070(pAd)||IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
6424 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
6426 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
6427 if (OrigR66Value != R66)
6429 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6432 else
6434 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
6435 if (OrigR66Value != R66)
6437 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6441 else
6442 #endif // RT30xx //
6444 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
6446 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
6447 if (OrigR66Value != R66)
6449 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6452 else
6454 R66 = 0x2E + GET_LNA_GAIN(pAd);
6455 if (OrigR66Value != R66)
6457 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6462 else
6463 { //A band
6464 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
6466 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
6468 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
6469 if (OrigR66Value != R66)
6471 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6474 else
6476 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
6477 if (OrigR66Value != R66)
6479 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6483 else
6485 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
6487 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
6488 if (OrigR66Value != R66)
6490 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6493 else
6495 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
6496 if (OrigR66Value != R66)
6498 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6507 #endif // CONFIG_STA_SUPPORT //
6509 VOID RTMPSetAGCInitValue(
6510 IN PRTMP_ADAPTER pAd,
6511 IN UCHAR BandWidth)
6513 UCHAR R66 = 0x30;
6515 if (pAd->LatchRfRegs.Channel <= 14)
6516 { // BG band
6517 #ifdef RT30xx
6518 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6520 if (IS_RT3070(pAd)||IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
6522 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
6523 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6525 else
6526 #endif // RT30xx //
6528 R66 = 0x2E + GET_LNA_GAIN(pAd);
6529 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6532 else
6533 { //A band
6535 if (BandWidth == BW_20)
6537 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
6538 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6540 #ifdef DOT11_N_SUPPORT
6541 else
6543 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
6544 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6546 #endif // DOT11_N_SUPPORT //