2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
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. *
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. *
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. *
25 *************************************************************************
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"
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,
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,
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;
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 ==========================================================================
354 initialize the MLME task and its data structure (queue, spinlock,
355 timer, state machines).
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)
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 //
438 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
444 ==========================================================================
446 main loop of the MLME
448 Mlme has to be initialized, and there are something inside the queue
450 This function is invoked from MPSetInformation and MPReceive;
451 This task guarantee only one MlmeHandler will run.
453 IRQL = DISPATCH_LEVEL
455 ==========================================================================
458 IN PRTMP_ADAPTER pAd)
460 MLME_QUEUE_ELEM *Elem = NULL;
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);
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));
493 DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
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);
510 case AUTH_STATE_MACHINE:
511 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
513 case AUTH_RSP_STATE_MACHINE:
514 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
516 case SYNC_STATE_MACHINE:
517 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
519 case MLME_CNTL_STATE_MACHINE:
520 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
522 case WPA_PSK_STATE_MACHINE:
523 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
526 #ifdef QOS_DLS_SUPPORT
527 case DLS_STATE_MACHINE:
528 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
530 #endif // QOS_DLS_SUPPORT //
532 #endif // CONFIG_STA_SUPPORT //
534 case ACTION_STATE_MACHINE:
535 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
538 case WPA_STATE_MACHINE:
539 StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem);
544 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
549 Elem->Occupied = FALSE;
554 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
558 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
559 pAd->Mlme.bRunning = FALSE;
560 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
564 ==========================================================================
566 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
568 Adapter - NIC Adapter pointer
570 The MLME task will no longer work properly
574 ==========================================================================
577 IN PRTMP_ADAPTER pAd)
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
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);
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;
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;
684 ==========================================================================
686 This routine is executed periodically to -
687 1. Decide if it's a right time to turn on PwrMgmt bit of all
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)
707 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
710 #ifdef CONFIG_STA_SUPPORT
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)*/)
723 // Read GPIO pin2 as Hardware controlled radio state
725 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
727 //KH(PCIE PS):Added based on Jane<--
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);
741 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
743 //KH(PCIE PS):Added based on Jane-->
747 pAd->StaCfg.bHwRadio = TRUE;
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)
759 // Update extra information
760 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
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))))
782 RTMP_MLME_PRE_SANITY_CHECK(pAd);
785 /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
788 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
790 pAd->Mlme.PeriodicRound ++;
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
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 ++;
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);
866 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
868 MlmeResetRalinkCounters(pAd);
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);
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);
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));
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
941 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
943 AsicEvaluateRxAnt(pAd);
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)
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.
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);
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(
1014 if (SsidLen > MAX_LEN_OF_SSID)
1017 // Check each character value
1018 for (index = 0; index < SsidLen; index++)
1020 if (pSsid[index] < 0x20)
1028 VOID MlmeSelectTxRateTable(
1029 IN PRTMP_ADAPTER pAd,
1030 IN PMAC_TABLE_ENTRY pEntry,
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];
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)))
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))
1065 if (pAd->LatchRfRegs.Channel <= 14)
1067 *ppTable = RateSwitchTable11N2S;
1068 *pTableSize = RateSwitchTable11N2S[0];
1069 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1073 *ppTable = RateSwitchTable11N2SForABand;
1074 *pTableSize = RateSwitchTable11N2SForABand[0];
1075 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
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];
1101 *ppTable = RateSwitchTable11G;
1102 *pTableSize = RateSwitchTable11G[0];
1103 *pInitTxRateIdx = RateSwitchTable11G[1];
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)))
1116 *ppTable = RateSwitchTable11BGN1S;
1117 *pTableSize = RateSwitchTable11BGN1S[0];
1118 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
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))
1128 if (pAd->LatchRfRegs.Channel <= 14)
1130 *ppTable = RateSwitchTable11BGN2S;
1131 *pTableSize = RateSwitchTable11BGN2S[0];
1132 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1137 *ppTable = RateSwitchTable11BGN2SForABand;
1138 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1139 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
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)))
1148 *ppTable = RateSwitchTable11N1S;
1149 *pTableSize = RateSwitchTable11N1S[0];
1150 *pInitTxRateIdx = RateSwitchTable11N1S[1];
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))
1158 if (pAd->LatchRfRegs.Channel <= 14)
1160 *ppTable = RateSwitchTable11N2S;
1161 *pTableSize = RateSwitchTable11N2S[0];
1162 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1166 *ppTable = RateSwitchTable11N2SForABand;
1167 *pTableSize = RateSwitchTable11N2SForABand[0];
1168 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
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 //
1182 *ppTable = RateSwitchTable11B;
1183 *pTableSize = RateSwitchTable11B[0];
1184 *pInitTxRateIdx = RateSwitchTable11B[1];
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 //
1196 *ppTable = RateSwitchTable11BG;
1197 *pTableSize = RateSwitchTable11BG[0];
1198 *pInitTxRateIdx = RateSwitchTable11BG[1];
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 //
1210 *ppTable = RateSwitchTable11G;
1211 *pTableSize = RateSwitchTable11G[0];
1212 *pInitTxRateIdx = RateSwitchTable11G[1];
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 //
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];
1242 *ppTable = RateSwitchTable11BG;
1243 *pTableSize = RateSwitchTable11BG[0];
1244 *pInitTxRateIdx = RateSwitchTable11BG[1];
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"));
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"));
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"));
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 //
1292 #ifdef CONFIG_STA_SUPPORT
1293 VOID STAMlmePeriodicExec(
1303 We return here in ATE mode, because the statistics
1304 that ATE need are not collected via this routine.
1309 #endif // RALINK_ATE //
1312 // It is supposed that we will never reach here in ATE mode.
1313 ASSERT(!(ATE_ON(pAd)));
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);
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);
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"));
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))
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);
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);
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);
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)
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
1512 rv = MlmeCheckForFastRoaming(pAd);
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;
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
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)
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;
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)
1591 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
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);
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 //
1637 IN PVOID SystemSpecific1,
1638 IN PVOID FunctionContext,
1639 IN PVOID SystemSpecific2,
1640 IN PVOID SystemSpecific3)
1642 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1646 MLME_DISASSOC_REQ_STRUCT DisassocReq;
1648 if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
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
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"));
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;
1697 MLME_CNTL_STATE_MACHINE,
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));
1716 MLME_CNTL_STATE_MACHINE,
1718 sizeof(NDIS_802_11_SSID),
1720 RTMP_MLME_HANDLER(pAd);
1726 ==========================================================================
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
1735 ==========================================================================
1737 VOID MlmeCheckForRoaming(
1738 IN PRTMP_ADAPTER pAd,
1742 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
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 ==========================================================================
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
1790 ==========================================================================
1792 BOOLEAN MlmeCheckForFastRoaming(
1793 IN PRTMP_ADAPTER pAd)
1796 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
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);
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;
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;
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;
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;
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);
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);
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 ==========================================================================
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}
1959 IRQL = DISPATCH_LEVEL
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;
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;
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)
2001 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2003 Rssi = RTMPMaxRssi(pAd,
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;
2032 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2036 if (INFRA_ON(pAd) && (i == 1))
2037 Rssi = RTMPMaxRssi(pAd,
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;
2052 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / 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;
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);
2079 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
2080 if ((MACValue & 0xffffff) == 0)
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);
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));
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)
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)
2183 else if (pCurrTxRate->CurrMCS == MCS_1)
2187 else if (pCurrTxRate->CurrMCS == MCS_2)
2191 else if (pCurrTxRate->CurrMCS == MCS_3)
2195 else if (pCurrTxRate->CurrMCS == MCS_4)
2199 else if (pCurrTxRate->CurrMCS == MCS_5)
2203 else if (pCurrTxRate->CurrMCS == MCS_6)
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
2212 else if (pCurrTxRate->CurrMCS == MCS_12)
2216 else if (pCurrTxRate->CurrMCS == MCS_13)
2220 else if (pCurrTxRate->CurrMCS == MCS_14)
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
2229 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2233 else if (pCurrTxRate->CurrMCS == MCS_21)
2237 else if (pCurrTxRate->CurrMCS == MCS_22)
2241 else if (pCurrTxRate->CurrMCS == MCS_23)
2248 if (pAd->LatchRfRegs.Channel <= 14)
2250 if (pAd->NicConfig2.field.ExternalLNAForG)
2261 if (pAd->NicConfig2.field.ExternalLNAForA)
2270 #ifdef DOT11_N_SUPPORT
2272 if ((pTable == RateSwitchTable11BGN3S) ||
2273 (pTable == RateSwitchTable11N3S) ||
2274 (pTable == RateSwitchTable))
2275 {// N mode with 3 stream // 3*3
2276 if (MCS23 && (Rssi >= -70))
2278 else if (MCS22 && (Rssi >= -72))
2280 else if (MCS21 && (Rssi >= -76))
2282 else if (MCS20 && (Rssi >= -78))
2284 else if (MCS4 && (Rssi >= -82))
2286 else if (MCS3 && (Rssi >= -84))
2288 else if (MCS2 && (Rssi >= -86))
2290 else if (MCS1 && (Rssi >= -88))
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)))
2300 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2302 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2304 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2306 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2308 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2310 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2312 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2317 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2318 {// N mode with 1 stream
2319 if (MCS7 && (Rssi > (-72+RssiOffset)))
2321 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2323 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2325 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2327 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2329 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2331 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2337 #endif // DOT11_N_SUPPORT //
2339 if (MCS7 && (Rssi > -70))
2341 else if (MCS6 && (Rssi > -74))
2343 else if (MCS5 && (Rssi > -78))
2345 else if (MCS4 && (Rssi > -82))
2347 else if (MCS4 == 0) // for B-only mode
2349 else if (MCS3 && (Rssi > -85))
2351 else if (MCS2 && (Rssi > -87))
2353 else if (MCS1 && (Rssi > -90))
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);
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);
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;
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;
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;
2469 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2470 bTxRateChanged = FALSE;
2473 pEntry->LastTxOkCount = TxSuccess;
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));
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.
2507 SystemSpecific1 - Not used.
2508 FunctionContext - Pointer to our Adapter context.
2509 SystemSpecific2 - Not used.
2510 SystemSpecific3 - Not used.
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;
2526 ULONG TxErrorRatio = 0;
2527 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2528 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2530 UCHAR TableSize = 0;
2531 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2532 TX_STA_CNT1_STRUC StaTx1;
2533 TX_STA_CNT0_STRUC TxStaCnt0;
2535 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2536 MAC_TABLE_ENTRY *pEntry;
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)
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);
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));
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;
2618 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2622 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2623 pEntry->OneSecTxRetryOkCount +
2624 pEntry->OneSecTxFailCount;
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"));
2656 ULONG OneSecTxNoRetryOKRationCount;
2658 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
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;
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;
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 ==========================================================================
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.
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,
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)
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);
2780 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2785 // IRQL = PASSIVE_LEVEL
2786 // IRQL = DISPATCH_LEVEL
2788 IN PRTMP_ADAPTER pAd,
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 ==========================================================================
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.
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,
2825 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
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;
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;
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) &&
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));
2904 #endif // CONFIG_STA_SUPPORT //
2909 else if (MaxRssi < -90)
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;
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 ==========================================================================
2964 Update basic rate bitmap
2965 ==========================================================================
2968 VOID UpdateBasicRateBitmap(
2969 IN PRTMP_ADAPTER pAdapter)
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 */
2985 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2987 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2991 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
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])
3008 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
3010 if (ext_p[j] == rate[i])
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,
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);
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;
3092 // Auto rate switching is enabled only if more than one DESIRED RATES are
3093 // specified; otherwise disabled
3096 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
3097 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
3098 *auto_rate_cur_p = FALSE;
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;
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;
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);
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;
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
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)
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;
3224 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3227 pAd->CommonCfg.TxRate = RATE_11;
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;
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;
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];}
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;
3274 switch (pAd->CommonCfg.PhyMode)
3276 case PHY_11BG_MIXED:
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;
3286 pAd->CommonCfg.RtsRate = RATE_11;
3288 // pAd->CommonCfg.RtsRate = RATE_1;
3293 #ifdef DOT11_N_SUPPORT
3294 case PHY_11AGN_MIXED:
3295 case PHY_11GN_MIXED:
3297 case PHY_11AN_MIXED:
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];
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;
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];
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;
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];
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 ==========================================================================
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,
3368 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3370 RT_HT_CAPABILITY *pRtHtCap = NULL;
3371 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
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)
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;
3410 pMaxHtPhy->field.STBC = STBC_NONE;
3413 #endif // CONFIG_STA_SUPPORT //
3415 if (pDesireHtPhy->bHtEnable == FALSE)
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;
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;
3431 pMaxHtPhy->field.MODE = MODE_HTMIX;
3433 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3434 pMaxHtPhy->field.BW = BW_40;
3436 pMaxHtPhy->field.BW = BW_20;
3438 if (pMaxHtPhy->field.BW == BW_20)
3439 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
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
3451 bitmask = (1<<(i-(j*8)));
3453 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3455 pMaxHtPhy->field.MCS = i;
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
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;
3493 #endif // CONFIG_STA_SUPPORT //
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;
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"));
3517 IN PRTMP_ADAPTER pAd,
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
3540 IN PRTMP_ADAPTER pAd)
3542 RTMP_MLME_RADIO_OFF(pAd);
3545 // IRQL = DISPATCH_LEVEL
3547 IN PRTMP_ADAPTER pAd)
3549 RTMP_MLME_RADIO_ON(pAd);
3552 // ===========================================================================================
3554 // ===========================================================================================
3557 /*! \brief initialize BSS table
3558 * \param p_tab pointer to the table
3563 IRQL = PASSIVE_LEVEL
3564 IRQL = DISPATCH_LEVEL
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
3588 * \note search by sequential search
3590 IRQL = DISPATCH_LEVEL
3593 ULONG BssTableSearch(
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))
3613 return (ULONG)BSS_NOT_FOUND;
3616 ULONG BssSsidTableSearch(
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))
3639 return (ULONG)BSS_NOT_FOUND;
3642 ULONG BssTableSearchWithSSID(
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))))
3663 return (ULONG)BSS_NOT_FOUND;
3667 ULONG BssSsidTableSearchBySSID(
3674 for (i = 0; i < Tab->BssNr; i++)
3676 if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3681 return (ULONG)BSS_NOT_FOUND;
3685 // IRQL = DISPATCH_LEVEL
3686 VOID BssTableDeleteEntry(
3687 IN OUT BSS_TABLE *Tab,
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));
3709 #ifdef DOT11_N_SUPPORT
3711 ========================================================================
3712 Routine Description:
3713 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
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 //
3749 IRQL = DISPATCH_LEVEL
3753 IN PRTMP_ADAPTER pAd,
3754 OUT BSS_ENTRY *pBss,
3759 IN USHORT BeaconPeriod,
3760 IN PCF_PARM pCfParm,
3762 IN USHORT CapabilityInfo,
3764 IN UCHAR SupRateLen,
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,
3774 IN LARGE_INTEGER TimeStamp,
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
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;
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;
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);
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;
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
3846 pBss->VarIELen = LengthVIE;
3847 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
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);
3882 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3884 pBss->EdcaParm.bValid = FALSE;
3886 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3888 pBss->QosCapability.bValid = FALSE;
3890 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3892 pBss->QbssLoad.bValid = FALSE;
3894 #ifdef CONFIG_STA_SUPPORT
3895 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
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)
3913 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3915 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3917 pBss->WpaIE.IELen = 0;
3920 pBss->WpaIE.IELen = pEid->Len + 2;
3921 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3925 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3927 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3929 pBss->RsnIE.IELen = 0;
3932 pBss->RsnIE.IELen = pEid->Len + 2;
3933 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3936 #ifdef EXT_BUILD_CHANNEL_LIST
3938 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3939 pBss->bHasCountryIE = TRUE;
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
3955 * \param ssid_len Length of SSID
3957 * \param beacon_period
3964 * \param channel_idx
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,
3980 IN USHORT BeaconPeriod,
3983 IN USHORT CapabilityInfo,
3985 IN UCHAR SupRateLen,
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,
3995 IN LARGE_INTEGER TimeStamp,
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)
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;
4030 return BSS_NOT_FOUND;
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);
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);
4054 #ifdef CONFIG_STA_SUPPORT
4055 #ifdef DOT11_N_SUPPORT
4056 #ifdef DOT11N_DRAFT3
4058 IN PRTMP_ADAPTER pAd)
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,
4073 IN HT_CAPABILITY_IE *pHtCapability,
4074 IN UCHAR HtCapabilityLen,
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;
4089 // Beacon has Regulatory class IE. So use beacon's
4090 Tab->EventA[Tab->EventANo].RegClass = RegClass;
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;
4105 Tab->EventA[Tab->EventANo].RegClass = ??;
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.
4125 // IRQL = DISPATCH_LEVEL
4126 ========================================================================
4128 VOID TriEventCounterMaintenance(
4129 IN PRTMP_ADAPTER pAd)
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.
4147 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
4149 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
4150 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
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,
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 //
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"));
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"));
4211 #endif // DOT11_N_SUPPORT //
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))
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)
4230 // check group cipher
4231 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4232 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4233 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
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))
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)
4251 // check group cipher
4252 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4253 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4254 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
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))
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.
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!!
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;
4294 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4298 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4304 #endif // DOT11_N_SUPPORT //
4306 // copy matching BSS from InTab to OutTab
4307 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
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"));
4324 #endif // DOT11_N_SUPPORT //
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))
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)
4343 // check group cipher
4344 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
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))
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)
4362 // check group cipher
4363 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
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))
4375 // Bss Type matched, SSID matched.
4376 // We will check wepstatus for qualification Bss
4377 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
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;
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));
4401 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4405 BssTableSortByRssi(OutTab);
4409 // IRQL = DISPATCH_LEVEL
4410 VOID BssTableSortByRssi(
4411 IN OUT BSS_TABLE *OutTab)
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)
4437 PRSN_IE_HEADER_STRUCT pRsnHeader;
4438 PCIPHER_SUITE_STRUCT pCipher;
4439 PAKM_SUITE_STRUCT pAKM;
4442 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4445 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4449 pBss->WepStatus = Ndis802_11WEPEnabled;
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;
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;
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;
4484 if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4489 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4491 // if unsupported vendor specific IE
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;
4500 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4508 // Parse group cipher
4512 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4515 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4518 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4521 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4526 // number of unicast suite
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
4539 TmpCipher = Ndis802_11WEPDisabled;
4543 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4544 TmpCipher = Ndis802_11Encryption1Enabled;
4547 TmpCipher = Ndis802_11Encryption2Enabled;
4550 TmpCipher = Ndis802_11Encryption3Enabled;
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;
4563 pBss->WPA.PairCipherAux = TmpCipher;
4569 // 4. get AKM suite counts
4570 //Count = *(PUSHORT) pTmp;
4571 Count = (pTmp[1]<<8) + pTmp[0];
4572 pTmp += sizeof(USHORT);
4578 // Set AP support WPA-enterprise mode
4579 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4580 pBss->AuthMode = Ndis802_11AuthModeWPA;
4582 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4585 // Set AP support WPA-PSK mode
4586 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4587 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4589 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
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;
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;
4616 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4618 // 0. Version must be 1
4619 if (le2cpu16(pRsnHeader->Version) != 1)
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))
4628 // Parse group cipher
4629 switch (pCipher->Type)
4632 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4635 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4638 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4641 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
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
4659 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4660 TmpCipher = Ndis802_11WEPDisabled;
4661 switch (pCipher->Type)
4664 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4665 TmpCipher = Ndis802_11Encryption1Enabled;
4668 TmpCipher = Ndis802_11Encryption2Enabled;
4671 TmpCipher = Ndis802_11Encryption3Enabled;
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;
4684 pBss->WPA2.PairCipherAux = TmpCipher;
4686 pTmp += sizeof(CIPHER_SUITE_STRUCT);
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
4699 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4700 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4706 // Set AP support WPA-enterprise mode
4707 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4708 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4710 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4713 // Set AP support WPA-PSK mode
4714 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4715 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4717 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4720 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4721 pBss->AuthMode = Ndis802_11AuthModeMax;
4723 pBss->AuthModeAux = Ndis802_11AuthModeMax;
4726 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
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;
4757 Length -= (pEid->Len + 2);
4761 // ===========================================================================================
4763 // ===========================================================================================
4765 /*! \brief generates a random mac address value for IBSS BSSID
4766 * \param Addr the bssid location
4771 VOID MacAddrRandomBssid(
4772 IN PRTMP_ADAPTER pAd,
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
4790 * \pre the station has the following information in the pAd->StaCfg
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,
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 // ===========================================================================================
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
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!!!
4837 * Size of the buffer
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(
4847 OUT ULONG *FrameLen, ...)
4854 // calculates the total length
4856 va_start(Args, FrameLen);
4859 leng = va_arg(Args, int);
4860 if (leng == END_OF_ARGS)
4864 p = va_arg(Args, PVOID);
4865 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4866 TotLeng = TotLeng + leng;
4869 va_end(Args); /* clean up */
4870 *FrameLen = TotLeng;
4874 // ===========================================================================================
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
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)
4893 NdisAllocateSpinLock(&Queue->Lock);
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
4918 * \note The message has to be initialized
4920 IRQL = PASSIVE_LEVEL
4921 IRQL = DISPATCH_LEVEL
4924 BOOLEAN MlmeEnqueue(
4925 IN PRTMP_ADAPTER pAd,
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))
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));
4946 if (MlmeQueueFull(Queue))
4951 NdisAcquireSpinLock(&(Queue->Lock));
4955 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
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;
4968 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4971 NdisReleaseSpinLock(&(Queue->Lock));
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)
4986 IRQL = DISPATCH_LEVEL
4989 BOOLEAN MlmeEnqueueForRecv(
4990 IN PRTMP_ADAPTER pAd,
4992 IN ULONG TimeStampHigh,
4993 IN ULONG TimeStampLow,
5002 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
5004 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
5007 /* Nothing to do in ATE mode */
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"));
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));
5027 if (MlmeQueueFull(Queue))
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));
5041 #endif // CONFIG_STA_SUPPORT //
5043 // OK, we got all the informations, it is time to put things into queue
5044 NdisAcquireSpinLock(&(Queue->Lock));
5048 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
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;
5068 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
5071 NdisReleaseSpinLock(&(Queue->Lock));
5073 RTMP_MLME_HANDLER(pAd);
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
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]);
5097 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
5101 NdisReleaseSpinLock(&(Queue->Lock));
5105 // IRQL = DISPATCH_LEVEL
5106 VOID MlmeRestartStateMachine(
5107 IN PRTMP_ADAPTER pAd)
5110 MLME_QUEUE_ELEM *Elem = NULL;
5111 #endif // RTMP_MAC_PCI //
5112 #ifdef CONFIG_STA_SUPPORT
5114 #endif // CONFIG_STA_SUPPORT //
5116 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
5119 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5120 if(pAd->Mlme.bRunning)
5122 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
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;
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
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 //
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
5209 IRQL = DISPATCH_LEVEL
5212 BOOLEAN MlmeQueueEmpty(
5213 IN MLME_QUEUE *Queue)
5217 NdisAcquireSpinLock(&(Queue->Lock));
5218 Ans = (Queue->Num == 0);
5219 NdisReleaseSpinLock(&(Queue->Lock));
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
5230 IRQL = PASSIVE_LEVEL
5231 IRQL = DISPATCH_LEVEL
5234 BOOLEAN MlmeQueueFull(
5235 IN MLME_QUEUE *Queue)
5239 NdisAcquireSpinLock(&(Queue->Lock));
5240 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5241 NdisReleaseSpinLock(&(Queue->Lock));
5246 /*! \brief The destructor of MLME Queue
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));
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
5276 IRQL = DISPATCH_LEVEL
5279 #ifdef CONFIG_STA_SUPPORT
5280 BOOLEAN MsgTypeSubst(
5281 IN PRTMP_ADAPTER pAd,
5282 IN PFRAME_802_11 pFrame,
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;
5309 case SUBTYPE_ASSOC_RSP:
5310 *Machine = ASSOC_STATE_MACHINE;
5311 *MsgType = MT2_PEER_ASSOC_RSP;
5313 case SUBTYPE_REASSOC_REQ:
5314 *Machine = ASSOC_STATE_MACHINE;
5315 *MsgType = MT2_PEER_REASSOC_REQ;
5317 case SUBTYPE_REASSOC_RSP:
5318 *Machine = ASSOC_STATE_MACHINE;
5319 *MsgType = MT2_PEER_REASSOC_RSP;
5321 case SUBTYPE_PROBE_REQ:
5322 *Machine = SYNC_STATE_MACHINE;
5323 *MsgType = MT2_PEER_PROBE_REQ;
5325 case SUBTYPE_PROBE_RSP:
5326 *Machine = SYNC_STATE_MACHINE;
5327 *MsgType = MT2_PEER_PROBE_RSP;
5329 case SUBTYPE_BEACON:
5330 *Machine = SYNC_STATE_MACHINE;
5331 *MsgType = MT2_PEER_BEACON;
5334 *Machine = SYNC_STATE_MACHINE;
5335 *MsgType = MT2_PEER_ATIM;
5337 case SUBTYPE_DISASSOC:
5338 *Machine = ASSOC_STATE_MACHINE;
5339 *MsgType = MT2_PEER_DISASSOC_REQ;
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;
5363 case SUBTYPE_DEAUTH:
5364 *Machine = AUTH_RSP_STATE_MACHINE;
5365 *MsgType = MT2_PEER_DEAUTH;
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;
5376 *MsgType = (pFrame->Octet[0]&0x7F);
5386 #endif // CONFIG_STA_SUPPORT //
5388 // ===========================================================================================
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
5403 IRQL = PASSIVE_LEVEL
5406 VOID StateMachineInit(
5407 IN STATE_MACHINE *S,
5408 IN STATE_MACHINE_FUNC Trans[],
5411 IN STATE_MACHINE_FUNC DefFunc,
5417 // set number of states and messages
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
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
5445 IRQL = PASSIVE_LEVEL
5448 VOID StateMachineSetAction(
5449 IN STATE_MACHINE *S,
5452 IN STATE_MACHINE_FUNC Func)
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
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 ==========================================================================
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 ==========================================================================
5491 IN PRTMP_ADAPTER pAd,
5492 IN MLME_QUEUE_ELEM *Elem)
5496 // ===========================================================================================
5498 // ===========================================================================================
5501 ==========================================================================
5504 IRQL = PASSIVE_LEVEL
5506 ==========================================================================
5509 IN PRTMP_ADAPTER pAd,
5513 pAd->Mlme.ShiftReg = 1;
5515 pAd->Mlme.ShiftReg = Seed;
5519 ==========================================================================
5521 ==========================================================================
5524 IN PRTMP_ADAPTER pAd)
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;
5543 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5546 R = (R << 1) | Result;
5554 ========================================================================
5556 Routine Description:
5557 Verify the support rate for different PHY type
5560 pAd Pointer to our adapter
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;
5579 if (pAd->CommonCfg.PhyMode == PHY_11B)
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,
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;
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)
5640 ========================================================================
5642 Routine Description:
5643 Verify the support rate for HT phy type
5646 pAd Pointer to our adapter
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,
5658 IN HT_CAPABILITY_IE *pHtCapability,
5659 IN ADD_HT_INFO_IE *pAddHtInfo)
5661 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
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)
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;
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;
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;
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);
5741 #endif // DOT11_N_SUPPORT //
5742 #endif // CONFIG_STA_SUPPORT //
5745 ========================================================================
5747 Routine Description:
5748 Verify the support rate for different PHY type
5751 pAd Pointer to our adapter
5756 IRQL = PASSIVE_LEVEL
5758 ========================================================================
5760 VOID RTMPUpdateMlmeRate(
5761 IN PRTMP_ADAPTER pAd)
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)
5771 ProperMlmeRate = RATE_11;
5772 MinimumRate = RATE_1;
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))
5782 ProperMlmeRate = RATE_11;
5784 ProperMlmeRate = RATE_24;
5786 if (pAd->MlmeAux.Channel <= 14)
5787 MinimumRate = RATE_1;
5789 MinimumRate = RATE_6;
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:
5798 #endif // DOT11_N_SUPPORT //
5799 ProperMlmeRate = RATE_24;
5800 MinimumRate = RATE_6;
5802 case PHY_11ABG_MIXED:
5803 ProperMlmeRate = RATE_24;
5804 if (pAd->MlmeAux.Channel <= 14)
5805 MinimumRate = RATE_1;
5807 MinimumRate = RATE_6;
5810 ProperMlmeRate = RATE_1;
5811 MinimumRate = RATE_1;
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)
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)
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];
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));
5880 IN PRTMP_ADAPTER pAd,
5887 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
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);
5910 ========================================================================
5911 Routine Description:
5912 Periodic evaluate antenna link status
5915 pAd - Adapter pointer
5920 ========================================================================
5922 VOID AsicEvaluateRxAnt(
5923 IN PRTMP_ADAPTER pAd)
5925 #ifdef CONFIG_STA_SUPPORT
5927 #endif // CONFIG_STA_SUPPORT //
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)
5941 || (pAd->bPCIclkOff == TRUE)
5943 #ifdef ANT_DIVERSITY_SUPPORT
5944 || (pAd->EepromAccess)
5945 #endif // ANT_DIVERSITY_SUPPORT //
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);
5969 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
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)
5981 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5983 if(pAd->Antenna.field.RxPath == 3)
5987 else if(pAd->Antenna.field.RxPath == 2)
5991 else if(pAd->Antenna.field.RxPath == 1)
5995 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
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;
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
6030 pAd - Adapter pointer
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
6047 CHAR larger = -127, rssi0, rssi1, rssi2;
6048 #endif // CONFIG_STA_SUPPORT //
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)
6061 || (pAd->bPCIclkOff == TRUE)
6063 #ifdef ANT_DIVERSITY_SUPPORT
6064 || (pAd->EepromAccess)
6065 #endif // ANT_DIVERSITY_SUPPORT //
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]))
6076 #endif // CONFIG_STA_SUPPORT //
6077 if (bSwapAnt == TRUE)
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;
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 //
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)
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;
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;
6140 pAd->Mlme.RealRxPath = 3;
6142 else if(pAd->Antenna.field.RxPath == 2)
6144 if (rssi0 > (rssi1 + 20))
6145 pAd->Mlme.RealRxPath = 1;
6147 pAd->Mlme.RealRxPath = 2;
6150 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
6152 if(pAd->Mlme.RealRxPath == 3)
6156 else if(pAd->Mlme.RealRxPath == 2)
6160 else if(pAd->Mlme.RealRxPath == 1)
6164 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
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))
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
6207 pAd - Adapter pointer
6208 bPiggyBack - Enable / Disable Piggy-Back
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
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;
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 //
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)
6283 #endif // CONFIG_STA_SUPPORT //
6289 ========================================================================
6290 Routine Description:
6291 check if this entry need to fix tx legacy rate
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 //
6321 ========================================================================
6322 Routine Description:
6323 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
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)
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;
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 ==========================================================================
6376 dynamic tune BBP R66 to find a balance between sensibility and
6379 IRQL = DISPATCH_LEVEL
6381 ==========================================================================
6383 VOID AsicStaBbpTuning(
6384 IN PRTMP_ADAPTER pAd)
6386 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
6389 // 2860C did not support Fase CCA, therefore can't tune
6390 if (pAd->MACVersion == 0x28600100)
6396 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
6399 if ((pAd->OpMode == OPMODE_STA)
6400 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
6402 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
6404 && (pAd->bPCIclkOff == FALSE)
6405 #endif // RTMP_MAC_PCI //
6408 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
6411 if (pAd->Antenna.field.RxPath > 1)
6412 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
6414 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
6416 if (pAd->LatchRfRegs.Channel <= 14)
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);
6434 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
6435 if (OrigR66Value != R66)
6437 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
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);
6454 R66 = 0x2E + GET_LNA_GAIN(pAd);
6455 if (OrigR66Value != R66)
6457 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
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);
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);
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);
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,
6515 if (pAd->LatchRfRegs.Channel <= 14)
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);
6528 R66 = 0x2E + GET_LNA_GAIN(pAd);
6529 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
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
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 //