Staging: rt28x0: remove __LINE__ instances
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rt2860 / common / mlme.c
blob9c250c2b3294d4660fcf9b5b499c181a63929ac8
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
27 Module Name:
28 mlme.c
30 Abstract:
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
40 #include <stdarg.h>
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
47 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
48 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
49 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
50 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
51 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
52 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
54 UCHAR RateSwitchTable[] = {
55 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
56 0x11, 0x00, 0, 0, 0, // Initial used item after association
57 0x00, 0x00, 0, 40, 101,
58 0x01, 0x00, 1, 40, 50,
59 0x02, 0x00, 2, 35, 45,
60 0x03, 0x00, 3, 20, 45,
61 0x04, 0x21, 0, 30, 50,
62 0x05, 0x21, 1, 20, 50,
63 0x06, 0x21, 2, 20, 50,
64 0x07, 0x21, 3, 15, 50,
65 0x08, 0x21, 4, 15, 30,
66 0x09, 0x21, 5, 10, 25,
67 0x0a, 0x21, 6, 8, 25,
68 0x0b, 0x21, 7, 8, 25,
69 0x0c, 0x20, 12, 15, 30,
70 0x0d, 0x20, 13, 8, 20,
71 0x0e, 0x20, 14, 8, 20,
72 0x0f, 0x20, 15, 8, 25,
73 0x10, 0x22, 15, 8, 25,
74 0x11, 0x00, 0, 0, 0,
75 0x12, 0x00, 0, 0, 0,
76 0x13, 0x00, 0, 0, 0,
77 0x14, 0x00, 0, 0, 0,
78 0x15, 0x00, 0, 0, 0,
79 0x16, 0x00, 0, 0, 0,
80 0x17, 0x00, 0, 0, 0,
81 0x18, 0x00, 0, 0, 0,
82 0x19, 0x00, 0, 0, 0,
83 0x1a, 0x00, 0, 0, 0,
84 0x1b, 0x00, 0, 0, 0,
85 0x1c, 0x00, 0, 0, 0,
86 0x1d, 0x00, 0, 0, 0,
87 0x1e, 0x00, 0, 0, 0,
88 0x1f, 0x00, 0, 0, 0,
91 UCHAR RateSwitchTable11B[] = {
92 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
93 0x04, 0x03, 0, 0, 0, // Initial used item after association
94 0x00, 0x00, 0, 40, 101,
95 0x01, 0x00, 1, 40, 50,
96 0x02, 0x00, 2, 35, 45,
97 0x03, 0x00, 3, 20, 45,
100 UCHAR RateSwitchTable11BG[] = {
101 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
102 0x0a, 0x00, 0, 0, 0, // Initial used item after association
103 0x00, 0x00, 0, 40, 101,
104 0x01, 0x00, 1, 40, 50,
105 0x02, 0x00, 2, 35, 45,
106 0x03, 0x00, 3, 20, 45,
107 0x04, 0x10, 2, 20, 35,
108 0x05, 0x10, 3, 16, 35,
109 0x06, 0x10, 4, 10, 25,
110 0x07, 0x10, 5, 16, 25,
111 0x08, 0x10, 6, 10, 25,
112 0x09, 0x10, 7, 10, 13,
115 UCHAR RateSwitchTable11G[] = {
116 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
117 0x08, 0x00, 0, 0, 0, // Initial used item after association
118 0x00, 0x10, 0, 20, 101,
119 0x01, 0x10, 1, 20, 35,
120 0x02, 0x10, 2, 20, 35,
121 0x03, 0x10, 3, 16, 35,
122 0x04, 0x10, 4, 10, 25,
123 0x05, 0x10, 5, 16, 25,
124 0x06, 0x10, 6, 10, 25,
125 0x07, 0x10, 7, 10, 13,
128 UCHAR RateSwitchTable11N1S[] = {
129 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
130 0x0c, 0x0a, 0, 0, 0, // Initial used item after association
131 0x00, 0x00, 0, 40, 101,
132 0x01, 0x00, 1, 40, 50,
133 0x02, 0x00, 2, 25, 45,
134 0x03, 0x21, 0, 20, 35,
135 0x04, 0x21, 1, 20, 35,
136 0x05, 0x21, 2, 20, 35,
137 0x06, 0x21, 3, 15, 35,
138 0x07, 0x21, 4, 15, 30,
139 0x08, 0x21, 5, 10, 25,
140 0x09, 0x21, 6, 8, 14,
141 0x0a, 0x21, 7, 8, 14,
142 0x0b, 0x23, 7, 8, 14,
145 UCHAR RateSwitchTable11N2S[] = {
146 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
147 0x0e, 0x0c, 0, 0, 0, // Initial used item after association
148 0x00, 0x00, 0, 40, 101,
149 0x01, 0x00, 1, 40, 50,
150 0x02, 0x00, 2, 25, 45,
151 0x03, 0x21, 0, 20, 35,
152 0x04, 0x21, 1, 20, 35,
153 0x05, 0x21, 2, 20, 35,
154 0x06, 0x21, 3, 15, 35,
155 0x07, 0x21, 4, 15, 30,
156 0x08, 0x20, 11, 15, 30,
157 0x09, 0x20, 12, 15, 30,
158 0x0a, 0x20, 13, 8, 20,
159 0x0b, 0x20, 14, 8, 20,
160 0x0c, 0x20, 15, 8, 25,
161 0x0d, 0x22, 15, 8, 15,
164 UCHAR RateSwitchTable11N3S[] = {
165 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
166 0x0b, 0x00, 0, 0, 0, // 0x0a, 0x00, 0, 0, 0, // Initial used item after association
167 0x00, 0x21, 0, 30, 101,
168 0x01, 0x21, 1, 20, 50,
169 0x02, 0x21, 2, 20, 50,
170 0x03, 0x21, 3, 15, 50,
171 0x04, 0x21, 4, 15, 30,
172 0x05, 0x20, 11, 15, 30, // Required by System-Alan @ 20080812
173 0x06, 0x20, 12, 15, 30, // 0x05, 0x20, 12, 15, 30,
174 0x07, 0x20, 13, 8, 20, // 0x06, 0x20, 13, 8, 20,
175 0x08, 0x20, 14, 8, 20, // 0x07, 0x20, 14, 8, 20,
176 0x09, 0x20, 15, 8, 25, // 0x08, 0x20, 15, 8, 25,
177 0x0a, 0x22, 15, 8, 25, // 0x09, 0x22, 15, 8, 25,
180 UCHAR RateSwitchTable11N2SForABand[] = {
181 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
182 0x0b, 0x09, 0, 0, 0, // Initial used item after association
183 0x00, 0x21, 0, 30, 101,
184 0x01, 0x21, 1, 20, 50,
185 0x02, 0x21, 2, 20, 50,
186 0x03, 0x21, 3, 15, 50,
187 0x04, 0x21, 4, 15, 30,
188 0x05, 0x21, 5, 15, 30,
189 0x06, 0x20, 12, 15, 30,
190 0x07, 0x20, 13, 8, 20,
191 0x08, 0x20, 14, 8, 20,
192 0x09, 0x20, 15, 8, 25,
193 0x0a, 0x22, 15, 8, 25,
196 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
197 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
198 0x0b, 0x09, 0, 0, 0, // Initial used item after association
199 0x00, 0x21, 0, 30, 101,
200 0x01, 0x21, 1, 20, 50,
201 0x02, 0x21, 2, 20, 50,
202 0x03, 0x21, 3, 15, 50,
203 0x04, 0x21, 4, 15, 30,
204 0x05, 0x21, 5, 15, 30,
205 0x06, 0x20, 12, 15, 30,
206 0x07, 0x20, 13, 8, 20,
207 0x08, 0x20, 14, 8, 20,
208 0x09, 0x20, 15, 8, 25,
209 0x0a, 0x22, 15, 8, 25,
212 UCHAR RateSwitchTable11BGN1S[] = {
213 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
214 0x0c, 0x0a, 0, 0, 0, // Initial used item after association
215 0x00, 0x00, 0, 40, 101,
216 0x01, 0x00, 1, 40, 50,
217 0x02, 0x00, 2, 25, 45,
218 0x03, 0x21, 0, 20, 35,
219 0x04, 0x21, 1, 20, 35,
220 0x05, 0x21, 2, 20, 35,
221 0x06, 0x21, 3, 15, 35,
222 0x07, 0x21, 4, 15, 30,
223 0x08, 0x21, 5, 10, 25,
224 0x09, 0x21, 6, 8, 14,
225 0x0a, 0x21, 7, 8, 14,
226 0x0b, 0x23, 7, 8, 14,
229 UCHAR RateSwitchTable11BGN2S[] = {
230 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
231 0x0e, 0x0c, 0, 0, 0, // Initial used item after association
232 0x00, 0x00, 0, 40, 101,
233 0x01, 0x00, 1, 40, 50,
234 0x02, 0x00, 2, 25, 45,
235 0x03, 0x21, 0, 20, 35,
236 0x04, 0x21, 1, 20, 35,
237 0x05, 0x21, 2, 20, 35,
238 0x06, 0x21, 3, 15, 35,
239 0x07, 0x21, 4, 15, 30,
240 0x08, 0x20, 11, 15, 30,
241 0x09, 0x20, 12, 15, 30,
242 0x0a, 0x20, 13, 8, 20,
243 0x0b, 0x20, 14, 8, 20,
244 0x0c, 0x20, 15, 8, 25,
245 0x0d, 0x22, 15, 8, 15,
248 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
249 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
250 0x0a, 0x00, 0, 0, 0, // Initial used item after association
251 0x00, 0x21, 0, 30,101, //50
252 0x01, 0x21, 1, 20, 50,
253 0x02, 0x21, 2, 20, 50,
254 0x03, 0x21, 3, 20, 50,
255 0x04, 0x21, 4, 15, 50,
256 0x05, 0x20, 20, 15, 30,
257 0x06, 0x20, 21, 8, 20,
258 0x07, 0x20, 22, 8, 20,
259 0x08, 0x20, 23, 8, 25,
260 0x09, 0x22, 23, 8, 25,
263 UCHAR RateSwitchTable11BGN2SForABand[] = {
264 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
265 0x0b, 0x09, 0, 0, 0, // Initial used item after association
266 0x00, 0x21, 0, 30,101, //50
267 0x01, 0x21, 1, 20, 50,
268 0x02, 0x21, 2, 20, 50,
269 0x03, 0x21, 3, 15, 50,
270 0x04, 0x21, 4, 15, 30,
271 0x05, 0x21, 5, 15, 30,
272 0x06, 0x20, 12, 15, 30,
273 0x07, 0x20, 13, 8, 20,
274 0x08, 0x20, 14, 8, 20,
275 0x09, 0x20, 15, 8, 25,
276 0x0a, 0x22, 15, 8, 25,
279 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
280 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
281 0x0c, 0x09, 0, 0, 0, // Initial used item after association
282 0x00, 0x21, 0, 30,101, //50
283 0x01, 0x21, 1, 20, 50,
284 0x02, 0x21, 2, 20, 50,
285 0x03, 0x21, 3, 15, 50,
286 0x04, 0x21, 4, 15, 30,
287 0x05, 0x21, 5, 15, 30,
288 0x06, 0x21, 12, 15, 30,
289 0x07, 0x20, 20, 15, 30,
290 0x08, 0x20, 21, 8, 20,
291 0x09, 0x20, 22, 8, 20,
292 0x0a, 0x20, 23, 8, 25,
293 0x0b, 0x22, 23, 8, 25,
297 extern UCHAR OfdmRateToRxwiMCS[];
298 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
299 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
300 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
301 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
302 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
304 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
305 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
307 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
308 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
309 // clean environment.
310 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
311 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
313 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
314 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
316 UCHAR SsidIe = IE_SSID;
317 UCHAR SupRateIe = IE_SUPP_RATES;
318 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
319 UCHAR HtCapIe = IE_HT_CAP;
320 UCHAR AddHtInfoIe = IE_ADD_HT;
321 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
322 UCHAR ErpIe = IE_ERP;
323 UCHAR DsIe = IE_DS_PARM;
324 UCHAR TimIe = IE_TIM;
325 UCHAR WpaIe = IE_WPA;
326 UCHAR Wpa2Ie = IE_WPA2;
327 UCHAR IbssIe = IE_IBSS_PARM;
329 extern UCHAR WPA_OUI[];
331 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
333 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
334 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
338 ==========================================================================
339 Description:
340 initialize the MLME task and its data structure (queue, spinlock,
341 timer, state machines).
343 IRQL = PASSIVE_LEVEL
345 Return:
346 always return NDIS_STATUS_SUCCESS
348 ==========================================================================
350 NDIS_STATUS MlmeInit(
351 IN PRTMP_ADAPTER pAd)
353 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
355 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
359 Status = MlmeQueueInit(&pAd->Mlme.Queue);
360 if(Status != NDIS_STATUS_SUCCESS)
361 break;
363 pAd->Mlme.bRunning = FALSE;
364 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
367 BssTableInit(&pAd->ScanTab);
369 // init STA state machines
370 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
371 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
372 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
373 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
378 // Since we are using switch/case to implement it, the init is different from the above
379 // state machine init
380 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
384 WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, pAd->Mlme.WpaFunc);
387 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
389 // Init mlme periodic timer
390 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
392 // Set mlme periodic timer
393 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
395 // software-based RX Antenna diversity
396 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
399 #ifdef RTMP_PCI_SUPPORT
400 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
402 // only PCIe cards need these two timers
403 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
404 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
406 #endif // RTMP_PCI_SUPPORT //
408 RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer, GET_TIMER_FUNCTION(LinkDownExec), pAd, FALSE);
410 #ifdef RTMP_MAC_USB
411 RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer, GET_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout), pAd, FALSE);
412 pAd->Mlme.AutoWakeupTimerRunning = FALSE;
413 #endif // RTMP_MAC_USB //
416 } while (FALSE);
418 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
420 return Status;
424 ==========================================================================
425 Description:
426 main loop of the MLME
427 Pre:
428 Mlme has to be initialized, and there are something inside the queue
429 Note:
430 This function is invoked from MPSetInformation and MPReceive;
431 This task guarantee only one MlmeHandler will run.
433 IRQL = DISPATCH_LEVEL
435 ==========================================================================
437 VOID MlmeHandler(
438 IN PRTMP_ADAPTER pAd)
440 MLME_QUEUE_ELEM *Elem = NULL;
442 // Only accept MLME and Frame from peer side, no other (control/data) frame should
443 // get into this state machine
445 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
446 if(pAd->Mlme.bRunning)
448 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
449 return;
451 else
453 pAd->Mlme.bRunning = TRUE;
455 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
457 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
459 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
460 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
461 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
463 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
464 break;
467 //From message type, determine which state machine I should drive
468 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
470 #ifdef RTMP_MAC_USB
471 if (Elem->MsgType == MT2_RESET_CONF)
473 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
474 MlmeRestartStateMachine(pAd);
475 Elem->Occupied = FALSE;
476 Elem->MsgLen = 0;
477 continue;
479 #endif // RTMP_MAC_USB //
481 // if dequeue success
482 switch (Elem->Machine)
484 // STA state machines
485 case ASSOC_STATE_MACHINE:
486 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
487 break;
488 case AUTH_STATE_MACHINE:
489 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
490 break;
491 case AUTH_RSP_STATE_MACHINE:
492 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
493 break;
494 case SYNC_STATE_MACHINE:
495 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
496 break;
497 case MLME_CNTL_STATE_MACHINE:
498 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
499 break;
500 case WPA_PSK_STATE_MACHINE:
501 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
502 break;
506 case ACTION_STATE_MACHINE:
507 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
508 break;
510 case WPA_STATE_MACHINE:
511 StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem);
512 break;
515 default:
516 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
517 break;
518 } // end of switch
520 // free MLME element
521 Elem->Occupied = FALSE;
522 Elem->MsgLen = 0;
525 else {
526 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
530 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
531 pAd->Mlme.bRunning = FALSE;
532 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
536 ==========================================================================
537 Description:
538 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
539 Parameters:
540 Adapter - NIC Adapter pointer
541 Post:
542 The MLME task will no longer work properly
544 IRQL = PASSIVE_LEVEL
546 ==========================================================================
548 VOID MlmeHalt(
549 IN PRTMP_ADAPTER pAd)
551 BOOLEAN Cancelled;
553 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
555 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
557 // disable BEACON generation and other BEACON related hardware timers
558 AsicDisableSync(pAd);
562 // Cancel pending timers
563 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
564 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
565 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
566 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
567 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
568 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
571 #ifdef RTMP_MAC_PCI
572 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
573 &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
575 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
576 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
578 #endif // RTMP_MAC_PCI //
580 RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
582 #ifdef RTMP_MAC_USB
583 RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
584 #endif // RTMP_MAC_USB //
587 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
588 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
592 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
594 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
596 // Set LED
597 RTMPSetLED(pAd, LED_HALT);
598 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
599 #ifdef RTMP_MAC_USB
601 LED_CFG_STRUC LedCfg;
602 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
603 LedCfg.field.LedPolar = 0;
604 LedCfg.field.RLedMode = 0;
605 LedCfg.field.GLedMode = 0;
606 LedCfg.field.YLedMode = 0;
607 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
609 #endif // RTMP_MAC_USB //
611 if (pChipOps->AsicHaltAction)
612 pChipOps->AsicHaltAction(pAd);
615 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
617 MlmeQueueDestroy(&pAd->Mlme.Queue);
618 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
620 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
623 VOID MlmeResetRalinkCounters(
624 IN PRTMP_ADAPTER pAd)
626 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
627 // clear all OneSecxxx counters.
628 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
629 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
630 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
631 pAd->RalinkCounters.OneSecRxOkCnt = 0;
632 pAd->RalinkCounters.OneSecTxFailCount = 0;
633 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
634 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
635 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
636 pAd->RalinkCounters.OneSecReceivedByteCount = 0;
637 pAd->RalinkCounters.OneSecTransmittedByteCount = 0;
639 // TODO: for debug only. to be removed
640 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
641 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
642 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
643 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
644 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
645 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
646 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
647 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
648 pAd->RalinkCounters.OneSecTxDoneCount = 0;
649 pAd->RalinkCounters.OneSecRxCount = 0;
650 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
651 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
653 return;
658 ==========================================================================
659 Description:
660 This routine is executed periodically to -
661 1. Decide if it's a right time to turn on PwrMgmt bit of all
662 outgoiing frames
663 2. Calculate ChannelQuality based on statistics of the last
664 period, so that TX rate won't toggling very frequently between a
665 successful TX and a failed TX.
666 3. If the calculated ChannelQuality indicated current connection not
667 healthy, then a ROAMing attempt is tried here.
669 IRQL = DISPATCH_LEVEL
671 ==========================================================================
673 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
674 VOID MlmePeriodicExec(
675 IN PVOID SystemSpecific1,
676 IN PVOID FunctionContext,
677 IN PVOID SystemSpecific2,
678 IN PVOID SystemSpecific3)
680 ULONG TxTotalCnt;
681 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
683 #ifdef RTMP_MAC_PCI
685 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
686 // Move code to here, because following code will return when radio is off
687 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && (pAd->StaCfg.bHardwareRadio == TRUE) &&
688 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
689 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
690 /*&&(pAd->bPCIclkOff == FALSE)*/)
692 UINT32 data = 0;
694 // Read GPIO pin2 as Hardware controlled radio state
695 #ifndef RT3090
696 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
697 #endif // RT3090 //
698 //KH(PCIE PS):Added based on Jane<--
699 #ifdef RT3090
700 // Read GPIO pin2 as Hardware controlled radio state
701 // We need to Read GPIO if HW said so no mater what advance power saving
702 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
703 && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
704 && (pAd->StaCfg.PSControl.field.EnablePSinIdle == TRUE))
706 // Want to make sure device goes to L0 state before reading register.
707 RTMPPCIeLinkCtrlValueRestore(pAd, 0);
708 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
709 RTMPPCIeLinkCtrlSetting(pAd, 3);
711 else
712 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
713 #endif // RT3090 //
714 //KH(PCIE PS):Added based on Jane-->
716 if (data & 0x04)
718 pAd->StaCfg.bHwRadio = TRUE;
720 else
722 pAd->StaCfg.bHwRadio = FALSE;
724 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
726 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
727 if (pAd->StaCfg.bRadio == TRUE)
729 MlmeRadioOn(pAd);
730 // Update extra information
731 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
733 else
735 MlmeRadioOff(pAd);
736 // Update extra information
737 pAd->ExtraInfo = HW_RADIO_OFF;
742 #endif // RTMP_MAC_PCI //
744 // Do nothing if the driver is starting halt state.
745 // This might happen when timer already been fired before cancel timer with mlmehalt
746 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
747 fRTMP_ADAPTER_RADIO_OFF |
748 fRTMP_ADAPTER_RADIO_MEASUREMENT |
749 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
750 return;
752 RTMP_MLME_PRE_SANITY_CHECK(pAd);
755 // Do nothing if monitor mode is on
756 if (MONITOR_ON(pAd))
757 return;
759 if (pAd->Mlme.PeriodicRound & 0x1)
761 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
762 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
763 (STA_TGN_WIFI_ON(pAd)) &&
764 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
767 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
768 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
770 else if ((STA_TGN_WIFI_ON(pAd)) &&
771 ((pAd->MACVersion & 0xffff) == 0x0101))
773 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
774 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
779 pAd->bUpdateBcnCntDone = FALSE;
781 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
782 pAd->Mlme.PeriodicRound ++;
784 #ifdef RTMP_MAC_USB
785 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
786 NICUpdateFifoStaCounters(pAd);
787 #endif // RTMP_MAC_USB //
789 // execute every 500ms
790 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
792 // perform dynamic tx rate switching based on past TX history
794 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
796 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
797 MlmeDynamicTxRateSwitching(pAd);
801 // Normal 1 second Mlme PeriodicExec.
802 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
804 pAd->Mlme.OneSecPeriodicRound ++;
809 //ORIBATimerTimeout(pAd);
811 // Media status changed, report to NDIS
812 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
814 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
815 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
817 pAd->IndicateMediaState = NdisMediaStateConnected;
818 RTMP_IndicateMediaState(pAd);
821 else
823 pAd->IndicateMediaState = NdisMediaStateDisconnected;
824 RTMP_IndicateMediaState(pAd);
828 NdisGetSystemUpTime(&pAd->Mlme.Now32);
830 // add the most up-to-date h/w raw counters into software variable, so that
831 // the dynamic tuning mechanism below are based on most up-to-date information
832 NICUpdateRawCounters(pAd);
834 #ifdef RTMP_MAC_USB
835 RTUSBWatchDog(pAd);
836 #endif // RTMP_MAC_USB //
838 // Need statistics after read counter. So put after NICUpdateRawCounters
839 ORIBATimerTimeout(pAd);
841 // if MGMT RING is full more than twice within 1 second, we consider there's
842 // a hardware problem stucking the TX path. In this case, try a hardware reset
843 // to recover the system
844 // if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
845 // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
846 // else
847 // pAd->RalinkCounters.MgmtRingFullCount = 0;
849 // The time period for checking antenna is according to traffic
851 if (pAd->Mlme.bEnableAutoAntennaCheck)
853 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
854 pAd->RalinkCounters.OneSecTxRetryOkCount +
855 pAd->RalinkCounters.OneSecTxFailCount;
857 // dynamic adjust antenna evaluation period according to the traffic
858 if (TxTotalCnt > 50)
860 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
862 AsicEvaluateRxAnt(pAd);
865 else
867 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
869 AsicEvaluateRxAnt(pAd);
875 STAMlmePeriodicExec(pAd);
877 MlmeResetRalinkCounters(pAd);
880 #ifdef RTMP_MAC_PCI
881 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
882 #endif // RTMP_MAC_PCI //
884 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
885 // and sending CTS-to-self over and over.
886 // Software Patch Solution:
887 // 1. Polling debug state register 0x10F4 every one second.
888 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
889 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
891 UINT32 MacReg = 0;
893 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
894 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
896 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
897 RTMPusecDelay(1);
898 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
900 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
905 RTMP_MLME_HANDLER(pAd);
909 pAd->bUpdateBcnCntDone = FALSE;
914 ==========================================================================
915 Validate SSID for connection try and rescan purpose
916 Valid SSID will have visible chars only.
917 The valid length is from 0 to 32.
918 IRQL = DISPATCH_LEVEL
919 ==========================================================================
921 BOOLEAN MlmeValidateSSID(
922 IN PUCHAR pSsid,
923 IN UCHAR SsidLen)
925 int index;
927 if (SsidLen > MAX_LEN_OF_SSID)
928 return (FALSE);
930 // Check each character value
931 for (index = 0; index < SsidLen; index++)
933 if (pSsid[index] < 0x20)
934 return (FALSE);
937 // All checked
938 return (TRUE);
941 VOID MlmeSelectTxRateTable(
942 IN PRTMP_ADAPTER pAd,
943 IN PMAC_TABLE_ENTRY pEntry,
944 IN PUCHAR *ppTable,
945 IN PUCHAR pTableSize,
946 IN PUCHAR pInitTxRateIdx)
950 // decide the rate table for tuning
951 if (pAd->CommonCfg.TxRateTableSize > 0)
953 *ppTable = RateSwitchTable;
954 *pTableSize = RateSwitchTable[0];
955 *pInitTxRateIdx = RateSwitchTable[1];
957 break;
960 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
962 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
963 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
964 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
965 {// 11N 1S Adhoc
966 *ppTable = RateSwitchTable11N1S;
967 *pTableSize = RateSwitchTable11N1S[0];
968 *pInitTxRateIdx = RateSwitchTable11N1S[1];
971 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
972 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
973 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
974 (pAd->Antenna.field.TxPath == 2))
975 {// 11N 2S Adhoc
976 if (pAd->LatchRfRegs.Channel <= 14)
978 *ppTable = RateSwitchTable11N2S;
979 *pTableSize = RateSwitchTable11N2S[0];
980 *pInitTxRateIdx = RateSwitchTable11N2S[1];
982 else
984 *ppTable = RateSwitchTable11N2SForABand;
985 *pTableSize = RateSwitchTable11N2SForABand[0];
986 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
990 else
991 if ((pEntry->RateLen == 4)
992 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
995 *ppTable = RateSwitchTable11B;
996 *pTableSize = RateSwitchTable11B[0];
997 *pInitTxRateIdx = RateSwitchTable11B[1];
1000 else if (pAd->LatchRfRegs.Channel <= 14)
1002 *ppTable = RateSwitchTable11BG;
1003 *pTableSize = RateSwitchTable11BG[0];
1004 *pInitTxRateIdx = RateSwitchTable11BG[1];
1007 else
1009 *ppTable = RateSwitchTable11G;
1010 *pTableSize = RateSwitchTable11G[0];
1011 *pInitTxRateIdx = RateSwitchTable11G[1];
1014 break;
1017 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1018 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1019 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1020 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1021 {// 11BGN 1S AP
1022 *ppTable = RateSwitchTable11BGN1S;
1023 *pTableSize = RateSwitchTable11BGN1S[0];
1024 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1026 break;
1029 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1030 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1031 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1032 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1033 {// 11BGN 2S AP
1034 if (pAd->LatchRfRegs.Channel <= 14)
1036 *ppTable = RateSwitchTable11BGN2S;
1037 *pTableSize = RateSwitchTable11BGN2S[0];
1038 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1041 else
1043 *ppTable = RateSwitchTable11BGN2SForABand;
1044 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1045 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1048 break;
1051 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1052 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1053 {// 11N 1S AP
1054 *ppTable = RateSwitchTable11N1S;
1055 *pTableSize = RateSwitchTable11N1S[0];
1056 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1058 break;
1061 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1062 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1063 {// 11N 2S AP
1064 if (pAd->LatchRfRegs.Channel <= 14)
1066 *ppTable = RateSwitchTable11N2S;
1067 *pTableSize = RateSwitchTable11N2S[0];
1068 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1070 else
1072 *ppTable = RateSwitchTable11N2SForABand;
1073 *pTableSize = RateSwitchTable11N2SForABand[0];
1074 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1077 break;
1079 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1080 if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode==PHY_11B)
1081 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1082 /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)*/
1084 {// B only AP
1085 *ppTable = RateSwitchTable11B;
1086 *pTableSize = RateSwitchTable11B[0];
1087 *pInitTxRateIdx = RateSwitchTable11B[1];
1089 break;
1092 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1093 if ((pEntry->RateLen > 8)
1094 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1096 {// B/G mixed AP
1097 *ppTable = RateSwitchTable11BG;
1098 *pTableSize = RateSwitchTable11BG[0];
1099 *pInitTxRateIdx = RateSwitchTable11BG[1];
1101 break;
1104 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1105 if ((pEntry->RateLen == 8)
1106 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1108 {// G only AP
1109 *ppTable = RateSwitchTable11G;
1110 *pTableSize = RateSwitchTable11G[0];
1111 *pInitTxRateIdx = RateSwitchTable11G[1];
1113 break;
1117 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1118 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1119 { // Legacy mode
1120 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1122 *ppTable = RateSwitchTable11B;
1123 *pTableSize = RateSwitchTable11B[0];
1124 *pInitTxRateIdx = RateSwitchTable11B[1];
1126 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1128 *ppTable = RateSwitchTable11G;
1129 *pTableSize = RateSwitchTable11G[0];
1130 *pInitTxRateIdx = RateSwitchTable11G[1];
1133 else
1135 *ppTable = RateSwitchTable11BG;
1136 *pTableSize = RateSwitchTable11BG[0];
1137 *pInitTxRateIdx = RateSwitchTable11BG[1];
1139 break;
1141 if (pAd->LatchRfRegs.Channel <= 14)
1143 if (pAd->CommonCfg.TxStream == 1)
1145 *ppTable = RateSwitchTable11N1S;
1146 *pTableSize = RateSwitchTable11N1S[0];
1147 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1148 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1150 else
1152 *ppTable = RateSwitchTable11N2S;
1153 *pTableSize = RateSwitchTable11N2S[0];
1154 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1155 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1158 else
1160 if (pAd->CommonCfg.TxStream == 1)
1162 *ppTable = RateSwitchTable11N1S;
1163 *pTableSize = RateSwitchTable11N1S[0];
1164 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1165 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1167 else
1169 *ppTable = RateSwitchTable11N2SForABand;
1170 *pTableSize = RateSwitchTable11N2SForABand[0];
1171 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1172 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1175 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1176 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1178 } while(FALSE);
1182 VOID STAMlmePeriodicExec(
1183 PRTMP_ADAPTER pAd)
1185 ULONG TxTotalCnt;
1186 int i;
1189 We return here in ATE mode, because the statistics
1190 that ATE need are not collected via this routine.
1192 #if defined(RT305x)||defined(RT3070)
1193 // request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18
1194 if (!pAd->CommonCfg.HighPowerPatchDisabled)
1196 #ifdef RT3070
1197 if ( (IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201)))
1198 #endif // RT3070 //
1200 if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0) && (pAd->StaCfg.RssiSample.AvgRssi0 > (pAd->BbpRssiToDbmDelta - 35)))
1202 RT30xxWriteRFRegister(pAd, RF_R27, 0x20);
1204 else
1206 RT30xxWriteRFRegister(pAd, RF_R27, 0x23);
1210 #endif
1211 #ifdef PCIE_PS_SUPPORT
1212 // don't perform idle-power-save mechanism within 3 min after driver initialization.
1213 // This can make rebooter test more robust
1214 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1216 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
1217 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1218 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1219 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1221 if (IS_RT3090(pAd)|| IS_RT3572(pAd) || IS_RT3390(pAd))
1223 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1225 DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __func__));
1226 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1228 else
1230 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x2);
1231 // Wait command success
1232 AsicCheckCommanOk(pAd, PowerSafeCID);
1233 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1234 DBGPRINT(RT_DEBUG_TRACE, ("PSM - rt30xx Issue Sleep command)\n"));
1237 else if (pAd->Mlme.OneSecPeriodicRound > 180)
1239 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1241 DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __func__));
1242 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1244 else
1246 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x02);
1247 // Wait command success
1248 AsicCheckCommanOk(pAd, PowerSafeCID);
1249 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1250 DBGPRINT(RT_DEBUG_TRACE, ("PSM - rt28xx Issue Sleep command)\n"));
1254 else
1256 DBGPRINT(RT_DEBUG_TRACE,("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1257 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid[0], pAd->CommonCfg.Ssid[1], pAd->CommonCfg.Ssid[2], pAd->CommonCfg.Ssid[3],
1258 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1], pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
1261 #endif // PCIE_PS_SUPPORT //
1263 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1265 // WPA MIC error should block association attempt for 60 seconds
1266 if (pAd->StaCfg.bBlockAssoc &&
1267 RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastMicErrorTime + (60*OS_HZ)))
1268 pAd->StaCfg.bBlockAssoc = FALSE;
1271 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1273 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1275 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1277 pAd->PreMediaState = pAd->IndicateMediaState;
1283 if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd))
1286 else
1288 AsicStaBbpTuning(pAd);
1291 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1292 pAd->RalinkCounters.OneSecTxRetryOkCount +
1293 pAd->RalinkCounters.OneSecTxFailCount;
1295 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1297 // update channel quality for Roaming and UI LinkQuality display
1298 MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32);
1301 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1302 // Radio is currently in noisy environment
1303 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1304 AsicAdjustTxPower(pAd);
1306 if (INFRA_ON(pAd))
1309 // Is PSM bit consistent with user power management policy?
1310 // This is the only place that will set PSM bit ON.
1311 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1312 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1314 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1316 if ((RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (1*OS_HZ))) &&
1317 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1318 (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < 600)))
1320 RTMPSetAGCInitValue(pAd, BW_20);
1321 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1324 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1325 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1327 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1329 // When APSD is enabled, the period changes as 20 sec
1330 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1331 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1333 else
1335 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1336 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1338 if (pAd->CommonCfg.bWmmCapable)
1339 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1340 else
1341 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1346 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1348 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1350 // Lost AP, send disconnect & link down event
1351 LinkDown(pAd, FALSE);
1354 RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0);
1356 // RTMPPatchMacBbpBug(pAd);
1357 MlmeAutoReconnectLastSSID(pAd);
1359 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1361 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1362 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1363 MlmeAutoReconnectLastSSID(pAd);
1366 if (pAd->StaCfg.bAutoRoaming)
1368 BOOLEAN rv = FALSE;
1369 CHAR dBmToRoam = pAd->StaCfg.dBmToRoam;
1370 CHAR MaxRssi = RTMPMaxRssi(pAd,
1371 pAd->StaCfg.RssiSample.LastRssi0,
1372 pAd->StaCfg.RssiSample.LastRssi1,
1373 pAd->StaCfg.RssiSample.LastRssi2);
1375 // Scanning, ignore Roaming
1376 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) &&
1377 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1378 (MaxRssi <= dBmToRoam))
1380 DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", MaxRssi, (CHAR)dBmToRoam));
1383 // Add auto seamless roaming
1384 if (rv == FALSE)
1385 rv = MlmeCheckForFastRoaming(pAd);
1387 if (rv == FALSE)
1389 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1391 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1392 pAd->StaCfg.ScanCnt = 2;
1393 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1394 MlmeAutoScan(pAd);
1400 else if (ADHOC_ON(pAd))
1402 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1403 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1404 // join later.
1405 if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME) &&
1406 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1408 MLME_START_REQ_STRUCT StartReq;
1410 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1411 LinkDown(pAd, FALSE);
1413 StartParmFill(pAd, &StartReq, (CHAR *)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1414 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1415 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1418 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1420 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1422 if (pEntry->ValidAsCLI == FALSE)
1423 continue;
1425 if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1426 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1429 else // no INFRA nor ADHOC connection
1432 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1433 RTMP_TIME_BEFORE(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
1434 goto SKIP_AUTO_SCAN_CONN;
1435 else
1436 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1438 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1439 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1440 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1442 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1444 MLME_SCAN_REQ_STRUCT ScanReq;
1446 if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (10 * OS_HZ)))
1448 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1449 ScanParmFill(pAd, &ScanReq, (PSTRING) pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1450 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1451 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1452 // Reset Missed scan number
1453 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1455 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1456 MlmeAutoReconnectLastSSID(pAd);
1458 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1460 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1462 MlmeAutoScan(pAd);
1463 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1465 else
1467 MlmeAutoReconnectLastSSID(pAd);
1473 SKIP_AUTO_SCAN_CONN:
1475 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1477 pAd->MacTab.fAnyBASession = TRUE;
1478 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1480 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1482 pAd->MacTab.fAnyBASession = FALSE;
1483 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1486 return;
1489 // Link down report
1490 VOID LinkDownExec(
1491 IN PVOID SystemSpecific1,
1492 IN PVOID FunctionContext,
1493 IN PVOID SystemSpecific2,
1494 IN PVOID SystemSpecific3)
1496 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1498 if (pAd != NULL)
1500 MLME_DISASSOC_REQ_STRUCT DisassocReq;
1502 if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
1503 (INFRA_ON(pAd)))
1505 DBGPRINT(RT_DEBUG_TRACE, ("LinkDownExec(): disassociate with current AP...\n"));
1506 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
1507 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
1508 sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
1509 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1511 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1512 RTMP_IndicateMediaState(pAd);
1513 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1518 // IRQL = DISPATCH_LEVEL
1519 VOID MlmeAutoScan(
1520 IN PRTMP_ADAPTER pAd)
1522 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1523 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1525 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1526 MlmeEnqueue(pAd,
1527 MLME_CNTL_STATE_MACHINE,
1528 OID_802_11_BSSID_LIST_SCAN,
1529 pAd->MlmeAux.AutoReconnectSsidLen,
1530 pAd->MlmeAux.AutoReconnectSsid);
1531 RTMP_MLME_HANDLER(pAd);
1535 // IRQL = DISPATCH_LEVEL
1536 VOID MlmeAutoReconnectLastSSID(
1537 IN PRTMP_ADAPTER pAd)
1539 if (pAd->StaCfg.bAutoConnectByBssid)
1541 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n",
1542 pAd->MlmeAux.Bssid[0],
1543 pAd->MlmeAux.Bssid[1],
1544 pAd->MlmeAux.Bssid[2],
1545 pAd->MlmeAux.Bssid[3],
1546 pAd->MlmeAux.Bssid[4],
1547 pAd->MlmeAux.Bssid[5]));
1549 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1550 MlmeEnqueue(pAd,
1551 MLME_CNTL_STATE_MACHINE,
1552 OID_802_11_BSSID,
1553 MAC_ADDR_LEN,
1554 pAd->MlmeAux.Bssid);
1556 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1558 RTMP_MLME_HANDLER(pAd);
1560 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1561 else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1562 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1564 NDIS_802_11_SSID OidSsid;
1565 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1566 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1568 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1569 MlmeEnqueue(pAd,
1570 MLME_CNTL_STATE_MACHINE,
1571 OID_802_11_SSID,
1572 sizeof(NDIS_802_11_SSID),
1573 &OidSsid);
1574 RTMP_MLME_HANDLER(pAd);
1580 ==========================================================================
1581 Description:
1582 This routine checks if there're other APs out there capable for
1583 roaming. Caller should call this routine only when Link up in INFRA mode
1584 and channel quality is below CQI_GOOD_THRESHOLD.
1586 IRQL = DISPATCH_LEVEL
1588 Output:
1589 ==========================================================================
1591 VOID MlmeCheckForRoaming(
1592 IN PRTMP_ADAPTER pAd,
1593 IN ULONG Now32)
1595 USHORT i;
1596 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1597 BSS_ENTRY *pBss;
1599 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1600 // put all roaming candidates into RoamTab, and sort in RSSI order
1601 BssTableInit(pRoamTab);
1602 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1604 pBss = &pAd->ScanTab.BssEntry[i];
1606 if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) < Now32)
1607 continue; // AP disappear
1608 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1609 continue; // RSSI too weak. forget it.
1610 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1611 continue; // skip current AP
1612 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1613 continue; // only AP with stronger RSSI is eligible for roaming
1615 // AP passing all above rules is put into roaming candidate table
1616 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1617 pRoamTab->BssNr += 1;
1620 if (pRoamTab->BssNr > 0)
1622 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1623 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1625 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1626 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1627 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1628 RTMP_MLME_HANDLER(pAd);
1631 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1635 ==========================================================================
1636 Description:
1637 This routine checks if there're other APs out there capable for
1638 roaming. Caller should call this routine only when link up in INFRA mode
1639 and channel quality is below CQI_GOOD_THRESHOLD.
1641 IRQL = DISPATCH_LEVEL
1643 Output:
1644 ==========================================================================
1646 BOOLEAN MlmeCheckForFastRoaming(
1647 IN PRTMP_ADAPTER pAd)
1649 USHORT i;
1650 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1651 BSS_ENTRY *pBss;
1653 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1654 // put all roaming candidates into RoamTab, and sort in RSSI order
1655 BssTableInit(pRoamTab);
1656 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1658 pBss = &pAd->ScanTab.BssEntry[i];
1660 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1661 continue; // RSSI too weak. forget it.
1662 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1663 continue; // skip current AP
1664 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1665 continue; // skip different SSID
1666 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1667 continue; // skip AP without better RSSI
1669 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));
1670 // AP passing all above rules is put into roaming candidate table
1671 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1672 pRoamTab->BssNr += 1;
1675 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1676 if (pRoamTab->BssNr > 0)
1678 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1679 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1681 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1682 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1683 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1684 RTMP_MLME_HANDLER(pAd);
1685 return TRUE;
1689 return FALSE;
1692 VOID MlmeSetTxRate(
1693 IN PRTMP_ADAPTER pAd,
1694 IN PMAC_TABLE_ENTRY pEntry,
1695 IN PRTMP_TX_RATE_SWITCH pTxRate)
1697 UCHAR MaxMode = MODE_OFDM;
1699 MaxMode = MODE_HTGREENFIELD;
1701 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1702 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1703 else
1704 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1706 if (pTxRate->CurrMCS < MCS_AUTO)
1707 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1709 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1710 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1712 if (ADHOC_ON(pAd))
1714 // If peer adhoc is b-only mode, we can't send 11g rate.
1715 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1716 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1719 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1721 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1722 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1723 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1725 // Patch speed error in status page
1726 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1728 else
1730 if (pTxRate->Mode <= MaxMode)
1731 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1733 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1734 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1735 else
1736 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1738 // Reexam each bandwidth's SGI support.
1739 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1741 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1742 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1743 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1744 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1747 // Turn RTS/CTS rate to 6Mbps.
1748 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1750 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1751 if (pAd->MacTab.fAnyBASession)
1753 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1755 else
1757 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1760 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1762 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1763 if (pAd->MacTab.fAnyBASession)
1765 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1767 else
1769 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1772 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1774 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1777 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1779 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1782 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1783 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1784 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1785 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1786 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1787 pAd->WIFItestbed.bGreenField)
1788 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1791 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1795 ==========================================================================
1796 Description:
1797 This routine calculates the acumulated TxPER of eaxh TxRate. And
1798 according to the calculation result, change CommonCfg.TxRate which
1799 is the stable TX Rate we expect the Radio situation could sustained.
1801 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1802 Output:
1803 CommonCfg.TxRate -
1805 IRQL = DISPATCH_LEVEL
1807 NOTE:
1808 call this routine every second
1809 ==========================================================================
1811 VOID MlmeDynamicTxRateSwitching(
1812 IN PRTMP_ADAPTER pAd)
1814 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1815 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1816 ULONG TxErrorRatio = 0;
1817 BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
1818 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1819 PUCHAR pTable;
1820 UCHAR TableSize = 0;
1821 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1822 CHAR Rssi, RssiOffset = 0;
1823 TX_STA_CNT1_STRUC StaTx1;
1824 TX_STA_CNT0_STRUC TxStaCnt0;
1825 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1826 MAC_TABLE_ENTRY *pEntry;
1827 RSSI_SAMPLE *pRssi = &pAd->StaCfg.RssiSample;
1831 // walk through MAC table, see if need to change AP's TX rate toward each entry
1833 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1835 pEntry = &pAd->MacTab.Content[i];
1837 // check if this entry need to switch rate automatically
1838 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1839 continue;
1841 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1843 Rssi = RTMPMaxRssi(pAd,
1844 pRssi->AvgRssi0,
1845 pRssi->AvgRssi1,
1846 pRssi->AvgRssi2);
1848 // Update statistic counter
1849 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1850 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1851 pAd->bUpdateBcnCntDone = TRUE;
1852 TxRetransmit = StaTx1.field.TxRetransmit;
1853 TxSuccess = StaTx1.field.TxSuccess;
1854 TxFailCount = TxStaCnt0.field.TxFailCount;
1855 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1857 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1858 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1859 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1860 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1861 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1862 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1864 // if no traffic in the past 1-sec period, don't change TX rate,
1865 // but clear all bad history. because the bad history may affect the next
1866 // Chariot throughput test
1867 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1868 pAd->RalinkCounters.OneSecTxRetryOkCount +
1869 pAd->RalinkCounters.OneSecTxFailCount;
1871 if (TxTotalCnt)
1872 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1874 else
1876 if (INFRA_ON(pAd) && (i == 1))
1877 Rssi = RTMPMaxRssi(pAd,
1878 pRssi->AvgRssi0,
1879 pRssi->AvgRssi1,
1880 pRssi->AvgRssi2);
1881 else
1882 Rssi = RTMPMaxRssi(pAd,
1883 pEntry->RssiSample.AvgRssi0,
1884 pEntry->RssiSample.AvgRssi1,
1885 pEntry->RssiSample.AvgRssi2);
1887 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1888 pEntry->OneSecTxRetryOkCount +
1889 pEntry->OneSecTxFailCount;
1891 if (TxTotalCnt)
1892 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1895 if (TxTotalCnt)
1898 Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1899 We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1901 if (TxErrorRatio == 100)
1903 TX_RTY_CFG_STRUC TxRtyCfg,TxRtyCfgtmp;
1904 ULONG Index;
1905 ULONG MACValue;
1907 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1908 TxRtyCfgtmp.word = TxRtyCfg.word;
1909 TxRtyCfg.field.LongRtyLimit = 0x0;
1910 TxRtyCfg.field.ShortRtyLimit = 0x0;
1911 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1913 RTMPusecDelay(1);
1915 Index = 0;
1916 MACValue = 0;
1919 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
1920 if ((MACValue & 0xffffff) == 0)
1921 break;
1922 Index++;
1923 RTMPusecDelay(1000);
1924 }while((Index < 330)&&(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)));
1926 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1927 TxRtyCfg.field.LongRtyLimit = TxRtyCfgtmp.field.LongRtyLimit;
1928 TxRtyCfg.field.ShortRtyLimit = TxRtyCfgtmp.field.ShortRtyLimit;
1929 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1933 CurrRateIdx = pEntry->CurrTxRateIndex;
1935 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1937 if (CurrRateIdx >= TableSize)
1939 CurrRateIdx = TableSize - 1;
1942 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1943 // So need to sync here.
1944 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1945 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1946 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1950 // Need to sync Real Tx rate and our record.
1951 // Then return for next DRS.
1952 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1953 pEntry->CurrTxRateIndex = InitTxRateIdx;
1954 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1956 // reset all OneSecTx counters
1957 RESET_ONE_SEC_TX_CNT(pEntry);
1958 continue;
1961 // decide the next upgrade rate and downgrade rate, if any
1962 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
1964 UpRateIdx = CurrRateIdx + 1;
1965 DownRateIdx = CurrRateIdx -1;
1967 else if (CurrRateIdx == 0)
1969 UpRateIdx = CurrRateIdx + 1;
1970 DownRateIdx = CurrRateIdx;
1972 else if (CurrRateIdx == (TableSize - 1))
1974 UpRateIdx = CurrRateIdx;
1975 DownRateIdx = CurrRateIdx - 1;
1978 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1980 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
1982 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
1983 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
1985 else
1987 TrainUp = pCurrTxRate->TrainUp;
1988 TrainDown = pCurrTxRate->TrainDown;
1991 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
1994 // Keep the last time TxRateChangeAction status.
1996 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2001 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2002 // (criteria copied from RT2500 for Netopia case)
2004 if (TxTotalCnt <= 15)
2006 CHAR idx = 0;
2007 UCHAR TxRateIdx;
2008 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2009 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2010 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2012 // check the existence and index of each needed MCS
2013 while (idx < pTable[0])
2015 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2017 if (pCurrTxRate->CurrMCS == MCS_0)
2019 MCS0 = idx;
2021 else if (pCurrTxRate->CurrMCS == MCS_1)
2023 MCS1 = idx;
2025 else if (pCurrTxRate->CurrMCS == MCS_2)
2027 MCS2 = idx;
2029 else if (pCurrTxRate->CurrMCS == MCS_3)
2031 MCS3 = idx;
2033 else if (pCurrTxRate->CurrMCS == MCS_4)
2035 MCS4 = idx;
2037 else if (pCurrTxRate->CurrMCS == MCS_5)
2039 MCS5 = idx;
2041 else if (pCurrTxRate->CurrMCS == MCS_6)
2043 MCS6 = idx;
2045 //else if (pCurrTxRate->CurrMCS == MCS_7)
2046 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2048 MCS7 = idx;
2050 else if (pCurrTxRate->CurrMCS == MCS_12)
2052 MCS12 = idx;
2054 else if (pCurrTxRate->CurrMCS == MCS_13)
2056 MCS13 = idx;
2058 else if (pCurrTxRate->CurrMCS == MCS_14)
2060 MCS14 = idx;
2062 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2063 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
2065 MCS15 = idx;
2067 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2069 MCS20 = idx;
2071 else if (pCurrTxRate->CurrMCS == MCS_21)
2073 MCS21 = idx;
2075 else if (pCurrTxRate->CurrMCS == MCS_22)
2077 MCS22 = idx;
2079 else if (pCurrTxRate->CurrMCS == MCS_23)
2081 MCS23 = idx;
2083 idx ++;
2086 if (pAd->LatchRfRegs.Channel <= 14)
2088 if (pAd->NicConfig2.field.ExternalLNAForG)
2090 RssiOffset = 2;
2092 else
2094 RssiOffset = 5;
2097 else
2099 if (pAd->NicConfig2.field.ExternalLNAForA)
2101 RssiOffset = 5;
2103 else
2105 RssiOffset = 8;
2109 /*if (MCS15)*/
2110 if ((pTable == RateSwitchTable11BGN3S) ||
2111 (pTable == RateSwitchTable11N3S) ||
2112 (pTable == RateSwitchTable))
2113 {// N mode with 3 stream // 3*3
2114 if (MCS23 && (Rssi >= -70))
2115 TxRateIdx = MCS23;
2116 else if (MCS22 && (Rssi >= -72))
2117 TxRateIdx = MCS22;
2118 else if (MCS21 && (Rssi >= -76))
2119 TxRateIdx = MCS21;
2120 else if (MCS20 && (Rssi >= -78))
2121 TxRateIdx = MCS20;
2122 else if (MCS4 && (Rssi >= -82))
2123 TxRateIdx = MCS4;
2124 else if (MCS3 && (Rssi >= -84))
2125 TxRateIdx = MCS3;
2126 else if (MCS2 && (Rssi >= -86))
2127 TxRateIdx = MCS2;
2128 else if (MCS1 && (Rssi >= -88))
2129 TxRateIdx = MCS1;
2130 else
2131 TxRateIdx = MCS0;
2133 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2134 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2135 {// N mode with 2 stream
2136 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2137 TxRateIdx = MCS15;
2138 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2139 TxRateIdx = MCS14;
2140 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2141 TxRateIdx = MCS13;
2142 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2143 TxRateIdx = MCS12;
2144 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2145 TxRateIdx = MCS4;
2146 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2147 TxRateIdx = MCS3;
2148 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2149 TxRateIdx = MCS2;
2150 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2151 TxRateIdx = MCS1;
2152 else
2153 TxRateIdx = MCS0;
2155 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2156 {// N mode with 1 stream
2157 if (MCS7 && (Rssi > (-72+RssiOffset)))
2158 TxRateIdx = MCS7;
2159 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2160 TxRateIdx = MCS6;
2161 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2162 TxRateIdx = MCS5;
2163 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2164 TxRateIdx = MCS4;
2165 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2166 TxRateIdx = MCS3;
2167 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2168 TxRateIdx = MCS2;
2169 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2170 TxRateIdx = MCS1;
2171 else
2172 TxRateIdx = MCS0;
2174 else
2175 {// Legacy mode
2176 if (MCS7 && (Rssi > -70))
2177 TxRateIdx = MCS7;
2178 else if (MCS6 && (Rssi > -74))
2179 TxRateIdx = MCS6;
2180 else if (MCS5 && (Rssi > -78))
2181 TxRateIdx = MCS5;
2182 else if (MCS4 && (Rssi > -82))
2183 TxRateIdx = MCS4;
2184 else if (MCS4 == 0) // for B-only mode
2185 TxRateIdx = MCS3;
2186 else if (MCS3 && (Rssi > -85))
2187 TxRateIdx = MCS3;
2188 else if (MCS2 && (Rssi > -87))
2189 TxRateIdx = MCS2;
2190 else if (MCS1 && (Rssi > -90))
2191 TxRateIdx = MCS1;
2192 else
2193 TxRateIdx = MCS0;
2196 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2198 pEntry->CurrTxRateIndex = TxRateIdx;
2199 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2200 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2203 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2204 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2205 pEntry->fLastSecAccordingRSSI = TRUE;
2206 // reset all OneSecTx counters
2207 RESET_ONE_SEC_TX_CNT(pEntry);
2209 continue;
2212 if (pEntry->fLastSecAccordingRSSI == TRUE)
2214 pEntry->fLastSecAccordingRSSI = FALSE;
2215 pEntry->LastSecTxRateChangeAction = 0;
2216 // reset all OneSecTx counters
2217 RESET_ONE_SEC_TX_CNT(pEntry);
2219 continue;
2224 BOOLEAN bTrainUpDown = FALSE;
2226 pEntry->CurrTxRateStableTime ++;
2228 // downgrade TX quality if PER >= Rate-Down threshold
2229 if (TxErrorRatio >= TrainDown)
2231 bTrainUpDown = TRUE;
2232 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2234 // upgrade TX quality if PER <= Rate-Up threshold
2235 else if (TxErrorRatio <= TrainUp)
2237 bTrainUpDown = TRUE;
2238 bUpgradeQuality = TRUE;
2239 if (pEntry->TxQuality[CurrRateIdx])
2240 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2242 if (pEntry->TxRateUpPenalty)
2243 pEntry->TxRateUpPenalty --;
2244 else if (pEntry->TxQuality[UpRateIdx])
2245 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2248 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2250 if (bTrainUpDown)
2252 // perform DRS - consider TxRate Down first, then rate up.
2253 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2255 pEntry->CurrTxRateIndex = DownRateIdx;
2257 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2259 pEntry->CurrTxRateIndex = UpRateIdx;
2262 } while (FALSE);
2264 // if rate-up happen, clear all bad history of all TX rates
2265 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2267 pEntry->CurrTxRateStableTime = 0;
2268 pEntry->TxRateUpPenalty = 0;
2269 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2270 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2271 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2274 // For TxRate fast train up
2276 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2278 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2280 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2282 bTxRateChanged = TRUE;
2284 // if rate-down happen, only clear DownRate's bad history
2285 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2287 pEntry->CurrTxRateStableTime = 0;
2288 pEntry->TxRateUpPenalty = 0; // no penalty
2289 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2290 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2291 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2294 // For TxRate fast train down
2296 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2298 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2300 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2302 bTxRateChanged = TRUE;
2304 else
2306 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2307 bTxRateChanged = FALSE;
2310 pEntry->LastTxOkCount = TxSuccess;
2312 UCHAR tmpTxRate;
2314 // to fix tcp ack issue
2315 if (!bTxRateChanged && (pAd->RalinkCounters.OneSecReceivedByteCount > (pAd->RalinkCounters.OneSecTransmittedByteCount * 5)))
2317 tmpTxRate = DownRateIdx;
2318 DBGPRINT_RAW(RT_DEBUG_TRACE,("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2319 pAd->RalinkCounters.OneSecReceivedByteCount, pAd->RalinkCounters.OneSecTransmittedByteCount, pEntry->CurrTxRateIndex, tmpTxRate));
2321 else
2323 tmpTxRate = pEntry->CurrTxRateIndex;
2326 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(tmpTxRate+1)*5];
2328 if (bTxRateChanged && pNextTxRate)
2330 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2332 // reset all OneSecTx counters
2333 RESET_ONE_SEC_TX_CNT(pEntry);
2338 ========================================================================
2339 Routine Description:
2340 Station side, Auto TxRate faster train up timer call back function.
2342 Arguments:
2343 SystemSpecific1 - Not used.
2344 FunctionContext - Pointer to our Adapter context.
2345 SystemSpecific2 - Not used.
2346 SystemSpecific3 - Not used.
2348 Return Value:
2349 None
2351 ========================================================================
2353 VOID StaQuickResponeForRateUpExec(
2354 IN PVOID SystemSpecific1,
2355 IN PVOID FunctionContext,
2356 IN PVOID SystemSpecific2,
2357 IN PVOID SystemSpecific3)
2359 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2360 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2361 ULONG TxTotalCnt;
2362 ULONG TxErrorRatio = 0;
2363 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2364 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2365 PUCHAR pTable;
2366 UCHAR TableSize = 0;
2367 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2368 TX_STA_CNT1_STRUC StaTx1;
2369 TX_STA_CNT0_STRUC TxStaCnt0;
2370 CHAR Rssi, ratio;
2371 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2372 MAC_TABLE_ENTRY *pEntry;
2373 ULONG i;
2375 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2378 // walk through MAC table, see if need to change AP's TX rate toward each entry
2380 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2382 pEntry = &pAd->MacTab.Content[i];
2384 // check if this entry need to switch rate automatically
2385 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2386 continue;
2388 if (INFRA_ON(pAd) && (i == 1))
2389 Rssi = RTMPMaxRssi(pAd,
2390 pAd->StaCfg.RssiSample.AvgRssi0,
2391 pAd->StaCfg.RssiSample.AvgRssi1,
2392 pAd->StaCfg.RssiSample.AvgRssi2);
2393 else
2394 Rssi = RTMPMaxRssi(pAd,
2395 pEntry->RssiSample.AvgRssi0,
2396 pEntry->RssiSample.AvgRssi1,
2397 pEntry->RssiSample.AvgRssi2);
2399 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2401 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2403 // decide the next upgrade rate and downgrade rate, if any
2404 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2406 UpRateIdx = CurrRateIdx + 1;
2407 DownRateIdx = CurrRateIdx -1;
2409 else if (CurrRateIdx == 0)
2411 UpRateIdx = CurrRateIdx + 1;
2412 DownRateIdx = CurrRateIdx;
2414 else if (CurrRateIdx == (TableSize - 1))
2416 UpRateIdx = CurrRateIdx;
2417 DownRateIdx = CurrRateIdx - 1;
2420 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2422 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2424 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2425 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2427 else
2429 TrainUp = pCurrTxRate->TrainUp;
2430 TrainDown = pCurrTxRate->TrainDown;
2433 if (pAd->MacTab.Size == 1)
2435 // Update statistic counter
2436 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2437 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2439 TxRetransmit = StaTx1.field.TxRetransmit;
2440 TxSuccess = StaTx1.field.TxSuccess;
2441 TxFailCount = TxStaCnt0.field.TxFailCount;
2442 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2444 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2445 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2446 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2447 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2448 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2449 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2451 if (TxTotalCnt)
2452 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2454 else
2456 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2457 pEntry->OneSecTxRetryOkCount +
2458 pEntry->OneSecTxFailCount;
2460 if (TxTotalCnt)
2461 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2466 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2467 // (criteria copied from RT2500 for Netopia case)
2469 if (TxTotalCnt <= 12)
2471 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2472 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2474 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2476 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2477 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2479 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2481 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2484 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2485 return;
2490 ULONG OneSecTxNoRetryOKRationCount;
2492 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2493 ratio = 5;
2494 else
2495 ratio = 4;
2497 // downgrade TX quality if PER >= Rate-Down threshold
2498 if (TxErrorRatio >= TrainDown)
2500 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2503 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2505 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2507 // perform DRS - consider TxRate Down first, then rate up.
2508 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2510 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2512 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2513 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2518 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2520 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2524 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2526 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2529 }while (FALSE);
2531 // if rate-up happen, clear all bad history of all TX rates
2532 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2534 pAd->DrsCounters.TxRateUpPenalty = 0;
2535 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2536 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2537 bTxRateChanged = TRUE;
2539 // if rate-down happen, only clear DownRate's bad history
2540 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2542 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2544 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2545 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2546 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2547 bTxRateChanged = TRUE;
2549 else
2551 bTxRateChanged = FALSE;
2554 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2555 if (bTxRateChanged && pNextTxRate)
2557 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2563 ==========================================================================
2564 Description:
2565 This routine is executed periodically inside MlmePeriodicExec() after
2566 association with an AP.
2567 It checks if StaCfg.Psm is consistent with user policy (recorded in
2568 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2569 there're some conditions to consider:
2570 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2571 the time when Mibss==TRUE
2572 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2573 if outgoing traffic available in TxRing or MgmtRing.
2574 Output:
2575 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2577 IRQL = DISPATCH_LEVEL
2579 ==========================================================================
2581 VOID MlmeCheckPsmChange(
2582 IN PRTMP_ADAPTER pAd,
2583 IN ULONG Now32)
2585 ULONG PowerMode;
2587 // condition -
2588 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2589 // 2. user wants either MAX_PSP or FAST_PSP
2590 // 3. but current psm is not in PWR_SAVE
2591 // 4. CNTL state machine is not doing SCANning
2592 // 5. no TX SUCCESS event for the past 1-sec period
2593 PowerMode = pAd->StaCfg.WindowsPowerMode;
2595 if (INFRA_ON(pAd) &&
2596 (PowerMode != Ndis802_11PowerModeCAM) &&
2597 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2598 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2599 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)&&
2600 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2601 /*&&
2602 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2603 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2605 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2606 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2607 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
2608 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2610 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2612 else
2614 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2619 // IRQL = PASSIVE_LEVEL
2620 // IRQL = DISPATCH_LEVEL
2621 VOID MlmeSetPsmBit(
2622 IN PRTMP_ADAPTER pAd,
2623 IN USHORT psm)
2625 AUTO_RSP_CFG_STRUC csr4;
2627 pAd->StaCfg.Psm = psm;
2628 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2629 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2630 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2632 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2636 ==========================================================================
2637 Description:
2638 This routine calculates TxPER, RxPER of the past N-sec period. And
2639 according to the calculation result, ChannelQuality is calculated here
2640 to decide if current AP is still doing the job.
2642 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2643 Output:
2644 StaCfg.ChannelQuality - 0..100
2646 IRQL = DISPATCH_LEVEL
2648 NOTE: This routine decide channle quality based on RX CRC error ratio.
2649 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2650 is performed right before this routine, so that this routine can decide
2651 channel quality based on the most up-to-date information
2652 ==========================================================================
2654 VOID MlmeCalculateChannelQuality(
2655 IN PRTMP_ADAPTER pAd,
2656 IN PMAC_TABLE_ENTRY pMacEntry,
2657 IN ULONG Now32)
2659 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
2660 ULONG RxCnt, RxPER;
2661 UCHAR NorRssi;
2662 CHAR MaxRssi;
2663 RSSI_SAMPLE *pRssiSample = NULL;
2664 UINT32 OneSecTxNoRetryOkCount = 0;
2665 UINT32 OneSecTxRetryOkCount = 0;
2666 UINT32 OneSecTxFailCount = 0;
2667 UINT32 OneSecRxOkCnt = 0;
2668 UINT32 OneSecRxFcsErrCnt = 0;
2669 ULONG ChannelQuality = 0; // 0..100, Channel Quality Indication for Roaming
2670 ULONG BeaconLostTime = pAd->StaCfg.BeaconLostTime;
2673 if (pAd->OpMode == OPMODE_STA)
2675 pRssiSample = &pAd->StaCfg.RssiSample;
2676 OneSecTxNoRetryOkCount = pAd->RalinkCounters.OneSecTxNoRetryOkCount;
2677 OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2678 OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2679 OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2680 OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
2683 MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
2684 pRssiSample->LastRssi1,
2685 pRssiSample->LastRssi2);
2688 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
2690 TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2691 TxCnt = TxOkCnt + OneSecTxFailCount;
2692 if (TxCnt < 5)
2694 TxPER = 0;
2695 TxPRR = 0;
2697 else
2699 TxPER = (OneSecTxFailCount * 100) / TxCnt;
2700 TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2704 // calculate RX PER - don't take RxPER into consideration if too few sample
2706 RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2707 if (RxCnt < 5)
2708 RxPER = 0;
2709 else
2710 RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
2713 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
2715 if ((pAd->OpMode == OPMODE_STA) &&
2716 INFRA_ON(pAd) &&
2717 (OneSecTxNoRetryOkCount < 2) && // no heavy traffic
2718 ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32))
2720 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
2721 ChannelQuality = 0;
2723 else
2725 // Normalize Rssi
2726 if (MaxRssi > -40)
2727 NorRssi = 100;
2728 else if (MaxRssi < -90)
2729 NorRssi = 0;
2730 else
2731 NorRssi = (MaxRssi + 90) * 2;
2733 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
2734 ChannelQuality = (RSSI_WEIGHTING * NorRssi +
2735 TX_WEIGHTING * (100 - TxPRR) +
2736 RX_WEIGHTING* (100 - RxPER)) / 100;
2740 if (pAd->OpMode == OPMODE_STA)
2741 pAd->Mlme.ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality;
2747 // IRQL = DISPATCH_LEVEL
2748 VOID MlmeSetTxPreamble(
2749 IN PRTMP_ADAPTER pAd,
2750 IN USHORT TxPreamble)
2752 AUTO_RSP_CFG_STRUC csr4;
2755 // Always use Long preamble before verifiation short preamble functionality works well.
2756 // Todo: remove the following line if short preamble functionality works
2758 //TxPreamble = Rt802_11PreambleLong;
2760 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2761 if (TxPreamble == Rt802_11PreambleLong)
2763 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2764 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2765 csr4.field.AutoResponderPreamble = 0;
2767 else
2769 // NOTE: 1Mbps should always use long preamble
2770 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2771 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2772 csr4.field.AutoResponderPreamble = 1;
2775 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2779 ==========================================================================
2780 Description:
2781 Update basic rate bitmap
2782 ==========================================================================
2785 VOID UpdateBasicRateBitmap(
2786 IN PRTMP_ADAPTER pAdapter)
2788 INT i, j;
2789 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2790 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2791 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2792 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2793 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2796 /* if A mode, always use fix BasicRateBitMap */
2797 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2798 if (pAdapter->CommonCfg.Channel > 14)
2799 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2800 /* End of if */
2802 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2804 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2805 return;
2806 } /* End of if */
2808 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2810 sup_p[i] &= 0x7f;
2811 ext_p[i] &= 0x7f;
2812 } /* End of for */
2814 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2816 if (bitmap & (1 << i))
2818 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2820 if (sup_p[j] == rate[i])
2821 sup_p[j] |= 0x80;
2822 /* End of if */
2823 } /* End of for */
2825 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2827 if (ext_p[j] == rate[i])
2828 ext_p[j] |= 0x80;
2829 /* End of if */
2830 } /* End of for */
2831 } /* End of if */
2832 } /* End of for */
2833 } /* End of UpdateBasicRateBitmap */
2835 // IRQL = PASSIVE_LEVEL
2836 // IRQL = DISPATCH_LEVEL
2837 // bLinkUp is to identify the inital link speed.
2838 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2839 VOID MlmeUpdateTxRates(
2840 IN PRTMP_ADAPTER pAd,
2841 IN BOOLEAN bLinkUp,
2842 IN UCHAR apidx)
2844 int i, num;
2845 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2846 UCHAR MinSupport = RATE_54;
2847 ULONG BasicRateBitmap = 0;
2848 UCHAR CurrBasicRate = RATE_1;
2849 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2850 PHTTRANSMIT_SETTING pHtPhy = NULL;
2851 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2852 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2853 BOOLEAN *auto_rate_cur_p;
2854 UCHAR HtMcs = MCS_AUTO;
2856 // find max desired rate
2857 UpdateBasicRateBitmap(pAd);
2859 num = 0;
2860 auto_rate_cur_p = NULL;
2861 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2863 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2865 case 2: Rate = RATE_1; num++; break;
2866 case 4: Rate = RATE_2; num++; break;
2867 case 11: Rate = RATE_5_5; num++; break;
2868 case 22: Rate = RATE_11; num++; break;
2869 case 12: Rate = RATE_6; num++; break;
2870 case 18: Rate = RATE_9; num++; break;
2871 case 24: Rate = RATE_12; num++; break;
2872 case 36: Rate = RATE_18; num++; break;
2873 case 48: Rate = RATE_24; num++; break;
2874 case 72: Rate = RATE_36; num++; break;
2875 case 96: Rate = RATE_48; num++; break;
2876 case 108: Rate = RATE_54; num++; break;
2877 //default: Rate = RATE_1; break;
2879 if (MaxDesire < Rate) MaxDesire = Rate;
2882 //===========================================================================
2883 //===========================================================================
2885 pHtPhy = &pAd->StaCfg.HTPhyMode;
2886 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2887 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2889 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2890 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2892 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2893 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2894 (MaxDesire > RATE_11))
2896 MaxDesire = RATE_11;
2900 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2901 pMinHtPhy->word = 0;
2902 pMaxHtPhy->word = 0;
2903 pHtPhy->word = 0;
2905 // Auto rate switching is enabled only if more than one DESIRED RATES are
2906 // specified; otherwise disabled
2907 if (num <= 1)
2909 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2910 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2911 *auto_rate_cur_p = FALSE;
2913 else
2915 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2916 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2917 *auto_rate_cur_p = TRUE;
2920 if (HtMcs != MCS_AUTO)
2922 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2923 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2924 *auto_rate_cur_p = FALSE;
2926 else
2928 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2929 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2930 *auto_rate_cur_p = TRUE;
2933 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2935 pSupRate = &pAd->StaActive.SupRate[0];
2936 pExtRate = &pAd->StaActive.ExtRate[0];
2937 SupRateLen = pAd->StaActive.SupRateLen;
2938 ExtRateLen = pAd->StaActive.ExtRateLen;
2940 else
2942 pSupRate = &pAd->CommonCfg.SupRate[0];
2943 pExtRate = &pAd->CommonCfg.ExtRate[0];
2944 SupRateLen = pAd->CommonCfg.SupRateLen;
2945 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2948 // find max supported rate
2949 for (i=0; i<SupRateLen; i++)
2951 switch (pSupRate[i] & 0x7f)
2953 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2954 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2955 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2956 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2957 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2958 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2959 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2960 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2961 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2962 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2963 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2964 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2965 default: Rate = RATE_1; break;
2967 if (MaxSupport < Rate) MaxSupport = Rate;
2969 if (MinSupport > Rate) MinSupport = Rate;
2972 for (i=0; i<ExtRateLen; i++)
2974 switch (pExtRate[i] & 0x7f)
2976 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2977 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2978 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2979 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2980 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2981 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2982 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2983 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2984 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2985 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2986 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2987 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2988 default: Rate = RATE_1; break;
2990 if (MaxSupport < Rate) MaxSupport = Rate;
2992 if (MinSupport > Rate) MinSupport = Rate;
2995 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2997 // bug fix
2998 // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
3000 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3001 // the DURATION field of outgoing uniicast DATA/MGMT frame
3002 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3004 if (BasicRateBitmap & (0x01 << i))
3005 CurrBasicRate = (UCHAR)i;
3006 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3009 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3010 // max tx rate = min {max desire rate, max supported rate}
3011 if (MaxSupport < MaxDesire)
3012 pAd->CommonCfg.MaxTxRate = MaxSupport;
3013 else
3014 pAd->CommonCfg.MaxTxRate = MaxDesire;
3016 pAd->CommonCfg.MinTxRate = MinSupport;
3017 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
3018 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
3019 // on average RSSI
3020 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
3021 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
3022 // 3. -75 > RSSI, start at 11 Mbps (long distance)
3023 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
3024 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
3025 if (*auto_rate_cur_p)
3027 short dbm = 0;
3029 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3031 if (bLinkUp == TRUE)
3032 pAd->CommonCfg.TxRate = RATE_24;
3033 else
3034 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3036 if (dbm < -75)
3037 pAd->CommonCfg.TxRate = RATE_11;
3038 else if (dbm < -70)
3039 pAd->CommonCfg.TxRate = RATE_24;
3041 // should never exceed MaxTxRate (consider 11B-only mode)
3042 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3043 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3045 pAd->CommonCfg.TxRateIndex = 0;
3047 else
3049 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3050 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3051 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3053 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3054 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3055 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3056 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3059 if (pAd->CommonCfg.TxRate <= RATE_11)
3061 pMaxHtPhy->field.MODE = MODE_CCK;
3062 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3063 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3065 else
3067 pMaxHtPhy->field.MODE = MODE_OFDM;
3068 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3069 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3070 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3071 else
3072 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3075 pHtPhy->word = (pMaxHtPhy->word);
3076 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3078 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3079 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3080 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3082 else
3084 switch (pAd->CommonCfg.PhyMode)
3086 case PHY_11BG_MIXED:
3087 case PHY_11B:
3088 case PHY_11BGN_MIXED:
3089 pAd->CommonCfg.MlmeRate = RATE_1;
3090 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3091 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3093 //#ifdef WIFI_TEST
3094 pAd->CommonCfg.RtsRate = RATE_11;
3095 //#else
3096 // pAd->CommonCfg.RtsRate = RATE_1;
3097 //#endif
3098 break;
3099 case PHY_11G:
3100 case PHY_11A:
3101 case PHY_11AGN_MIXED:
3102 case PHY_11GN_MIXED:
3103 case PHY_11N_2_4G:
3104 case PHY_11AN_MIXED:
3105 case PHY_11N_5G:
3106 pAd->CommonCfg.MlmeRate = RATE_6;
3107 pAd->CommonCfg.RtsRate = RATE_6;
3108 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3109 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3110 break;
3111 case PHY_11ABG_MIXED:
3112 case PHY_11ABGN_MIXED:
3113 if (pAd->CommonCfg.Channel <= 14)
3115 pAd->CommonCfg.MlmeRate = RATE_1;
3116 pAd->CommonCfg.RtsRate = RATE_1;
3117 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3118 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3120 else
3122 pAd->CommonCfg.MlmeRate = RATE_6;
3123 pAd->CommonCfg.RtsRate = RATE_6;
3124 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3125 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3127 break;
3128 default: // error
3129 pAd->CommonCfg.MlmeRate = RATE_6;
3130 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3131 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3132 pAd->CommonCfg.RtsRate = RATE_1;
3133 break;
3136 // Keep Basic Mlme Rate.
3138 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3139 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3140 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3141 else
3142 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3143 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3146 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3147 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3148 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3149 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3150 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3151 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3152 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 ));
3156 ==========================================================================
3157 Description:
3158 This function update HT Rate setting.
3159 Input Wcid value is valid for 2 case :
3160 1. it's used for Station in infra mode that copy AP rate to Mactable.
3161 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3163 IRQL = DISPATCH_LEVEL
3165 ==========================================================================
3167 VOID MlmeUpdateHtTxRates(
3168 IN PRTMP_ADAPTER pAd,
3169 IN UCHAR apidx)
3171 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3172 CHAR i; // 3*3
3173 RT_HT_CAPABILITY *pRtHtCap = NULL;
3174 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3175 ULONG BasicMCS;
3176 UCHAR j, bitmask;
3177 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3178 PHTTRANSMIT_SETTING pHtPhy = NULL;
3179 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3180 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3181 BOOLEAN *auto_rate_cur_p;
3183 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3185 auto_rate_cur_p = NULL;
3188 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3189 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3190 pHtPhy = &pAd->StaCfg.HTPhyMode;
3191 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3192 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3194 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3197 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3199 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3200 return;
3202 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3203 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3204 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3205 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3206 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3207 pMaxHtPhy->field.STBC = STBC_USE;
3208 else
3209 pMaxHtPhy->field.STBC = STBC_NONE;
3211 else
3213 if (pDesireHtPhy->bHtEnable == FALSE)
3214 return;
3216 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3217 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3218 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3219 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3220 pMaxHtPhy->field.STBC = STBC_USE;
3221 else
3222 pMaxHtPhy->field.STBC = STBC_NONE;
3225 // Decide MAX ht rate.
3226 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3227 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3228 else
3229 pMaxHtPhy->field.MODE = MODE_HTMIX;
3231 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3232 pMaxHtPhy->field.BW = BW_40;
3233 else
3234 pMaxHtPhy->field.BW = BW_20;
3236 if (pMaxHtPhy->field.BW == BW_20)
3237 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3238 else
3239 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3241 if (pDesireHtPhy->MCSSet[4] != 0)
3243 pMaxHtPhy->field.MCS = 32;
3246 for (i=23; i>=0; i--) // 3*3
3248 j = i/8;
3249 bitmask = (1<<(i-(j*8)));
3251 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3253 pMaxHtPhy->field.MCS = i;
3254 break;
3257 if (i==0)
3258 break;
3261 // Copy MIN ht rate. rt2860???
3262 pMinHtPhy->field.BW = BW_20;
3263 pMinHtPhy->field.MCS = 0;
3264 pMinHtPhy->field.STBC = 0;
3265 pMinHtPhy->field.ShortGI = 0;
3266 //If STA assigns fixed rate. update to fixed here.
3267 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3269 if (pDesireHtPhy->MCSSet[4] != 0)
3271 pMaxHtPhy->field.MCS = 32;
3272 pMinHtPhy->field.MCS = 32;
3273 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3276 for (i=23; (CHAR)i >= 0; i--) // 3*3
3278 j = i/8;
3279 bitmask = (1<<(i-(j*8)));
3280 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3282 pMaxHtPhy->field.MCS = i;
3283 pMinHtPhy->field.MCS = i;
3284 break;
3286 if (i==0)
3287 break;
3292 // Decide ht rate
3293 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3294 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3295 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3296 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3297 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3299 // use default now. rt2860
3300 if (pDesireHtPhy->MCSSet[0] != 0xff)
3301 *auto_rate_cur_p = FALSE;
3302 else
3303 *auto_rate_cur_p = TRUE;
3305 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3306 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3307 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3308 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3312 VOID BATableInit(
3313 IN PRTMP_ADAPTER pAd,
3314 IN BA_TABLE *Tab)
3316 int i;
3318 Tab->numAsOriginator = 0;
3319 Tab->numAsRecipient = 0;
3320 Tab->numDoneOriginator = 0;
3321 NdisAllocateSpinLock(&pAd->BATabLock);
3322 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3324 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3325 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3327 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3329 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3333 // IRQL = DISPATCH_LEVEL
3334 VOID MlmeRadioOff(
3335 IN PRTMP_ADAPTER pAd)
3337 RTMP_MLME_RADIO_OFF(pAd);
3340 // IRQL = DISPATCH_LEVEL
3341 VOID MlmeRadioOn(
3342 IN PRTMP_ADAPTER pAd)
3344 RTMP_MLME_RADIO_ON(pAd);
3347 // ===========================================================================================
3348 // bss_table.c
3349 // ===========================================================================================
3352 /*! \brief initialize BSS table
3353 * \param p_tab pointer to the table
3354 * \return none
3355 * \pre
3356 * \post
3358 IRQL = PASSIVE_LEVEL
3359 IRQL = DISPATCH_LEVEL
3362 VOID BssTableInit(
3363 IN BSS_TABLE *Tab)
3365 int i;
3367 Tab->BssNr = 0;
3368 Tab->BssOverlapNr = 0;
3369 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3371 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3372 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3377 /*! \brief search the BSS table by SSID
3378 * \param p_tab pointer to the bss table
3379 * \param ssid SSID string
3380 * \return index of the table, BSS_NOT_FOUND if not in the table
3381 * \pre
3382 * \post
3383 * \note search by sequential search
3385 IRQL = DISPATCH_LEVEL
3388 ULONG BssTableSearch(
3389 IN BSS_TABLE *Tab,
3390 IN PUCHAR pBssid,
3391 IN UCHAR Channel)
3393 UCHAR i;
3395 for (i = 0; i < Tab->BssNr; i++)
3398 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3399 // We should distinguish this case.
3401 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3402 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3403 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3405 return i;
3408 return (ULONG)BSS_NOT_FOUND;
3411 ULONG BssSsidTableSearch(
3412 IN BSS_TABLE *Tab,
3413 IN PUCHAR pBssid,
3414 IN PUCHAR pSsid,
3415 IN UCHAR SsidLen,
3416 IN UCHAR Channel)
3418 UCHAR i;
3420 for (i = 0; i < Tab->BssNr; i++)
3423 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3424 // We should distinguish this case.
3426 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3427 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3428 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3429 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3431 return i;
3434 return (ULONG)BSS_NOT_FOUND;
3437 ULONG BssTableSearchWithSSID(
3438 IN BSS_TABLE *Tab,
3439 IN PUCHAR Bssid,
3440 IN PUCHAR pSsid,
3441 IN UCHAR SsidLen,
3442 IN UCHAR Channel)
3444 UCHAR i;
3446 for (i = 0; i < Tab->BssNr; i++)
3448 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3449 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3450 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3451 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3452 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3453 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3455 return i;
3458 return (ULONG)BSS_NOT_FOUND;
3462 ULONG BssSsidTableSearchBySSID(
3463 IN BSS_TABLE *Tab,
3464 IN PUCHAR pSsid,
3465 IN UCHAR SsidLen)
3467 UCHAR i;
3469 for (i = 0; i < Tab->BssNr; i++)
3471 if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3473 return i;
3476 return (ULONG)BSS_NOT_FOUND;
3480 // IRQL = DISPATCH_LEVEL
3481 VOID BssTableDeleteEntry(
3482 IN OUT BSS_TABLE *Tab,
3483 IN PUCHAR pBssid,
3484 IN UCHAR Channel)
3486 UCHAR i, j;
3488 for (i = 0; i < Tab->BssNr; i++)
3490 if ((Tab->BssEntry[i].Channel == Channel) &&
3491 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3493 for (j = i; j < Tab->BssNr - 1; j++)
3495 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3497 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3498 Tab->BssNr -= 1;
3499 return;
3505 ========================================================================
3506 Routine Description:
3507 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3509 Arguments:
3510 // IRQL = DISPATCH_LEVEL
3511 ========================================================================
3513 VOID BATableDeleteORIEntry(
3514 IN OUT PRTMP_ADAPTER pAd,
3515 IN BA_ORI_ENTRY *pBAORIEntry)
3518 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3520 NdisAcquireSpinLock(&pAd->BATabLock);
3521 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3523 pAd->BATable.numAsOriginator -= 1;
3524 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3525 // Erase Bitmap flag.
3527 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3528 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3529 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3530 pBAORIEntry->Token = 1;
3531 // Not clear Sequence here.
3532 NdisReleaseSpinLock(&pAd->BATabLock);
3536 /*! \brief
3537 * \param
3538 * \return
3539 * \pre
3540 * \post
3542 IRQL = DISPATCH_LEVEL
3545 VOID BssEntrySet(
3546 IN PRTMP_ADAPTER pAd,
3547 OUT BSS_ENTRY *pBss,
3548 IN PUCHAR pBssid,
3549 IN CHAR Ssid[],
3550 IN UCHAR SsidLen,
3551 IN UCHAR BssType,
3552 IN USHORT BeaconPeriod,
3553 IN PCF_PARM pCfParm,
3554 IN USHORT AtimWin,
3555 IN USHORT CapabilityInfo,
3556 IN UCHAR SupRate[],
3557 IN UCHAR SupRateLen,
3558 IN UCHAR ExtRate[],
3559 IN UCHAR ExtRateLen,
3560 IN HT_CAPABILITY_IE *pHtCapability,
3561 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3562 IN UCHAR HtCapabilityLen,
3563 IN UCHAR AddHtInfoLen,
3564 IN UCHAR NewExtChanOffset,
3565 IN UCHAR Channel,
3566 IN CHAR Rssi,
3567 IN LARGE_INTEGER TimeStamp,
3568 IN UCHAR CkipFlag,
3569 IN PEDCA_PARM pEdcaParm,
3570 IN PQOS_CAPABILITY_PARM pQosCapability,
3571 IN PQBSS_LOAD_PARM pQbssLoad,
3572 IN USHORT LengthVIE,
3573 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3575 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3576 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3577 pBss->Hidden = 1;
3578 if (SsidLen > 0)
3580 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3581 // Or send beacon /probe response with SSID len matching real SSID length,
3582 // but SSID is all zero. such as "00-00-00-00" with length 4.
3583 // We have to prevent this case overwrite correct table
3584 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3586 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3587 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3588 pBss->SsidLen = SsidLen;
3589 pBss->Hidden = 0;
3592 else
3593 pBss->SsidLen = 0;
3594 pBss->BssType = BssType;
3595 pBss->BeaconPeriod = BeaconPeriod;
3596 if (BssType == BSS_INFRA)
3598 if (pCfParm->bValid)
3600 pBss->CfpCount = pCfParm->CfpCount;
3601 pBss->CfpPeriod = pCfParm->CfpPeriod;
3602 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3603 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3606 else
3608 pBss->AtimWin = AtimWin;
3611 pBss->CapabilityInfo = CapabilityInfo;
3612 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3613 // Combine with AuthMode, they will decide the connection methods.
3614 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3615 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3616 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3617 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3618 else
3619 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3620 pBss->SupRateLen = SupRateLen;
3621 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3622 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3623 pBss->NewExtChanOffset = NewExtChanOffset;
3624 pBss->ExtRateLen = ExtRateLen;
3625 pBss->Channel = Channel;
3626 pBss->CentralChannel = Channel;
3627 pBss->Rssi = Rssi;
3628 // Update CkipFlag. if not exists, the value is 0x0
3629 pBss->CkipFlag = CkipFlag;
3631 // New for microsoft Fixed IEs
3632 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3633 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3634 pBss->FixIEs.Capabilities = CapabilityInfo;
3636 // New for microsoft Variable IEs
3637 if (LengthVIE != 0)
3639 pBss->VarIELen = LengthVIE;
3640 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3642 else
3644 pBss->VarIELen = 0;
3647 pBss->AddHtInfoLen = 0;
3648 pBss->HtCapabilityLen = 0;
3649 if (HtCapabilityLen> 0)
3651 pBss->HtCapabilityLen = HtCapabilityLen;
3652 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3653 if (AddHtInfoLen > 0)
3655 pBss->AddHtInfoLen = AddHtInfoLen;
3656 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3658 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3660 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3662 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3664 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3669 BssCipherParse(pBss);
3671 // new for QOS
3672 if (pEdcaParm)
3673 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3674 else
3675 pBss->EdcaParm.bValid = FALSE;
3676 if (pQosCapability)
3677 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3678 else
3679 pBss->QosCapability.bValid = FALSE;
3680 if (pQbssLoad)
3681 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3682 else
3683 pBss->QbssLoad.bValid = FALSE;
3686 PEID_STRUCT pEid;
3687 USHORT Length = 0;
3690 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3691 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3692 pEid = (PEID_STRUCT) pVIE;
3693 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3695 switch(pEid->Eid)
3697 case IE_WPA:
3698 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3700 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3702 pBss->WpaIE.IELen = 0;
3703 break;
3705 pBss->WpaIE.IELen = pEid->Len + 2;
3706 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3708 break;
3709 case IE_RSN:
3710 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3712 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3714 pBss->RsnIE.IELen = 0;
3715 break;
3717 pBss->RsnIE.IELen = pEid->Len + 2;
3718 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3720 break;
3722 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3723 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3729 * \brief insert an entry into the bss table
3730 * \param p_tab The BSS table
3731 * \param Bssid BSSID
3732 * \param ssid SSID
3733 * \param ssid_len Length of SSID
3734 * \param bss_type
3735 * \param beacon_period
3736 * \param timestamp
3737 * \param p_cf
3738 * \param atim_win
3739 * \param cap
3740 * \param rates
3741 * \param rates_len
3742 * \param channel_idx
3743 * \return none
3744 * \pre
3745 * \post
3746 * \note If SSID is identical, the old entry will be replaced by the new one
3748 IRQL = DISPATCH_LEVEL
3751 ULONG BssTableSetEntry(
3752 IN PRTMP_ADAPTER pAd,
3753 OUT BSS_TABLE *Tab,
3754 IN PUCHAR pBssid,
3755 IN CHAR Ssid[],
3756 IN UCHAR SsidLen,
3757 IN UCHAR BssType,
3758 IN USHORT BeaconPeriod,
3759 IN CF_PARM *CfParm,
3760 IN USHORT AtimWin,
3761 IN USHORT CapabilityInfo,
3762 IN UCHAR SupRate[],
3763 IN UCHAR SupRateLen,
3764 IN UCHAR ExtRate[],
3765 IN UCHAR ExtRateLen,
3766 IN HT_CAPABILITY_IE *pHtCapability,
3767 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3768 IN UCHAR HtCapabilityLen,
3769 IN UCHAR AddHtInfoLen,
3770 IN UCHAR NewExtChanOffset,
3771 IN UCHAR ChannelNo,
3772 IN CHAR Rssi,
3773 IN LARGE_INTEGER TimeStamp,
3774 IN UCHAR CkipFlag,
3775 IN PEDCA_PARM pEdcaParm,
3776 IN PQOS_CAPABILITY_PARM pQosCapability,
3777 IN PQBSS_LOAD_PARM pQbssLoad,
3778 IN USHORT LengthVIE,
3779 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3781 ULONG Idx;
3783 Idx = BssTableSearchWithSSID(Tab, pBssid, (UCHAR *)Ssid, SsidLen, ChannelNo);
3784 if (Idx == BSS_NOT_FOUND)
3786 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3789 // It may happen when BSS Table was full.
3790 // The desired AP will not be added into BSS Table
3791 // In this case, if we found the desired AP then overwrite BSS Table.
3793 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3795 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3796 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3798 Idx = Tab->BssOverlapNr;
3799 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3800 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3801 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3802 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3804 return Idx;
3806 else
3808 return BSS_NOT_FOUND;
3811 Idx = Tab->BssNr;
3812 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3813 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3814 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3815 Tab->BssNr++;
3817 else
3819 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3820 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3821 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3823 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3824 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3825 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3829 return Idx;
3833 // IRQL = DISPATCH_LEVEL
3834 VOID BssTableSsidSort(
3835 IN PRTMP_ADAPTER pAd,
3836 OUT BSS_TABLE *OutTab,
3837 IN CHAR Ssid[],
3838 IN UCHAR SsidLen)
3840 INT i;
3841 BssTableInit(OutTab);
3843 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3845 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3846 BOOLEAN bIsHiddenApIncluded = FALSE;
3848 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3849 (pAd->MlmeAux.Channel > 14) &&
3850 RadarChannelCheck(pAd, pInBss->Channel))
3853 if (pInBss->Hidden)
3854 bIsHiddenApIncluded = TRUE;
3857 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3858 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3860 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3864 // 2.4G/5G N only mode
3865 if ((pInBss->HtCapabilityLen == 0) &&
3866 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3868 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3869 continue;
3871 // New for WPA2
3872 // Check the Authmode first
3873 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3875 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3876 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3877 // None matched
3878 continue;
3880 // Check cipher suite, AP must have more secured cipher than station setting
3881 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3883 // If it's not mixed mode, we should only let BSS pass with the same encryption
3884 if (pInBss->WPA.bMixMode == FALSE)
3885 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3886 continue;
3888 // check group cipher
3889 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3890 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3891 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3892 continue;
3894 // check pairwise cipher, skip if none matched
3895 // If profile set to AES, let it pass without question.
3896 // If profile set to TKIP, we must find one mateched
3897 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3898 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3899 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3900 continue;
3902 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3904 // If it's not mixed mode, we should only let BSS pass with the same encryption
3905 if (pInBss->WPA2.bMixMode == FALSE)
3906 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3907 continue;
3909 // check group cipher
3910 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3911 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3912 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3913 continue;
3915 // check pairwise cipher, skip if none matched
3916 // If profile set to AES, let it pass without question.
3917 // If profile set to TKIP, we must find one mateched
3918 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3919 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3920 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3921 continue;
3924 // Bss Type matched, SSID matched.
3925 // We will check wepstatus for qualification Bss
3926 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3928 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3930 // For the SESv2 case, we will not qualify WepStatus.
3932 if (!pInBss->bSES)
3933 continue;
3936 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3937 // It definitely will fail. So, skip it.
3938 // CCX also require not even try to connect it!!
3939 if (SsidLen == 0)
3940 continue;
3942 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3943 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3944 if ((pInBss->CentralChannel != pInBss->Channel) &&
3945 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3947 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3949 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3950 SetCommonHT(pAd);
3951 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3953 else
3955 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3957 SetCommonHT(pAd);
3962 // copy matching BSS from InTab to OutTab
3963 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3965 OutTab->BssNr++;
3967 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3969 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3972 // 2.4G/5G N only mode
3973 if ((pInBss->HtCapabilityLen == 0) &&
3974 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3976 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3977 continue;
3980 // New for WPA2
3981 // Check the Authmode first
3982 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3984 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3985 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3986 // None matched
3987 continue;
3989 // Check cipher suite, AP must have more secured cipher than station setting
3990 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3992 // If it's not mixed mode, we should only let BSS pass with the same encryption
3993 if (pInBss->WPA.bMixMode == FALSE)
3994 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3995 continue;
3997 // check group cipher
3998 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3999 continue;
4001 // check pairwise cipher, skip if none matched
4002 // If profile set to AES, let it pass without question.
4003 // If profile set to TKIP, we must find one mateched
4004 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4005 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4006 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4007 continue;
4009 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4011 // If it's not mixed mode, we should only let BSS pass with the same encryption
4012 if (pInBss->WPA2.bMixMode == FALSE)
4013 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4014 continue;
4016 // check group cipher
4017 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4018 continue;
4020 // check pairwise cipher, skip if none matched
4021 // If profile set to AES, let it pass without question.
4022 // If profile set to TKIP, we must find one mateched
4023 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4024 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4025 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4026 continue;
4029 // Bss Type matched, SSID matched.
4030 // We will check wepstatus for qualification Bss
4031 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4032 continue;
4034 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4035 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4036 if ((pInBss->CentralChannel != pInBss->Channel) &&
4037 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4039 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4041 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4042 SetCommonHT(pAd);
4043 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4047 // copy matching BSS from InTab to OutTab
4048 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4050 OutTab->BssNr++;
4053 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4054 break;
4057 BssTableSortByRssi(OutTab);
4061 // IRQL = DISPATCH_LEVEL
4062 VOID BssTableSortByRssi(
4063 IN OUT BSS_TABLE *OutTab)
4065 INT i, j;
4066 BSS_ENTRY TmpBss;
4068 for (i = 0; i < OutTab->BssNr - 1; i++)
4070 for (j = i+1; j < OutTab->BssNr; j++)
4072 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4074 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4075 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4076 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4083 VOID BssCipherParse(
4084 IN OUT PBSS_ENTRY pBss)
4086 PEID_STRUCT pEid;
4087 PUCHAR pTmp;
4088 PRSN_IE_HEADER_STRUCT pRsnHeader;
4089 PCIPHER_SUITE_STRUCT pCipher;
4090 PAKM_SUITE_STRUCT pAKM;
4091 USHORT Count;
4092 INT Length;
4093 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4096 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4098 if (pBss->Privacy)
4100 pBss->WepStatus = Ndis802_11WEPEnabled;
4102 else
4104 pBss->WepStatus = Ndis802_11WEPDisabled;
4106 // Set default to disable & open authentication before parsing variable IE
4107 pBss->AuthMode = Ndis802_11AuthModeOpen;
4108 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4110 // Init WPA setting
4111 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4112 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4113 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4114 pBss->WPA.RsnCapability = 0;
4115 pBss->WPA.bMixMode = FALSE;
4117 // Init WPA2 setting
4118 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4119 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4120 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4121 pBss->WPA2.RsnCapability = 0;
4122 pBss->WPA2.bMixMode = FALSE;
4125 Length = (INT) pBss->VarIELen;
4127 while (Length > 0)
4129 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4130 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4131 pEid = (PEID_STRUCT) pTmp;
4132 switch (pEid->Eid)
4134 case IE_WPA:
4135 if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4137 pBss->bSES = TRUE;
4138 break;
4140 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4142 // if unsupported vendor specific IE
4143 break;
4145 // Skip OUI, version, and multicast suite
4146 // This part should be improved in the future when AP supported multiple cipher suite.
4147 // For now, it's OK since almost all APs have fixed cipher suite supported.
4148 // pTmp = (PUCHAR) pEid->Octet;
4149 pTmp += 11;
4151 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4152 // Value Meaning
4153 // 0 None
4154 // 1 WEP-40
4155 // 2 Tkip
4156 // 3 WRAP
4157 // 4 AES
4158 // 5 WEP-104
4159 // Parse group cipher
4160 switch (*pTmp)
4162 case 1:
4163 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4164 break;
4165 case 5:
4166 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4167 break;
4168 case 2:
4169 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4170 break;
4171 case 4:
4172 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4173 break;
4174 default:
4175 break;
4177 // number of unicast suite
4178 pTmp += 1;
4180 // skip all unicast cipher suites
4181 //Count = *(PUSHORT) pTmp;
4182 Count = (pTmp[1]<<8) + pTmp[0];
4183 pTmp += sizeof(USHORT);
4185 // Parsing all unicast cipher suite
4186 while (Count > 0)
4188 // Skip OUI
4189 pTmp += 3;
4190 TmpCipher = Ndis802_11WEPDisabled;
4191 switch (*pTmp)
4193 case 1:
4194 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4195 TmpCipher = Ndis802_11Encryption1Enabled;
4196 break;
4197 case 2:
4198 TmpCipher = Ndis802_11Encryption2Enabled;
4199 break;
4200 case 4:
4201 TmpCipher = Ndis802_11Encryption3Enabled;
4202 break;
4203 default:
4204 break;
4206 if (TmpCipher > pBss->WPA.PairCipher)
4208 // Move the lower cipher suite to PairCipherAux
4209 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4210 pBss->WPA.PairCipher = TmpCipher;
4212 else
4214 pBss->WPA.PairCipherAux = TmpCipher;
4216 pTmp++;
4217 Count--;
4220 // 4. get AKM suite counts
4221 //Count = *(PUSHORT) pTmp;
4222 Count = (pTmp[1]<<8) + pTmp[0];
4223 pTmp += sizeof(USHORT);
4224 pTmp += 3;
4226 switch (*pTmp)
4228 case 1:
4229 // Set AP support WPA-enterprise mode
4230 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4231 pBss->AuthMode = Ndis802_11AuthModeWPA;
4232 else
4233 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4234 break;
4235 case 2:
4236 // Set AP support WPA-PSK mode
4237 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4238 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4239 else
4240 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4241 break;
4242 default:
4243 break;
4245 pTmp += 1;
4247 // Fixed for WPA-None
4248 if (pBss->BssType == BSS_ADHOC)
4250 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4251 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4252 pBss->WepStatus = pBss->WPA.GroupCipher;
4253 // Patched bugs for old driver
4254 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4255 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4257 else
4258 pBss->WepStatus = pBss->WPA.PairCipher;
4260 // Check the Pair & Group, if different, turn on mixed mode flag
4261 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4262 pBss->WPA.bMixMode = TRUE;
4264 break;
4266 case IE_RSN:
4267 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4269 // 0. Version must be 1
4270 if (le2cpu16(pRsnHeader->Version) != 1)
4271 break;
4272 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4274 // 1. Check group cipher
4275 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4276 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4277 break;
4279 // Parse group cipher
4280 switch (pCipher->Type)
4282 case 1:
4283 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4284 break;
4285 case 5:
4286 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4287 break;
4288 case 2:
4289 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4290 break;
4291 case 4:
4292 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4293 break;
4294 default:
4295 break;
4297 // set to correct offset for next parsing
4298 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4300 // 2. Get pairwise cipher counts
4301 //Count = *(PUSHORT) pTmp;
4302 Count = (pTmp[1]<<8) + pTmp[0];
4303 pTmp += sizeof(USHORT);
4305 // 3. Get pairwise cipher
4306 // Parsing all unicast cipher suite
4307 while (Count > 0)
4309 // Skip OUI
4310 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4311 TmpCipher = Ndis802_11WEPDisabled;
4312 switch (pCipher->Type)
4314 case 1:
4315 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4316 TmpCipher = Ndis802_11Encryption1Enabled;
4317 break;
4318 case 2:
4319 TmpCipher = Ndis802_11Encryption2Enabled;
4320 break;
4321 case 4:
4322 TmpCipher = Ndis802_11Encryption3Enabled;
4323 break;
4324 default:
4325 break;
4327 if (TmpCipher > pBss->WPA2.PairCipher)
4329 // Move the lower cipher suite to PairCipherAux
4330 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4331 pBss->WPA2.PairCipher = TmpCipher;
4333 else
4335 pBss->WPA2.PairCipherAux = TmpCipher;
4337 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4338 Count--;
4341 // 4. get AKM suite counts
4342 //Count = *(PUSHORT) pTmp;
4343 Count = (pTmp[1]<<8) + pTmp[0];
4344 pTmp += sizeof(USHORT);
4346 // 5. Get AKM ciphers
4347 // Parsing all AKM ciphers
4348 while (Count > 0)
4350 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4351 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4352 break;
4354 switch (pAKM->Type)
4356 case 1:
4357 // Set AP support WPA-enterprise mode
4358 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4359 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4360 else
4361 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4362 break;
4363 case 2:
4364 // Set AP support WPA-PSK mode
4365 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4366 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4367 else
4368 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4369 break;
4370 default:
4371 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4372 pBss->AuthMode = Ndis802_11AuthModeMax;
4373 else
4374 pBss->AuthModeAux = Ndis802_11AuthModeMax;
4375 break;
4377 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4378 Count--;
4381 // Fixed for WPA-None
4382 if (pBss->BssType == BSS_ADHOC)
4384 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4385 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4386 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4387 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4388 pBss->WepStatus = pBss->WPA.GroupCipher;
4389 // Patched bugs for old driver
4390 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4391 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4393 pBss->WepStatus = pBss->WPA2.PairCipher;
4395 // 6. Get RSN capability
4396 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4397 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4398 pTmp += sizeof(USHORT);
4400 // Check the Pair & Group, if different, turn on mixed mode flag
4401 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4402 pBss->WPA2.bMixMode = TRUE;
4404 break;
4405 default:
4406 break;
4408 Length -= (pEid->Len + 2);
4412 // ===========================================================================================
4413 // mac_table.c
4414 // ===========================================================================================
4416 /*! \brief generates a random mac address value for IBSS BSSID
4417 * \param Addr the bssid location
4418 * \return none
4419 * \pre
4420 * \post
4422 VOID MacAddrRandomBssid(
4423 IN PRTMP_ADAPTER pAd,
4424 OUT PUCHAR pAddr)
4426 INT i;
4428 for (i = 0; i < MAC_ADDR_LEN; i++)
4430 pAddr[i] = RandomByte(pAd);
4433 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4436 /*! \brief init the management mac frame header
4437 * \param p_hdr mac header
4438 * \param subtype subtype of the frame
4439 * \param p_ds destination address, don't care if it is a broadcast address
4440 * \return none
4441 * \pre the station has the following information in the pAd->StaCfg
4442 * - bssid
4443 * - station address
4444 * \post
4445 * \note this function initializes the following field
4447 IRQL = PASSIVE_LEVEL
4448 IRQL = DISPATCH_LEVEL
4451 VOID MgtMacHeaderInit(
4452 IN PRTMP_ADAPTER pAd,
4453 IN OUT PHEADER_802_11 pHdr80211,
4454 IN UCHAR SubType,
4455 IN UCHAR ToDs,
4456 IN PUCHAR pDA,
4457 IN PUCHAR pBssid)
4459 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4461 pHdr80211->FC.Type = BTYPE_MGMT;
4462 pHdr80211->FC.SubType = SubType;
4463 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4464 // pHdr80211->FC.Type = BTYPE_CNTL;
4465 pHdr80211->FC.ToDs = ToDs;
4466 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4467 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4468 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4471 // ===========================================================================================
4472 // mem_mgmt.c
4473 // ===========================================================================================
4475 /*!***************************************************************************
4476 * This routine build an outgoing frame, and fill all information specified
4477 * in argument list to the frame body. The actual frame size is the summation
4478 * of all arguments.
4479 * input params:
4480 * Buffer - pointer to a pre-allocated memory segment
4481 * args - a list of <int arg_size, arg> pairs.
4482 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4483 * function will FAIL!!!
4484 * return:
4485 * Size of the buffer
4486 * usage:
4487 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4489 IRQL = PASSIVE_LEVEL
4490 IRQL = DISPATCH_LEVEL
4492 ****************************************************************************/
4493 ULONG MakeOutgoingFrame(
4494 OUT UCHAR *Buffer,
4495 OUT ULONG *FrameLen, ...)
4497 UCHAR *p;
4498 int leng;
4499 ULONG TotLeng;
4500 va_list Args;
4502 // calculates the total length
4503 TotLeng = 0;
4504 va_start(Args, FrameLen);
4507 leng = va_arg(Args, int);
4508 if (leng == END_OF_ARGS)
4510 break;
4512 p = va_arg(Args, PVOID);
4513 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4514 TotLeng = TotLeng + leng;
4515 } while(TRUE);
4517 va_end(Args); /* clean up */
4518 *FrameLen = TotLeng;
4519 return TotLeng;
4522 // ===========================================================================================
4523 // mlme_queue.c
4524 // ===========================================================================================
4526 /*! \brief Initialize The MLME Queue, used by MLME Functions
4527 * \param *Queue The MLME Queue
4528 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4529 * \pre
4530 * \post
4531 * \note Because this is done only once (at the init stage), no need to be locked
4533 IRQL = PASSIVE_LEVEL
4536 NDIS_STATUS MlmeQueueInit(
4537 IN MLME_QUEUE *Queue)
4539 INT i;
4541 NdisAllocateSpinLock(&Queue->Lock);
4543 Queue->Num = 0;
4544 Queue->Head = 0;
4545 Queue->Tail = 0;
4547 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4549 Queue->Entry[i].Occupied = FALSE;
4550 Queue->Entry[i].MsgLen = 0;
4551 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4554 return NDIS_STATUS_SUCCESS;
4557 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4558 * \param *Queue The MLME Queue
4559 * \param Machine The State Machine Id
4560 * \param MsgType The Message Type
4561 * \param MsgLen The Message length
4562 * \param *Msg The message pointer
4563 * \return TRUE if enqueue is successful, FALSE if the queue is full
4564 * \pre
4565 * \post
4566 * \note The message has to be initialized
4568 IRQL = PASSIVE_LEVEL
4569 IRQL = DISPATCH_LEVEL
4572 BOOLEAN MlmeEnqueue(
4573 IN PRTMP_ADAPTER pAd,
4574 IN ULONG Machine,
4575 IN ULONG MsgType,
4576 IN ULONG MsgLen,
4577 IN VOID *Msg)
4579 INT Tail;
4580 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4582 // Do nothing if the driver is starting halt state.
4583 // This might happen when timer already been fired before cancel timer with mlmehalt
4584 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4585 return FALSE;
4587 // First check the size, it MUST not exceed the mlme queue size
4588 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4590 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4591 return FALSE;
4594 if (MlmeQueueFull(Queue))
4596 return FALSE;
4599 NdisAcquireSpinLock(&(Queue->Lock));
4600 Tail = Queue->Tail;
4601 Queue->Tail++;
4602 Queue->Num++;
4603 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4605 Queue->Tail = 0;
4608 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4609 Queue->Entry[Tail].Occupied = TRUE;
4610 Queue->Entry[Tail].Machine = Machine;
4611 Queue->Entry[Tail].MsgType = MsgType;
4612 Queue->Entry[Tail].MsgLen = MsgLen;
4614 if (Msg != NULL)
4616 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4619 NdisReleaseSpinLock(&(Queue->Lock));
4620 return TRUE;
4623 /*! \brief This function is used when Recv gets a MLME message
4624 * \param *Queue The MLME Queue
4625 * \param TimeStampHigh The upper 32 bit of timestamp
4626 * \param TimeStampLow The lower 32 bit of timestamp
4627 * \param Rssi The receiving RSSI strength
4628 * \param MsgLen The length of the message
4629 * \param *Msg The message pointer
4630 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4631 * \pre
4632 * \post
4634 IRQL = DISPATCH_LEVEL
4637 BOOLEAN MlmeEnqueueForRecv(
4638 IN PRTMP_ADAPTER pAd,
4639 IN ULONG Wcid,
4640 IN ULONG TimeStampHigh,
4641 IN ULONG TimeStampLow,
4642 IN UCHAR Rssi0,
4643 IN UCHAR Rssi1,
4644 IN UCHAR Rssi2,
4645 IN ULONG MsgLen,
4646 IN VOID *Msg,
4647 IN UCHAR Signal)
4649 INT Tail, Machine;
4650 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4651 INT MsgType;
4652 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4655 // Do nothing if the driver is starting halt state.
4656 // This might happen when timer already been fired before cancel timer with mlmehalt
4657 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4659 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4660 return FALSE;
4663 // First check the size, it MUST not exceed the mlme queue size
4664 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4666 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4667 return FALSE;
4670 if (MlmeQueueFull(Queue))
4672 return FALSE;
4676 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4678 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4679 return FALSE;
4683 // OK, we got all the informations, it is time to put things into queue
4684 NdisAcquireSpinLock(&(Queue->Lock));
4685 Tail = Queue->Tail;
4686 Queue->Tail++;
4687 Queue->Num++;
4688 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4690 Queue->Tail = 0;
4692 Queue->Entry[Tail].Occupied = TRUE;
4693 Queue->Entry[Tail].Machine = Machine;
4694 Queue->Entry[Tail].MsgType = MsgType;
4695 Queue->Entry[Tail].MsgLen = MsgLen;
4696 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4697 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4698 Queue->Entry[Tail].Rssi0 = Rssi0;
4699 Queue->Entry[Tail].Rssi1 = Rssi1;
4700 Queue->Entry[Tail].Rssi2 = Rssi2;
4701 Queue->Entry[Tail].Signal = Signal;
4702 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4704 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4706 if (Msg != NULL)
4708 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4711 NdisReleaseSpinLock(&(Queue->Lock));
4713 RTMP_MLME_HANDLER(pAd);
4715 return TRUE;
4719 /*! \brief Dequeue a message from the MLME Queue
4720 * \param *Queue The MLME Queue
4721 * \param *Elem The message dequeued from MLME Queue
4722 * \return TRUE if the Elem contains something, FALSE otherwise
4723 * \pre
4724 * \post
4726 IRQL = DISPATCH_LEVEL
4729 BOOLEAN MlmeDequeue(
4730 IN MLME_QUEUE *Queue,
4731 OUT MLME_QUEUE_ELEM **Elem)
4733 NdisAcquireSpinLock(&(Queue->Lock));
4734 *Elem = &(Queue->Entry[Queue->Head]);
4735 Queue->Num--;
4736 Queue->Head++;
4737 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4739 Queue->Head = 0;
4741 NdisReleaseSpinLock(&(Queue->Lock));
4742 return TRUE;
4745 // IRQL = DISPATCH_LEVEL
4746 VOID MlmeRestartStateMachine(
4747 IN PRTMP_ADAPTER pAd)
4749 #ifdef RTMP_MAC_PCI
4750 MLME_QUEUE_ELEM *Elem = NULL;
4751 #endif // RTMP_MAC_PCI //
4752 BOOLEAN Cancelled;
4754 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4756 #ifdef RTMP_MAC_PCI
4757 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4758 if(pAd->Mlme.bRunning)
4760 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4761 return;
4763 else
4765 pAd->Mlme.bRunning = TRUE;
4767 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4769 // Remove all Mlme queues elements
4770 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4772 //From message type, determine which state machine I should drive
4773 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4775 // free MLME element
4776 Elem->Occupied = FALSE;
4777 Elem->MsgLen = 0;
4780 else {
4781 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4784 #endif // RTMP_MAC_PCI //
4787 // Cancel all timer events
4788 // Be careful to cancel new added timer
4789 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4790 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4791 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4792 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4793 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4794 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4798 // Change back to original channel in case of doing scan
4799 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4800 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4802 // Resume MSDU which is turned off durning scan
4803 RTMPResumeMsduTransmission(pAd);
4806 // Set all state machines back IDLE
4807 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4808 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4809 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4810 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4811 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4812 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4815 #ifdef RTMP_MAC_PCI
4816 // Remove running state
4817 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4818 pAd->Mlme.bRunning = FALSE;
4819 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4820 #endif // RTMP_MAC_PCI //
4823 /*! \brief test if the MLME Queue is empty
4824 * \param *Queue The MLME Queue
4825 * \return TRUE if the Queue is empty, FALSE otherwise
4826 * \pre
4827 * \post
4829 IRQL = DISPATCH_LEVEL
4832 BOOLEAN MlmeQueueEmpty(
4833 IN MLME_QUEUE *Queue)
4835 BOOLEAN Ans;
4837 NdisAcquireSpinLock(&(Queue->Lock));
4838 Ans = (Queue->Num == 0);
4839 NdisReleaseSpinLock(&(Queue->Lock));
4841 return Ans;
4844 /*! \brief test if the MLME Queue is full
4845 * \param *Queue The MLME Queue
4846 * \return TRUE if the Queue is empty, FALSE otherwise
4847 * \pre
4848 * \post
4850 IRQL = PASSIVE_LEVEL
4851 IRQL = DISPATCH_LEVEL
4854 BOOLEAN MlmeQueueFull(
4855 IN MLME_QUEUE *Queue)
4857 BOOLEAN Ans;
4859 NdisAcquireSpinLock(&(Queue->Lock));
4860 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4861 NdisReleaseSpinLock(&(Queue->Lock));
4863 return Ans;
4866 /*! \brief The destructor of MLME Queue
4867 * \param
4868 * \return
4869 * \pre
4870 * \post
4871 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4873 IRQL = PASSIVE_LEVEL
4876 VOID MlmeQueueDestroy(
4877 IN MLME_QUEUE *pQueue)
4879 NdisAcquireSpinLock(&(pQueue->Lock));
4880 pQueue->Num = 0;
4881 pQueue->Head = 0;
4882 pQueue->Tail = 0;
4883 NdisReleaseSpinLock(&(pQueue->Lock));
4884 NdisFreeSpinLock(&(pQueue->Lock));
4888 /*! \brief To substitute the message type if the message is coming from external
4889 * \param pFrame The frame received
4890 * \param *Machine The state machine
4891 * \param *MsgType the message type for the state machine
4892 * \return TRUE if the substitution is successful, FALSE otherwise
4893 * \pre
4894 * \post
4896 IRQL = DISPATCH_LEVEL
4899 BOOLEAN MsgTypeSubst(
4900 IN PRTMP_ADAPTER pAd,
4901 IN PFRAME_802_11 pFrame,
4902 OUT INT *Machine,
4903 OUT INT *MsgType)
4905 USHORT Seq, Alg;
4906 UCHAR EAPType;
4907 PUCHAR pData;
4909 // Pointer to start of data frames including SNAP header
4910 pData = (PUCHAR) pFrame + LENGTH_802_11;
4912 // The only data type will pass to this function is EAPOL frame
4913 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4916 *Machine = WPA_STATE_MACHINE;
4917 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4918 return (WpaMsgTypeSubst(EAPType, (INT *) MsgType));
4922 switch (pFrame->Hdr.FC.SubType)
4924 case SUBTYPE_ASSOC_REQ:
4925 *Machine = ASSOC_STATE_MACHINE;
4926 *MsgType = MT2_PEER_ASSOC_REQ;
4927 break;
4928 case SUBTYPE_ASSOC_RSP:
4929 *Machine = ASSOC_STATE_MACHINE;
4930 *MsgType = MT2_PEER_ASSOC_RSP;
4931 break;
4932 case SUBTYPE_REASSOC_REQ:
4933 *Machine = ASSOC_STATE_MACHINE;
4934 *MsgType = MT2_PEER_REASSOC_REQ;
4935 break;
4936 case SUBTYPE_REASSOC_RSP:
4937 *Machine = ASSOC_STATE_MACHINE;
4938 *MsgType = MT2_PEER_REASSOC_RSP;
4939 break;
4940 case SUBTYPE_PROBE_REQ:
4941 *Machine = SYNC_STATE_MACHINE;
4942 *MsgType = MT2_PEER_PROBE_REQ;
4943 break;
4944 case SUBTYPE_PROBE_RSP:
4945 *Machine = SYNC_STATE_MACHINE;
4946 *MsgType = MT2_PEER_PROBE_RSP;
4947 break;
4948 case SUBTYPE_BEACON:
4949 *Machine = SYNC_STATE_MACHINE;
4950 *MsgType = MT2_PEER_BEACON;
4951 break;
4952 case SUBTYPE_ATIM:
4953 *Machine = SYNC_STATE_MACHINE;
4954 *MsgType = MT2_PEER_ATIM;
4955 break;
4956 case SUBTYPE_DISASSOC:
4957 *Machine = ASSOC_STATE_MACHINE;
4958 *MsgType = MT2_PEER_DISASSOC_REQ;
4959 break;
4960 case SUBTYPE_AUTH:
4961 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4962 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4963 NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT));
4964 if (Seq == 1 || Seq == 3)
4966 *Machine = AUTH_RSP_STATE_MACHINE;
4967 *MsgType = MT2_PEER_AUTH_ODD;
4969 else if (Seq == 2 || Seq == 4)
4971 if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY)
4973 *Machine = AUTH_STATE_MACHINE;
4974 *MsgType = MT2_PEER_AUTH_EVEN;
4977 else
4979 return FALSE;
4981 break;
4982 case SUBTYPE_DEAUTH:
4983 *Machine = AUTH_RSP_STATE_MACHINE;
4984 *MsgType = MT2_PEER_DEAUTH;
4985 break;
4986 case SUBTYPE_ACTION:
4987 *Machine = ACTION_STATE_MACHINE;
4988 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4989 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4991 *MsgType = MT2_ACT_INVALID;
4993 else
4995 *MsgType = (pFrame->Octet[0]&0x7F);
4997 break;
4998 default:
4999 return FALSE;
5000 break;
5003 return TRUE;
5006 // ===========================================================================================
5007 // state_machine.c
5008 // ===========================================================================================
5010 /*! \brief Initialize the state machine.
5011 * \param *S pointer to the state machine
5012 * \param Trans State machine transition function
5013 * \param StNr number of states
5014 * \param MsgNr number of messages
5015 * \param DefFunc default function, when there is invalid state/message combination
5016 * \param InitState initial state of the state machine
5017 * \param Base StateMachine base, internal use only
5018 * \pre p_sm should be a legal pointer
5019 * \post
5021 IRQL = PASSIVE_LEVEL
5024 VOID StateMachineInit(
5025 IN STATE_MACHINE *S,
5026 IN STATE_MACHINE_FUNC Trans[],
5027 IN ULONG StNr,
5028 IN ULONG MsgNr,
5029 IN STATE_MACHINE_FUNC DefFunc,
5030 IN ULONG InitState,
5031 IN ULONG Base)
5033 ULONG i, j;
5035 // set number of states and messages
5036 S->NrState = StNr;
5037 S->NrMsg = MsgNr;
5038 S->Base = Base;
5040 S->TransFunc = Trans;
5042 // init all state transition to default function
5043 for (i = 0; i < StNr; i++)
5045 for (j = 0; j < MsgNr; j++)
5047 S->TransFunc[i * MsgNr + j] = DefFunc;
5051 // set the starting state
5052 S->CurrState = InitState;
5055 /*! \brief This function fills in the function pointer into the cell in the state machine
5056 * \param *S pointer to the state machine
5057 * \param St state
5058 * \param Msg incoming message
5059 * \param f the function to be executed when (state, message) combination occurs at the state machine
5060 * \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
5061 * \post
5063 IRQL = PASSIVE_LEVEL
5066 VOID StateMachineSetAction(
5067 IN STATE_MACHINE *S,
5068 IN ULONG St,
5069 IN ULONG Msg,
5070 IN STATE_MACHINE_FUNC Func)
5072 ULONG MsgIdx;
5074 MsgIdx = Msg - S->Base;
5076 if (St < S->NrState && MsgIdx < S->NrMsg)
5078 // boundary checking before setting the action
5079 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5083 /*! \brief This function does the state transition
5084 * \param *Adapter the NIC adapter pointer
5085 * \param *S the state machine
5086 * \param *Elem the message to be executed
5087 * \return None
5089 IRQL = DISPATCH_LEVEL
5092 VOID StateMachinePerformAction(
5093 IN PRTMP_ADAPTER pAd,
5094 IN STATE_MACHINE *S,
5095 IN MLME_QUEUE_ELEM *Elem)
5097 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5101 ==========================================================================
5102 Description:
5103 The drop function, when machine executes this, the message is simply
5104 ignored. This function does nothing, the message is freed in
5105 StateMachinePerformAction()
5106 ==========================================================================
5108 VOID Drop(
5109 IN PRTMP_ADAPTER pAd,
5110 IN MLME_QUEUE_ELEM *Elem)
5114 // ===========================================================================================
5115 // lfsr.c
5116 // ===========================================================================================
5119 ==========================================================================
5120 Description:
5122 IRQL = PASSIVE_LEVEL
5124 ==========================================================================
5126 VOID LfsrInit(
5127 IN PRTMP_ADAPTER pAd,
5128 IN ULONG Seed)
5130 if (Seed == 0)
5131 pAd->Mlme.ShiftReg = 1;
5132 else
5133 pAd->Mlme.ShiftReg = Seed;
5137 ==========================================================================
5138 Description:
5139 ==========================================================================
5141 UCHAR RandomByte(
5142 IN PRTMP_ADAPTER pAd)
5144 ULONG i;
5145 UCHAR R, Result;
5147 R = 0;
5149 if (pAd->Mlme.ShiftReg == 0)
5150 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5152 for (i = 0; i < 8; i++)
5154 if (pAd->Mlme.ShiftReg & 0x00000001)
5156 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5157 Result = 1;
5159 else
5161 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5162 Result = 0;
5164 R = (R << 1) | Result;
5167 return R;
5172 ========================================================================
5174 Routine Description:
5175 Verify the support rate for different PHY type
5177 Arguments:
5178 pAd Pointer to our adapter
5180 Return Value:
5181 None
5183 IRQL = PASSIVE_LEVEL
5185 ========================================================================
5187 VOID RTMPCheckRates(
5188 IN PRTMP_ADAPTER pAd,
5189 IN OUT UCHAR SupRate[],
5190 IN OUT UCHAR *SupRateLen)
5192 UCHAR RateIdx, i, j;
5193 UCHAR NewRate[12], NewRateLen;
5195 NewRateLen = 0;
5197 if (pAd->CommonCfg.PhyMode == PHY_11B)
5198 RateIdx = 4;
5199 else
5200 RateIdx = 12;
5202 // Check for support rates exclude basic rate bit
5203 for (i = 0; i < *SupRateLen; i++)
5204 for (j = 0; j < RateIdx; j++)
5205 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5206 NewRate[NewRateLen++] = SupRate[i];
5208 *SupRateLen = NewRateLen;
5209 NdisMoveMemory(SupRate, NewRate, NewRateLen);
5212 BOOLEAN RTMPCheckChannel(
5213 IN PRTMP_ADAPTER pAd,
5214 IN UCHAR CentralChannel,
5215 IN UCHAR Channel)
5217 UCHAR k;
5218 UCHAR UpperChannel = 0, LowerChannel = 0;
5219 UCHAR NoEffectChannelinList = 0;
5221 // Find upper and lower channel according to 40MHz current operation.
5222 if (CentralChannel < Channel)
5224 UpperChannel = Channel;
5225 if (CentralChannel > 2)
5226 LowerChannel = CentralChannel - 2;
5227 else
5228 return FALSE;
5230 else if (CentralChannel > Channel)
5232 UpperChannel = CentralChannel + 2;
5233 LowerChannel = Channel;
5236 for (k = 0;k < pAd->ChannelListNum;k++)
5238 if (pAd->ChannelList[k].Channel == UpperChannel)
5240 NoEffectChannelinList ++;
5242 if (pAd->ChannelList[k].Channel == LowerChannel)
5244 NoEffectChannelinList ++;
5248 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
5249 if (NoEffectChannelinList == 2)
5250 return TRUE;
5251 else
5252 return FALSE;
5256 ========================================================================
5258 Routine Description:
5259 Verify the support rate for HT phy type
5261 Arguments:
5262 pAd Pointer to our adapter
5264 Return Value:
5265 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
5267 IRQL = PASSIVE_LEVEL
5269 ========================================================================
5271 BOOLEAN RTMPCheckHt(
5272 IN PRTMP_ADAPTER pAd,
5273 IN UCHAR Wcid,
5274 IN HT_CAPABILITY_IE *pHtCapability,
5275 IN ADD_HT_INFO_IE *pAddHtInfo)
5277 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5278 return FALSE;
5280 // If use AMSDU, set flag.
5281 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
5282 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
5283 // Save Peer Capability
5284 if (pHtCapability->HtCapInfo.ShortGIfor20)
5285 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
5286 if (pHtCapability->HtCapInfo.ShortGIfor40)
5287 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
5288 if (pHtCapability->HtCapInfo.TxSTBC)
5289 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
5290 if (pHtCapability->HtCapInfo.RxSTBC)
5291 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
5292 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
5294 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
5297 if (Wcid < MAX_LEN_OF_MAC_TABLE)
5299 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
5302 // Will check ChannelWidth for MCSSet[4] below
5303 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
5304 switch (pAd->CommonCfg.RxStream)
5306 case 1:
5307 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5308 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5309 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5310 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5311 break;
5312 case 2:
5313 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5314 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5315 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5316 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5317 break;
5318 case 3:
5319 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5320 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5321 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5322 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5323 break;
5326 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
5328 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5329 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5330 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
5332 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
5334 // Send Assoc Req with my HT capability.
5335 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5336 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
5337 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
5338 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
5339 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
5340 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
5341 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5342 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5343 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
5344 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
5345 if (pAd->CommonCfg.bRdg)
5347 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
5348 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5351 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
5352 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
5354 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5355 return TRUE;
5359 ========================================================================
5361 Routine Description:
5362 Verify the support rate for different PHY type
5364 Arguments:
5365 pAd Pointer to our adapter
5367 Return Value:
5368 None
5370 IRQL = PASSIVE_LEVEL
5372 ========================================================================
5374 VOID RTMPUpdateMlmeRate(
5375 IN PRTMP_ADAPTER pAd)
5377 UCHAR MinimumRate;
5378 UCHAR ProperMlmeRate; //= RATE_54;
5379 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
5380 BOOLEAN bMatch = FALSE;
5382 switch (pAd->CommonCfg.PhyMode)
5384 case PHY_11B:
5385 ProperMlmeRate = RATE_11;
5386 MinimumRate = RATE_1;
5387 break;
5388 case PHY_11BG_MIXED:
5389 case PHY_11ABGN_MIXED:
5390 case PHY_11BGN_MIXED:
5391 if ((pAd->MlmeAux.SupRateLen == 4) &&
5392 (pAd->MlmeAux.ExtRateLen == 0))
5393 // B only AP
5394 ProperMlmeRate = RATE_11;
5395 else
5396 ProperMlmeRate = RATE_24;
5398 if (pAd->MlmeAux.Channel <= 14)
5399 MinimumRate = RATE_1;
5400 else
5401 MinimumRate = RATE_6;
5402 break;
5403 case PHY_11A:
5404 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
5405 case PHY_11GN_MIXED:
5406 case PHY_11AGN_MIXED:
5407 case PHY_11AN_MIXED:
5408 case PHY_11N_5G:
5409 ProperMlmeRate = RATE_24;
5410 MinimumRate = RATE_6;
5411 break;
5412 case PHY_11ABG_MIXED:
5413 ProperMlmeRate = RATE_24;
5414 if (pAd->MlmeAux.Channel <= 14)
5415 MinimumRate = RATE_1;
5416 else
5417 MinimumRate = RATE_6;
5418 break;
5419 default: // error
5420 ProperMlmeRate = RATE_1;
5421 MinimumRate = RATE_1;
5422 break;
5425 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
5427 for (j = 0; j < RateIdx; j++)
5429 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5431 if (j == ProperMlmeRate)
5433 bMatch = TRUE;
5434 break;
5439 if (bMatch)
5440 break;
5443 if (bMatch == FALSE)
5445 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
5447 for (j = 0; j < RateIdx; j++)
5449 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
5451 if (j == ProperMlmeRate)
5453 bMatch = TRUE;
5454 break;
5459 if (bMatch)
5460 break;
5464 if (bMatch == FALSE)
5466 ProperMlmeRate = MinimumRate;
5469 pAd->CommonCfg.MlmeRate = MinimumRate;
5470 pAd->CommonCfg.RtsRate = ProperMlmeRate;
5471 if (pAd->CommonCfg.MlmeRate >= RATE_6)
5473 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
5474 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5475 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
5476 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5478 else
5480 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5481 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
5482 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
5483 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
5486 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
5489 CHAR RTMPMaxRssi(
5490 IN PRTMP_ADAPTER pAd,
5491 IN CHAR Rssi0,
5492 IN CHAR Rssi1,
5493 IN CHAR Rssi2)
5495 CHAR larger = -127;
5497 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
5499 larger = Rssi0;
5502 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
5504 larger = max(Rssi0, Rssi1);
5507 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
5509 larger = max(larger, Rssi2);
5512 if (larger == -127)
5513 larger = 0;
5515 return larger;
5520 ========================================================================
5521 Routine Description:
5522 Periodic evaluate antenna link status
5524 Arguments:
5525 pAd - Adapter pointer
5527 Return Value:
5528 None
5530 ========================================================================
5532 VOID AsicEvaluateRxAnt(
5533 IN PRTMP_ADAPTER pAd)
5535 UCHAR BBPR3 = 0;
5537 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5538 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5539 fRTMP_ADAPTER_RADIO_OFF |
5540 fRTMP_ADAPTER_NIC_NOT_EXIST |
5541 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5542 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5543 #ifdef RT30xx
5544 || (pAd->EepromAccess)
5545 #endif // RT30xx //
5546 #ifdef RT3090
5547 || (pAd->bPCIclkOff == TRUE)
5548 #endif // RT3090 //
5550 return;
5554 //if (pAd->StaCfg.Psm == PWR_SAVE)
5555 // return;
5559 if (pAd->StaCfg.Psm == PWR_SAVE)
5560 return;
5562 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5563 BBPR3 &= (~0x18);
5564 if(pAd->Antenna.field.RxPath == 3)
5566 BBPR3 |= (0x10);
5568 else if(pAd->Antenna.field.RxPath == 2)
5570 BBPR3 |= (0x8);
5572 else if(pAd->Antenna.field.RxPath == 1)
5574 BBPR3 |= (0x0);
5576 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5577 #ifdef RTMP_MAC_PCI
5578 pAd->StaCfg.BBPR3 = BBPR3;
5579 #endif // RTMP_MAC_PCI //
5580 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5583 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5584 pAd->RalinkCounters.OneSecTxRetryOkCount +
5585 pAd->RalinkCounters.OneSecTxFailCount;
5587 // dynamic adjust antenna evaluation period according to the traffic
5588 if (TxTotalCnt > 50)
5590 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
5591 pAd->Mlme.bLowThroughput = FALSE;
5593 else
5595 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
5596 pAd->Mlme.bLowThroughput = TRUE;
5607 ========================================================================
5608 Routine Description:
5609 After evaluation, check antenna link status
5611 Arguments:
5612 pAd - Adapter pointer
5614 Return Value:
5615 None
5617 ========================================================================
5619 VOID AsicRxAntEvalTimeout(
5620 IN PVOID SystemSpecific1,
5621 IN PVOID FunctionContext,
5622 IN PVOID SystemSpecific2,
5623 IN PVOID SystemSpecific3)
5625 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
5626 UCHAR BBPR3 = 0;
5627 CHAR larger = -127, rssi0, rssi1, rssi2;
5629 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5630 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5631 fRTMP_ADAPTER_RADIO_OFF |
5632 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5633 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5634 #ifdef RT30xx
5635 || (pAd->EepromAccess)
5636 #endif // RT30xx //
5637 #ifdef RT3090
5638 || (pAd->bPCIclkOff == TRUE)
5639 #endif // RT3090 //
5641 return;
5644 //if (pAd->StaCfg.Psm == PWR_SAVE)
5645 // return;
5647 if (pAd->StaCfg.Psm == PWR_SAVE)
5648 return;
5650 // if the traffic is low, use average rssi as the criteria
5651 if (pAd->Mlme.bLowThroughput == TRUE)
5653 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5654 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5655 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
5657 else
5659 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5660 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5661 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5664 if(pAd->Antenna.field.RxPath == 3)
5666 larger = max(rssi0, rssi1);
5668 if (larger > (rssi2 + 20))
5669 pAd->Mlme.RealRxPath = 2;
5670 else
5671 pAd->Mlme.RealRxPath = 3;
5673 else if(pAd->Antenna.field.RxPath == 2)
5675 if (rssi0 > (rssi1 + 20))
5676 pAd->Mlme.RealRxPath = 1;
5677 else
5678 pAd->Mlme.RealRxPath = 2;
5681 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5682 BBPR3 &= (~0x18);
5683 if(pAd->Mlme.RealRxPath == 3)
5685 BBPR3 |= (0x10);
5687 else if(pAd->Mlme.RealRxPath == 2)
5689 BBPR3 |= (0x8);
5691 else if(pAd->Mlme.RealRxPath == 1)
5693 BBPR3 |= (0x0);
5695 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5696 #ifdef RTMP_MAC_PCI
5697 pAd->StaCfg.BBPR3 = BBPR3;
5698 #endif // RTMP_MAC_PCI //
5706 VOID APSDPeriodicExec(
5707 IN PVOID SystemSpecific1,
5708 IN PVOID FunctionContext,
5709 IN PVOID SystemSpecific2,
5710 IN PVOID SystemSpecific3)
5712 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
5714 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5715 return;
5717 pAd->CommonCfg.TriggerTimerCount++;
5719 // Driver should not send trigger frame, it should be send by application layer
5721 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5722 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5723 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5725 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5726 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5727 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5728 pAd->CommonCfg.TriggerTimerCount = 0;
5729 pAd->CommonCfg.bInServicePeriod = TRUE;
5734 ========================================================================
5735 Routine Description:
5736 Set/reset MAC registers according to bPiggyBack parameter
5738 Arguments:
5739 pAd - Adapter pointer
5740 bPiggyBack - Enable / Disable Piggy-Back
5742 Return Value:
5743 None
5745 ========================================================================
5747 VOID RTMPSetPiggyBack(
5748 IN PRTMP_ADAPTER pAd,
5749 IN BOOLEAN bPiggyBack)
5751 TX_LINK_CFG_STRUC TxLinkCfg;
5753 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5755 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5756 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5760 ========================================================================
5761 Routine Description:
5762 check if this entry need to switch rate automatically
5764 Arguments:
5766 pEntry
5768 Return Value:
5769 TURE
5770 FALSE
5772 ========================================================================
5774 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
5775 IN PRTMP_ADAPTER pAd,
5776 IN PMAC_TABLE_ENTRY pEntry)
5778 BOOLEAN result = TRUE;
5781 // only associated STA counts
5782 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
5784 result = pAd->StaCfg.bAutoTxRateSwitch;
5786 else
5787 result = FALSE;
5790 return result;
5794 BOOLEAN RTMPAutoRateSwitchCheck(
5795 IN PRTMP_ADAPTER pAd)
5798 if (pAd->StaCfg.bAutoTxRateSwitch)
5799 return TRUE;
5801 return FALSE;
5806 ========================================================================
5807 Routine Description:
5808 check if this entry need to fix tx legacy rate
5810 Arguments:
5812 pEntry
5814 Return Value:
5815 TURE
5816 FALSE
5818 ========================================================================
5820 UCHAR RTMPStaFixedTxMode(
5821 IN PRTMP_ADAPTER pAd,
5822 IN PMAC_TABLE_ENTRY pEntry)
5824 UCHAR tx_mode = FIXED_TXMODE_HT;
5827 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
5830 return tx_mode;
5834 ========================================================================
5835 Routine Description:
5836 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5838 Arguments:
5840 pEntry
5842 Return Value:
5843 TURE
5844 FALSE
5846 ========================================================================
5848 VOID RTMPUpdateLegacyTxSetting(
5849 UCHAR fixed_tx_mode,
5850 PMAC_TABLE_ENTRY pEntry)
5852 HTTRANSMIT_SETTING TransmitSetting;
5854 if (fixed_tx_mode == FIXED_TXMODE_HT)
5855 return;
5857 TransmitSetting.word = 0;
5859 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5860 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5862 if (fixed_tx_mode == FIXED_TXMODE_CCK)
5864 TransmitSetting.field.MODE = MODE_CCK;
5865 // CCK mode allow MCS 0~3
5866 if (TransmitSetting.field.MCS > MCS_3)
5867 TransmitSetting.field.MCS = MCS_3;
5869 else
5871 TransmitSetting.field.MODE = MODE_OFDM;
5872 // OFDM mode allow MCS 0~7
5873 if (TransmitSetting.field.MCS > MCS_7)
5874 TransmitSetting.field.MCS = MCS_7;
5877 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
5879 pEntry->HTPhyMode.word = TransmitSetting.word;
5880 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5881 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
5886 ==========================================================================
5887 Description:
5888 dynamic tune BBP R66 to find a balance between sensibility and
5889 noise isolation
5891 IRQL = DISPATCH_LEVEL
5893 ==========================================================================
5895 VOID AsicStaBbpTuning(
5896 IN PRTMP_ADAPTER pAd)
5898 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
5899 CHAR Rssi;
5901 // 2860C did not support Fase CCA, therefore can't tune
5902 if (pAd->MACVersion == 0x28600100)
5903 return;
5906 // work as a STA
5908 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
5909 return;
5911 if ((pAd->OpMode == OPMODE_STA)
5912 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5914 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
5915 #ifdef RTMP_MAC_PCI
5916 && (pAd->bPCIclkOff == FALSE)
5917 #endif // RTMP_MAC_PCI //
5920 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5921 R66 = OrigR66Value;
5923 if (pAd->Antenna.field.RxPath > 1)
5924 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
5925 else
5926 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5928 if (pAd->LatchRfRegs.Channel <= 14)
5929 { //BG band
5930 #ifdef RT30xx
5931 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
5932 // Otherwise, it will have some throughput side effect when low RSSI
5934 if (IS_RT3070(pAd)||IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
5936 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
5938 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
5939 if (OrigR66Value != R66)
5941 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
5944 else
5946 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
5947 if (OrigR66Value != R66)
5949 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
5953 else
5954 #endif // RT30xx //
5956 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
5958 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
5959 if (OrigR66Value != R66)
5961 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
5964 else
5966 R66 = 0x2E + GET_LNA_GAIN(pAd);
5967 if (OrigR66Value != R66)
5969 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
5974 else
5975 { //A band
5976 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
5978 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
5980 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
5981 if (OrigR66Value != R66)
5983 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
5986 else
5988 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
5989 if (OrigR66Value != R66)
5991 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
5995 else
5997 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
5999 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
6000 if (OrigR66Value != R66)
6002 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6005 else
6007 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
6008 if (OrigR66Value != R66)
6010 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6020 VOID RTMPSetAGCInitValue(
6021 IN PRTMP_ADAPTER pAd,
6022 IN UCHAR BandWidth)
6024 UCHAR R66 = 0x30;
6026 if (pAd->LatchRfRegs.Channel <= 14)
6027 { // BG band
6028 #ifdef RT30xx
6029 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6031 if (IS_RT3070(pAd)||IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
6033 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
6034 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6036 else
6037 #endif // RT30xx //
6039 R66 = 0x2E + GET_LNA_GAIN(pAd);
6040 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6043 else
6044 { //A band
6046 if (BandWidth == BW_20)
6048 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
6049 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6051 else
6053 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
6054 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);