2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 u8 CISCO_OUI
[] = { 0x00, 0x40, 0x96 };
44 u8 WPA_OUI
[] = { 0x00, 0x50, 0xf2, 0x01 };
45 u8 RSN_OUI
[] = { 0x00, 0x0f, 0xac };
46 u8 WME_INFO_ELEM
[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
47 u8 WME_PARM_ELEM
[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
48 u8 Ccx2QosInfo
[] = { 0x00, 0x40, 0x96, 0x04 };
49 u8 RALINK_OUI
[] = { 0x00, 0x0c, 0x43 };
50 u8 BROADCOM_OUI
[] = { 0x00, 0x90, 0x4c };
51 u8 WPS_OUI
[] = { 0x00, 0x50, 0xf2, 0x04 };
52 u8 PRE_N_HT_OUI
[] = { 0x00, 0x90, 0x4c };
54 u8 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,
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,
91 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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 u8 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,
296 extern u8 OfdmRateToRxwiMCS
[];
297 /* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */
298 /* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */
299 unsigned long BasicRateMask
[12] =
300 { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ ,
301 0xfffff00f /* 11 */ ,
302 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ ,
303 0xfffff0ff /* 18 */ ,
304 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ ,
308 u8 BROADCAST_ADDR
[MAC_ADDR_LEN
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
309 u8 ZERO_MAC_ADDR
[MAC_ADDR_LEN
] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
311 /* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */
312 /* this value, then it's quaranteed capable of operating in 36 mbps TX rate in */
313 /* clean environment. */
314 /* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 */
315 char RssiSafeLevelForTxRate
[] =
316 { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
318 u8 RateIdToMbps
[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
319 u16 RateIdTo500Kbps
[] =
320 { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
323 u8 SupRateIe
= IE_SUPP_RATES
;
324 u8 ExtRateIe
= IE_EXT_SUPP_RATES
;
325 u8 HtCapIe
= IE_HT_CAP
;
326 u8 AddHtInfoIe
= IE_ADD_HT
;
327 u8 NewExtChanIe
= IE_SECONDARY_CH_OFFSET
;
329 u8 DsIe
= IE_DS_PARM
;
333 u8 IbssIe
= IE_IBSS_PARM
;
337 u8 SES_OUI
[] = { 0x00, 0x90, 0x4c };
340 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00
347 ==========================================================================
349 initialize the MLME task and its data structure (queue, spinlock,
350 timer, state machines).
355 always return NDIS_STATUS_SUCCESS
357 ==========================================================================
359 int MlmeInit(struct rt_rtmp_adapter
*pAd
)
361 int Status
= NDIS_STATUS_SUCCESS
;
363 DBGPRINT(RT_DEBUG_TRACE
, ("--> MLME Initialize\n"));
366 Status
= MlmeQueueInit(&pAd
->Mlme
.Queue
);
367 if (Status
!= NDIS_STATUS_SUCCESS
)
370 pAd
->Mlme
.bRunning
= FALSE
;
371 NdisAllocateSpinLock(&pAd
->Mlme
.TaskLock
);
374 BssTableInit(&pAd
->ScanTab
);
376 /* init STA state machines */
377 AssocStateMachineInit(pAd
, &pAd
->Mlme
.AssocMachine
,
378 pAd
->Mlme
.AssocFunc
);
379 AuthStateMachineInit(pAd
, &pAd
->Mlme
.AuthMachine
,
381 AuthRspStateMachineInit(pAd
, &pAd
->Mlme
.AuthRspMachine
,
382 pAd
->Mlme
.AuthRspFunc
);
383 SyncStateMachineInit(pAd
, &pAd
->Mlme
.SyncMachine
,
386 /* Since we are using switch/case to implement it, the init is different from the above */
387 /* state machine init */
388 MlmeCntlInit(pAd
, &pAd
->Mlme
.CntlMachine
, NULL
);
391 WpaStateMachineInit(pAd
, &pAd
->Mlme
.WpaMachine
,
394 ActionStateMachineInit(pAd
, &pAd
->Mlme
.ActMachine
,
397 /* Init mlme periodic timer */
398 RTMPInitTimer(pAd
, &pAd
->Mlme
.PeriodicTimer
,
399 GET_TIMER_FUNCTION(MlmePeriodicExec
), pAd
, TRUE
);
401 /* Set mlme periodic timer */
402 RTMPSetTimer(&pAd
->Mlme
.PeriodicTimer
, MLME_TASK_EXEC_INTV
);
404 /* software-based RX Antenna diversity */
405 RTMPInitTimer(pAd
, &pAd
->Mlme
.RxAntEvalTimer
,
406 GET_TIMER_FUNCTION(AsicRxAntEvalTimeout
), pAd
,
410 #ifdef RTMP_PCI_SUPPORT
411 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
)) {
412 /* only PCIe cards need these two timers */
413 RTMPInitTimer(pAd
, &pAd
->Mlme
.PsPollTimer
,
415 (PsPollWakeExec
), pAd
, FALSE
);
416 RTMPInitTimer(pAd
, &pAd
->Mlme
.RadioOnOffTimer
,
417 GET_TIMER_FUNCTION(RadioOnExec
),
420 #endif /* RTMP_PCI_SUPPORT // */
422 RTMPInitTimer(pAd
, &pAd
->Mlme
.LinkDownTimer
,
423 GET_TIMER_FUNCTION(LinkDownExec
), pAd
,
427 RTMPInitTimer(pAd
, &pAd
->Mlme
.AutoWakeupTimer
,
429 (RtmpUsbStaAsicForceWakeupTimeout
), pAd
,
431 pAd
->Mlme
.AutoWakeupTimerRunning
= FALSE
;
432 #endif /* RTMP_MAC_USB // */
437 DBGPRINT(RT_DEBUG_TRACE
, ("<-- MLME Initialize\n"));
443 ==========================================================================
445 main loop of the MLME
447 Mlme has to be initialized, and there are something inside the queue
449 This function is invoked from MPSetInformation and MPReceive;
450 This task guarantee only one MlmeHandler will run.
452 IRQL = DISPATCH_LEVEL
454 ==========================================================================
456 void MlmeHandler(struct rt_rtmp_adapter
*pAd
)
458 struct rt_mlme_queue_elem
*Elem
= NULL
;
460 /* Only accept MLME and Frame from peer side, no other (control/data) frame should */
461 /* get into this state machine */
463 NdisAcquireSpinLock(&pAd
->Mlme
.TaskLock
);
464 if (pAd
->Mlme
.bRunning
) {
465 NdisReleaseSpinLock(&pAd
->Mlme
.TaskLock
);
468 pAd
->Mlme
.bRunning
= TRUE
;
470 NdisReleaseSpinLock(&pAd
->Mlme
.TaskLock
);
472 while (!MlmeQueueEmpty(&pAd
->Mlme
.Queue
)) {
473 if (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS
) ||
474 RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
) ||
475 RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
)) {
476 DBGPRINT(RT_DEBUG_TRACE
,
477 ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n",
478 pAd
->Mlme
.Queue
.Num
));
481 /*From message type, determine which state machine I should drive */
482 if (MlmeDequeue(&pAd
->Mlme
.Queue
, &Elem
)) {
484 if (Elem
->MsgType
== MT2_RESET_CONF
) {
485 DBGPRINT_RAW(RT_DEBUG_TRACE
,
486 ("reset MLME state machine!\n"));
487 MlmeRestartStateMachine(pAd
);
488 Elem
->Occupied
= FALSE
;
492 #endif /* RTMP_MAC_USB // */
494 /* if dequeue success */
495 switch (Elem
->Machine
) {
496 /* STA state machines */
497 case ASSOC_STATE_MACHINE
:
498 StateMachinePerformAction(pAd
,
502 case AUTH_STATE_MACHINE
:
503 StateMachinePerformAction(pAd
,
507 case AUTH_RSP_STATE_MACHINE
:
508 StateMachinePerformAction(pAd
,
510 AuthRspMachine
, Elem
);
512 case SYNC_STATE_MACHINE
:
513 StateMachinePerformAction(pAd
,
517 case MLME_CNTL_STATE_MACHINE
:
518 MlmeCntlMachinePerformAction(pAd
,
522 case WPA_PSK_STATE_MACHINE
:
523 StateMachinePerformAction(pAd
,
525 WpaPskMachine
, Elem
);
528 case ACTION_STATE_MACHINE
:
529 StateMachinePerformAction(pAd
,
530 &pAd
->Mlme
.ActMachine
,
534 case WPA_STATE_MACHINE
:
535 StateMachinePerformAction(pAd
,
536 &pAd
->Mlme
.WpaMachine
,
541 DBGPRINT(RT_DEBUG_TRACE
,
542 ("ERROR: Illegal machine %ld in MlmeHandler()\n",
545 } /* end of switch */
547 /* free MLME element */
548 Elem
->Occupied
= FALSE
;
552 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
556 NdisAcquireSpinLock(&pAd
->Mlme
.TaskLock
);
557 pAd
->Mlme
.bRunning
= FALSE
;
558 NdisReleaseSpinLock(&pAd
->Mlme
.TaskLock
);
562 ==========================================================================
564 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
566 Adapter - NIC Adapter pointer
568 The MLME task will no longer work properly
572 ==========================================================================
574 void MlmeHalt(struct rt_rtmp_adapter
*pAd
)
578 DBGPRINT(RT_DEBUG_TRACE
, ("==> MlmeHalt\n"));
580 if (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
)) {
581 /* disable BEACON generation and other BEACON related hardware timers */
582 AsicDisableSync(pAd
);
586 /* Cancel pending timers */
587 RTMPCancelTimer(&pAd
->MlmeAux
.AssocTimer
, &Cancelled
);
588 RTMPCancelTimer(&pAd
->MlmeAux
.ReassocTimer
, &Cancelled
);
589 RTMPCancelTimer(&pAd
->MlmeAux
.DisassocTimer
, &Cancelled
);
590 RTMPCancelTimer(&pAd
->MlmeAux
.AuthTimer
, &Cancelled
);
591 RTMPCancelTimer(&pAd
->MlmeAux
.BeaconTimer
, &Cancelled
);
592 RTMPCancelTimer(&pAd
->MlmeAux
.ScanTimer
, &Cancelled
);
595 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
)
596 && (pAd
->StaCfg
.PSControl
.field
.EnableNewPS
== TRUE
)) {
597 RTMPCancelTimer(&pAd
->Mlme
.PsPollTimer
, &Cancelled
);
598 RTMPCancelTimer(&pAd
->Mlme
.RadioOnOffTimer
, &Cancelled
);
600 #endif /* RTMP_MAC_PCI // */
602 RTMPCancelTimer(&pAd
->Mlme
.LinkDownTimer
, &Cancelled
);
605 RTMPCancelTimer(&pAd
->Mlme
.AutoWakeupTimer
, &Cancelled
);
606 #endif /* RTMP_MAC_USB // */
609 RTMPCancelTimer(&pAd
->Mlme
.PeriodicTimer
, &Cancelled
);
610 RTMPCancelTimer(&pAd
->Mlme
.RxAntEvalTimer
, &Cancelled
);
612 if (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
)) {
613 struct rt_rtmp_chip_op
*pChipOps
= &pAd
->chipOps
;
616 RTMPSetLED(pAd
, LED_HALT
);
617 RTMPSetSignalLED(pAd
, -100); /* Force signal strength Led to be turned off, firmware is not done it. */
620 LED_CFG_STRUC LedCfg
;
621 RTMP_IO_READ32(pAd
, LED_CFG
, &LedCfg
.word
);
622 LedCfg
.field
.LedPolar
= 0;
623 LedCfg
.field
.RLedMode
= 0;
624 LedCfg
.field
.GLedMode
= 0;
625 LedCfg
.field
.YLedMode
= 0;
626 RTMP_IO_WRITE32(pAd
, LED_CFG
, LedCfg
.word
);
628 #endif /* RTMP_MAC_USB // */
630 if (pChipOps
->AsicHaltAction
)
631 pChipOps
->AsicHaltAction(pAd
);
634 RTMPusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled */
636 MlmeQueueDestroy(&pAd
->Mlme
.Queue
);
637 NdisFreeSpinLock(&pAd
->Mlme
.TaskLock
);
639 DBGPRINT(RT_DEBUG_TRACE
, ("<== MlmeHalt\n"));
642 void MlmeResetRalinkCounters(struct rt_rtmp_adapter
*pAd
)
644 pAd
->RalinkCounters
.LastOneSecRxOkDataCnt
=
645 pAd
->RalinkCounters
.OneSecRxOkDataCnt
;
646 /* clear all OneSecxxx counters. */
647 pAd
->RalinkCounters
.OneSecBeaconSentCnt
= 0;
648 pAd
->RalinkCounters
.OneSecFalseCCACnt
= 0;
649 pAd
->RalinkCounters
.OneSecRxFcsErrCnt
= 0;
650 pAd
->RalinkCounters
.OneSecRxOkCnt
= 0;
651 pAd
->RalinkCounters
.OneSecTxFailCount
= 0;
652 pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
= 0;
653 pAd
->RalinkCounters
.OneSecTxRetryOkCount
= 0;
654 pAd
->RalinkCounters
.OneSecRxOkDataCnt
= 0;
655 pAd
->RalinkCounters
.OneSecReceivedByteCount
= 0;
656 pAd
->RalinkCounters
.OneSecTransmittedByteCount
= 0;
658 /* TODO: for debug only. to be removed */
659 pAd
->RalinkCounters
.OneSecOsTxCount
[QID_AC_BE
] = 0;
660 pAd
->RalinkCounters
.OneSecOsTxCount
[QID_AC_BK
] = 0;
661 pAd
->RalinkCounters
.OneSecOsTxCount
[QID_AC_VI
] = 0;
662 pAd
->RalinkCounters
.OneSecOsTxCount
[QID_AC_VO
] = 0;
663 pAd
->RalinkCounters
.OneSecDmaDoneCount
[QID_AC_BE
] = 0;
664 pAd
->RalinkCounters
.OneSecDmaDoneCount
[QID_AC_BK
] = 0;
665 pAd
->RalinkCounters
.OneSecDmaDoneCount
[QID_AC_VI
] = 0;
666 pAd
->RalinkCounters
.OneSecDmaDoneCount
[QID_AC_VO
] = 0;
667 pAd
->RalinkCounters
.OneSecTxDoneCount
= 0;
668 pAd
->RalinkCounters
.OneSecRxCount
= 0;
669 pAd
->RalinkCounters
.OneSecTxAggregationCount
= 0;
670 pAd
->RalinkCounters
.OneSecRxAggregationCount
= 0;
676 ==========================================================================
678 This routine is executed periodically to -
679 1. Decide if it's a right time to turn on PwrMgmt bit of all
681 2. Calculate ChannelQuality based on statistics of the last
682 period, so that TX rate won't toggling very frequently between a
683 successful TX and a failed TX.
684 3. If the calculated ChannelQuality indicated current connection not
685 healthy, then a ROAMing attempt is tried here.
687 IRQL = DISPATCH_LEVEL
689 ==========================================================================
691 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec */
692 void MlmePeriodicExec(void *SystemSpecific1
,
693 void *FunctionContext
,
694 void *SystemSpecific2
, void *SystemSpecific3
)
696 unsigned long TxTotalCnt
;
697 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)FunctionContext
;
701 /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */
702 /* Move code to here, because following code will return when radio is off */
703 if ((pAd
->Mlme
.PeriodicRound
% (MLME_TASK_EXEC_MULTIPLE
* 2) ==
704 0) && (pAd
->StaCfg
.bHardwareRadio
== TRUE
)
705 && (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
))
706 && (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
))
707 /*&&(pAd->bPCIclkOff == FALSE) */
711 /* Read GPIO pin2 as Hardware controlled radio state */
713 RTMP_IO_READ32(pAd
, GPIO_CTRL_CFG
, &data
);
714 #endif /* RT3090 // */
715 /*KH(PCIE PS):Added based on Jane<-- */
717 /* Read GPIO pin2 as Hardware controlled radio state */
718 /* We need to Read GPIO if HW said so no mater what advance power saving */
719 if ((pAd
->OpMode
== OPMODE_STA
) && (IDLE_ON(pAd
))
721 (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_IDLE_RADIO_OFF
))
722 && (pAd
->StaCfg
.PSControl
.field
.EnablePSinIdle
==
724 /* Want to make sure device goes to L0 state before reading register. */
725 RTMPPCIeLinkCtrlValueRestore(pAd
, 0);
726 RTMP_IO_FORCE_READ32(pAd
, GPIO_CTRL_CFG
, &data
);
727 RTMPPCIeLinkCtrlSetting(pAd
, 3);
729 RTMP_IO_FORCE_READ32(pAd
, GPIO_CTRL_CFG
, &data
);
730 #endif /* RT3090 // */
731 /*KH(PCIE PS):Added based on Jane--> */
734 pAd
->StaCfg
.bHwRadio
= TRUE
;
736 pAd
->StaCfg
.bHwRadio
= FALSE
;
738 if (pAd
->StaCfg
.bRadio
!=
739 (pAd
->StaCfg
.bHwRadio
&& pAd
->StaCfg
.bSwRadio
)) {
740 pAd
->StaCfg
.bRadio
= (pAd
->StaCfg
.bHwRadio
741 && pAd
->StaCfg
.bSwRadio
);
742 if (pAd
->StaCfg
.bRadio
== TRUE
) {
744 /* Update extra information */
745 pAd
->ExtraInfo
= EXTRA_INFO_CLEAR
;
748 /* Update extra information */
749 pAd
->ExtraInfo
= HW_RADIO_OFF
;
754 #endif /* RTMP_MAC_PCI // */
756 /* Do nothing if the driver is starting halt state. */
757 /* This might happen when timer already been fired before cancel timer with mlmehalt */
758 if ((RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_HALT_IN_PROGRESS
|
759 fRTMP_ADAPTER_RADIO_OFF
|
760 fRTMP_ADAPTER_RADIO_MEASUREMENT
|
761 fRTMP_ADAPTER_RESET_IN_PROGRESS
))))
764 RTMP_MLME_PRE_SANITY_CHECK(pAd
);
767 /* Do nothing if monitor mode is on */
771 if (pAd
->Mlme
.PeriodicRound
& 0x1) {
772 /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D */
773 if (((pAd
->MACVersion
& 0xffff) == 0x0101) &&
774 (STA_TGN_WIFI_ON(pAd
)) &&
775 (pAd
->CommonCfg
.IOTestParm
.bToggle
== FALSE
))
777 RTMP_IO_WRITE32(pAd
, TXOP_CTRL_CFG
, 0x24Bf);
778 pAd
->CommonCfg
.IOTestParm
.bToggle
= TRUE
;
779 } else if ((STA_TGN_WIFI_ON(pAd
)) &&
780 ((pAd
->MACVersion
& 0xffff) == 0x0101)) {
781 RTMP_IO_WRITE32(pAd
, TXOP_CTRL_CFG
, 0x243f);
782 pAd
->CommonCfg
.IOTestParm
.bToggle
= FALSE
;
787 pAd
->bUpdateBcnCntDone
= FALSE
;
789 /* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */
790 pAd
->Mlme
.PeriodicRound
++;
793 /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */
794 NICUpdateFifoStaCounters(pAd
);
795 #endif /* RTMP_MAC_USB // */
797 /* execute every 500ms */
798 if ((pAd
->Mlme
.PeriodicRound
% 5 == 0)
799 && RTMPAutoRateSwitchCheck(pAd
)
800 /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ )
802 /* perform dynamic tx rate switching based on past TX history */
804 if ((OPSTATUS_TEST_FLAG
805 (pAd
, fOP_STATUS_MEDIA_STATE_CONNECTED
)
807 && (!OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
)))
808 MlmeDynamicTxRateSwitching(pAd
);
811 /* Normal 1 second Mlme PeriodicExec. */
812 if (pAd
->Mlme
.PeriodicRound
% MLME_TASK_EXEC_MULTIPLE
== 0) {
813 pAd
->Mlme
.OneSecPeriodicRound
++;
815 /*ORIBATimerTimeout(pAd); */
817 /* Media status changed, report to NDIS */
818 if (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_MEDIA_STATE_CHANGE
)) {
819 RTMP_CLEAR_FLAG(pAd
, fRTMP_ADAPTER_MEDIA_STATE_CHANGE
);
820 if (OPSTATUS_TEST_FLAG
821 (pAd
, fOP_STATUS_MEDIA_STATE_CONNECTED
)) {
822 pAd
->IndicateMediaState
=
823 NdisMediaStateConnected
;
824 RTMP_IndicateMediaState(pAd
);
827 pAd
->IndicateMediaState
=
828 NdisMediaStateDisconnected
;
829 RTMP_IndicateMediaState(pAd
);
833 NdisGetSystemUpTime(&pAd
->Mlme
.Now32
);
835 /* add the most up-to-date h/w raw counters into software variable, so that */
836 /* the dynamic tuning mechanism below are based on most up-to-date information */
837 NICUpdateRawCounters(pAd
);
841 #endif /* RTMP_MAC_USB // */
843 /* Need statistics after read counter. So put after NICUpdateRawCounters */
844 ORIBATimerTimeout(pAd
);
846 /* if MGMT RING is full more than twice within 1 second, we consider there's */
847 /* a hardware problem stucking the TX path. In this case, try a hardware reset */
848 /* to recover the system */
849 /* if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */
850 /* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */
852 /* pAd->RalinkCounters.MgmtRingFullCount = 0; */
854 /* The time period for checking antenna is according to traffic */
856 if (pAd
->Mlme
.bEnableAutoAntennaCheck
) {
858 pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
+
859 pAd
->RalinkCounters
.OneSecTxRetryOkCount
+
860 pAd
->RalinkCounters
.OneSecTxFailCount
;
862 /* dynamic adjust antenna evaluation period according to the traffic */
863 if (TxTotalCnt
> 50) {
864 if (pAd
->Mlme
.OneSecPeriodicRound
%
866 AsicEvaluateRxAnt(pAd
);
869 if (pAd
->Mlme
.OneSecPeriodicRound
% 3 ==
871 AsicEvaluateRxAnt(pAd
);
877 STAMlmePeriodicExec(pAd
);
879 MlmeResetRalinkCounters(pAd
);
883 if (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
)
884 && (pAd
->bPCIclkOff
== FALSE
))
885 #endif /* RTMP_MAC_PCI // */
887 /* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */
888 /* and sending CTS-to-self over and over. */
889 /* Software Patch Solution: */
890 /* 1. Polling debug state register 0x10F4 every one second. */
891 /* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */
892 /* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */
896 RTMP_IO_READ32(pAd
, 0x10F4, &MacReg
);
897 if (((MacReg
& 0x20000000) && (MacReg
& 0x80))
898 || ((MacReg
& 0x20000000)
899 && (MacReg
& 0x20))) {
900 RTMP_IO_WRITE32(pAd
, MAC_SYS_CTRL
, 0x1);
902 RTMP_IO_WRITE32(pAd
, MAC_SYS_CTRL
, 0xC);
904 DBGPRINT(RT_DEBUG_WARN
,
905 ("Warning, MAC specific condition occurs \n"));
910 RTMP_MLME_HANDLER(pAd
);
913 pAd
->bUpdateBcnCntDone
= FALSE
;
917 ==========================================================================
918 Validate SSID for connection try and rescan purpose
919 Valid SSID will have visible chars only.
920 The valid length is from 0 to 32.
921 IRQL = DISPATCH_LEVEL
922 ==========================================================================
924 BOOLEAN
MlmeValidateSSID(u8
*pSsid
, u8 SsidLen
)
928 if (SsidLen
> MAX_LEN_OF_SSID
)
931 /* Check each character value */
932 for (index
= 0; index
< SsidLen
; index
++) {
933 if (pSsid
[index
] < 0x20)
941 void MlmeSelectTxRateTable(struct rt_rtmp_adapter
*pAd
,
942 struct rt_mac_table_entry
*pEntry
,
944 u8
*pTableSize
, u8
*pInitTxRateIdx
)
947 /* decide the rate table for tuning */
948 if (pAd
->CommonCfg
.TxRateTableSize
> 0) {
949 *ppTable
= RateSwitchTable
;
950 *pTableSize
= RateSwitchTable
[0];
951 *pInitTxRateIdx
= RateSwitchTable
[1];
956 if ((pAd
->OpMode
== OPMODE_STA
) && ADHOC_ON(pAd
)) {
957 if ((pAd
->CommonCfg
.PhyMode
>= PHY_11ABGN_MIXED
) && (pEntry
->HTCapability
.MCSSet
[0] == 0xff) && ((pEntry
->HTCapability
.MCSSet
[1] == 0x00) || (pAd
->Antenna
.field
.TxPath
== 1))) { /* 11N 1S Adhoc */
958 *ppTable
= RateSwitchTable11N1S
;
959 *pTableSize
= RateSwitchTable11N1S
[0];
960 *pInitTxRateIdx
= RateSwitchTable11N1S
[1];
962 } else if ((pAd
->CommonCfg
.PhyMode
>= PHY_11ABGN_MIXED
) && (pEntry
->HTCapability
.MCSSet
[0] == 0xff) && (pEntry
->HTCapability
.MCSSet
[1] == 0xff) && (pAd
->Antenna
.field
.TxPath
== 2)) { /* 11N 2S Adhoc */
963 if (pAd
->LatchRfRegs
.Channel
<= 14) {
964 *ppTable
= RateSwitchTable11N2S
;
965 *pTableSize
= RateSwitchTable11N2S
[0];
967 RateSwitchTable11N2S
[1];
969 *ppTable
= RateSwitchTable11N2SForABand
;
971 RateSwitchTable11N2SForABand
[0];
973 RateSwitchTable11N2SForABand
[1];
976 } else if ((pEntry
->RateLen
== 4)
977 && (pEntry
->HTCapability
.MCSSet
[0] == 0)
978 && (pEntry
->HTCapability
.MCSSet
[1] == 0)
980 *ppTable
= RateSwitchTable11B
;
981 *pTableSize
= RateSwitchTable11B
[0];
982 *pInitTxRateIdx
= RateSwitchTable11B
[1];
984 } else if (pAd
->LatchRfRegs
.Channel
<= 14) {
985 *ppTable
= RateSwitchTable11BG
;
986 *pTableSize
= RateSwitchTable11BG
[0];
987 *pInitTxRateIdx
= RateSwitchTable11BG
[1];
990 *ppTable
= RateSwitchTable11G
;
991 *pTableSize
= RateSwitchTable11G
[0];
992 *pInitTxRateIdx
= RateSwitchTable11G
[1];
997 /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
998 /* ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
999 if (((pEntry
->RateLen
== 12) || (pAd
->OpMode
== OPMODE_STA
)) && (pEntry
->HTCapability
.MCSSet
[0] == 0xff) && ((pEntry
->HTCapability
.MCSSet
[1] == 0x00) || (pAd
->CommonCfg
.TxStream
== 1))) { /* 11BGN 1S AP */
1000 *ppTable
= RateSwitchTable11BGN1S
;
1001 *pTableSize
= RateSwitchTable11BGN1S
[0];
1002 *pInitTxRateIdx
= RateSwitchTable11BGN1S
[1];
1006 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
1007 /* (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1008 if (((pEntry
->RateLen
== 12) || (pAd
->OpMode
== OPMODE_STA
)) && (pEntry
->HTCapability
.MCSSet
[0] == 0xff) && (pEntry
->HTCapability
.MCSSet
[1] == 0xff) && (pAd
->CommonCfg
.TxStream
== 2)) { /* 11BGN 2S AP */
1009 if (pAd
->LatchRfRegs
.Channel
<= 14) {
1010 *ppTable
= RateSwitchTable11BGN2S
;
1011 *pTableSize
= RateSwitchTable11BGN2S
[0];
1012 *pInitTxRateIdx
= RateSwitchTable11BGN2S
[1];
1015 *ppTable
= RateSwitchTable11BGN2SForABand
;
1016 *pTableSize
= RateSwitchTable11BGN2SForABand
[0];
1018 RateSwitchTable11BGN2SForABand
[1];
1023 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1024 if ((pEntry
->HTCapability
.MCSSet
[0] == 0xff) && ((pEntry
->HTCapability
.MCSSet
[1] == 0x00) || (pAd
->CommonCfg
.TxStream
== 1))) { /* 11N 1S AP */
1025 *ppTable
= RateSwitchTable11N1S
;
1026 *pTableSize
= RateSwitchTable11N1S
[0];
1027 *pInitTxRateIdx
= RateSwitchTable11N1S
[1];
1031 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1032 if ((pEntry
->HTCapability
.MCSSet
[0] == 0xff) && (pEntry
->HTCapability
.MCSSet
[1] == 0xff) && (pAd
->CommonCfg
.TxStream
== 2)) { /* 11N 2S AP */
1033 if (pAd
->LatchRfRegs
.Channel
<= 14) {
1034 *ppTable
= RateSwitchTable11N2S
;
1035 *pTableSize
= RateSwitchTable11N2S
[0];
1036 *pInitTxRateIdx
= RateSwitchTable11N2S
[1];
1038 *ppTable
= RateSwitchTable11N2SForABand
;
1039 *pTableSize
= RateSwitchTable11N2SForABand
[0];
1041 RateSwitchTable11N2SForABand
[1];
1046 /*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1047 if ((pEntry
->RateLen
== 4 || pAd
->CommonCfg
.PhyMode
== PHY_11B
)
1048 /*Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode */
1049 /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */
1051 *ppTable
= RateSwitchTable11B
;
1052 *pTableSize
= RateSwitchTable11B
[0];
1053 *pInitTxRateIdx
= RateSwitchTable11B
[1];
1057 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1058 if ((pEntry
->RateLen
> 8)
1059 && (pEntry
->HTCapability
.MCSSet
[0] == 0)
1060 && (pEntry
->HTCapability
.MCSSet
[1] == 0)
1061 ) { /* B/G mixed AP */
1062 *ppTable
= RateSwitchTable11BG
;
1063 *pTableSize
= RateSwitchTable11BG
[0];
1064 *pInitTxRateIdx
= RateSwitchTable11BG
[1];
1068 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1069 if ((pEntry
->RateLen
== 8)
1070 && (pEntry
->HTCapability
.MCSSet
[0] == 0)
1071 && (pEntry
->HTCapability
.MCSSet
[1] == 0)
1073 *ppTable
= RateSwitchTable11G
;
1074 *pTableSize
= RateSwitchTable11G
[0];
1075 *pInitTxRateIdx
= RateSwitchTable11G
[1];
1081 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1082 if ((pEntry
->HTCapability
.MCSSet
[0] == 0) && (pEntry
->HTCapability
.MCSSet
[1] == 0)) { /* Legacy mode */
1083 if (pAd
->CommonCfg
.MaxTxRate
<= RATE_11
) {
1084 *ppTable
= RateSwitchTable11B
;
1085 *pTableSize
= RateSwitchTable11B
[0];
1086 *pInitTxRateIdx
= RateSwitchTable11B
[1];
1087 } else if ((pAd
->CommonCfg
.MaxTxRate
> RATE_11
)
1088 && (pAd
->CommonCfg
.MinTxRate
>
1090 *ppTable
= RateSwitchTable11G
;
1091 *pTableSize
= RateSwitchTable11G
[0];
1092 *pInitTxRateIdx
= RateSwitchTable11G
[1];
1095 *ppTable
= RateSwitchTable11BG
;
1096 *pTableSize
= RateSwitchTable11BG
[0];
1098 RateSwitchTable11BG
[1];
1102 if (pAd
->LatchRfRegs
.Channel
<= 14) {
1103 if (pAd
->CommonCfg
.TxStream
== 1) {
1104 *ppTable
= RateSwitchTable11N1S
;
1105 *pTableSize
= RateSwitchTable11N1S
[0];
1107 RateSwitchTable11N1S
[1];
1108 DBGPRINT_RAW(RT_DEBUG_ERROR
,
1109 ("DRS: unkown mode,default use 11N 1S AP \n"));
1111 *ppTable
= RateSwitchTable11N2S
;
1112 *pTableSize
= RateSwitchTable11N2S
[0];
1114 RateSwitchTable11N2S
[1];
1115 DBGPRINT_RAW(RT_DEBUG_ERROR
,
1116 ("DRS: unkown mode,default use 11N 2S AP \n"));
1119 if (pAd
->CommonCfg
.TxStream
== 1) {
1120 *ppTable
= RateSwitchTable11N1S
;
1121 *pTableSize
= RateSwitchTable11N1S
[0];
1123 RateSwitchTable11N1S
[1];
1124 DBGPRINT_RAW(RT_DEBUG_ERROR
,
1125 ("DRS: unkown mode,default use 11N 1S AP \n"));
1127 *ppTable
= RateSwitchTable11N2SForABand
;
1129 RateSwitchTable11N2SForABand
[0];
1131 RateSwitchTable11N2SForABand
[1];
1132 DBGPRINT_RAW(RT_DEBUG_ERROR
,
1133 ("DRS: unkown mode,default use 11N 2S AP \n"));
1136 DBGPRINT_RAW(RT_DEBUG_ERROR
,
1137 ("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1138 pAd
->StaActive
.SupRateLen
,
1139 pAd
->StaActive
.ExtRateLen
,
1140 pAd
->StaActive
.SupportedPhyInfo
.MCSSet
[0],
1141 pAd
->StaActive
.SupportedPhyInfo
.
1147 void STAMlmePeriodicExec(struct rt_rtmp_adapter
*pAd
)
1149 unsigned long TxTotalCnt
;
1153 We return here in ATE mode, because the statistics
1154 that ATE need are not collected via this routine.
1156 #if defined(RT305x)||defined(RT3070)
1157 /* 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 */
1158 if (!pAd
->CommonCfg
.HighPowerPatchDisabled
) {
1160 if ((IS_RT3070(pAd
) && ((pAd
->MACVersion
& 0xffff) < 0x0201)))
1161 #endif /* RT3070 // */
1163 if ((pAd
->StaCfg
.RssiSample
.AvgRssi0
!= 0)
1164 && (pAd
->StaCfg
.RssiSample
.AvgRssi0
>
1165 (pAd
->BbpRssiToDbmDelta
- 35))) {
1166 RT30xxWriteRFRegister(pAd
, RF_R27
, 0x20);
1168 RT30xxWriteRFRegister(pAd
, RF_R27
, 0x23);
1173 #ifdef PCIE_PS_SUPPORT
1174 /* don't perform idle-power-save mechanism within 3 min after driver initialization. */
1175 /* This can make rebooter test more robust */
1176 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_PCIE_DEVICE
)) {
1177 if ((pAd
->OpMode
== OPMODE_STA
) && (IDLE_ON(pAd
))
1178 && (pAd
->Mlme
.SyncMachine
.CurrState
== SYNC_IDLE
)
1179 && (pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
)
1180 && (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_IDLE_RADIO_OFF
))) {
1181 if (IS_RT3090(pAd
) || IS_RT3572(pAd
) || IS_RT3390(pAd
)) {
1182 if (pAd
->StaCfg
.PSControl
.field
.EnableNewPS
==
1184 DBGPRINT(RT_DEBUG_TRACE
,
1185 ("%s\n", __func__
));
1186 RT28xxPciAsicRadioOff(pAd
,
1187 GUI_IDLE_POWER_SAVE
,
1190 AsicSendCommandToMcu(pAd
, 0x30,
1193 /* Wait command success */
1194 AsicCheckCommanOk(pAd
, PowerSafeCID
);
1196 fRTMP_ADAPTER_IDLE_RADIO_OFF
);
1197 DBGPRINT(RT_DEBUG_TRACE
,
1198 ("PSM - rt30xx Issue Sleep command)\n"));
1200 } else if (pAd
->Mlme
.OneSecPeriodicRound
> 180) {
1201 if (pAd
->StaCfg
.PSControl
.field
.EnableNewPS
==
1203 DBGPRINT(RT_DEBUG_TRACE
,
1204 ("%s\n", __func__
));
1205 RT28xxPciAsicRadioOff(pAd
,
1206 GUI_IDLE_POWER_SAVE
,
1209 AsicSendCommandToMcu(pAd
, 0x30,
1212 /* Wait command success */
1213 AsicCheckCommanOk(pAd
, PowerSafeCID
);
1215 fRTMP_ADAPTER_IDLE_RADIO_OFF
);
1216 DBGPRINT(RT_DEBUG_TRACE
,
1217 ("PSM - rt28xx Issue Sleep command)\n"));
1221 DBGPRINT(RT_DEBUG_TRACE
,
1222 ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1223 pAd
->CommonCfg
.SsidLen
,
1224 pAd
->CommonCfg
.Ssid
[0],
1225 pAd
->CommonCfg
.Ssid
[1],
1226 pAd
->CommonCfg
.Ssid
[2],
1227 pAd
->CommonCfg
.Ssid
[3], pAd
->MlmeAux
.SsidLen
,
1228 pAd
->MlmeAux
.Ssid
[0], pAd
->MlmeAux
.Ssid
[1],
1229 pAd
->MlmeAux
.Ssid
[2], pAd
->MlmeAux
.Ssid
[3]));
1232 #endif /* PCIE_PS_SUPPORT // */
1234 if (pAd
->StaCfg
.WpaSupplicantUP
== WPA_SUPPLICANT_DISABLE
) {
1235 /* WPA MIC error should block association attempt for 60 seconds */
1236 if (pAd
->StaCfg
.bBlockAssoc
&&
1237 RTMP_TIME_AFTER(pAd
->Mlme
.Now32
,
1238 pAd
->StaCfg
.LastMicErrorTime
+
1240 pAd
->StaCfg
.bBlockAssoc
= FALSE
;
1243 if ((pAd
->PreMediaState
!= pAd
->IndicateMediaState
)
1244 && (pAd
->CommonCfg
.bWirelessEvent
)) {
1245 if (pAd
->IndicateMediaState
== NdisMediaStateConnected
) {
1246 RTMPSendWirelessEvent(pAd
, IW_STA_LINKUP_EVENT_FLAG
,
1247 pAd
->MacTab
.Content
[BSSID_WCID
].
1250 pAd
->PreMediaState
= pAd
->IndicateMediaState
;
1253 if (pAd
->CommonCfg
.PSPXlink
&& ADHOC_ON(pAd
)) {
1255 AsicStaBbpTuning(pAd
);
1258 TxTotalCnt
= pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
+
1259 pAd
->RalinkCounters
.OneSecTxRetryOkCount
+
1260 pAd
->RalinkCounters
.OneSecTxFailCount
;
1262 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_MEDIA_STATE_CONNECTED
)) {
1263 /* update channel quality for Roaming and UI LinkQuality display */
1264 MlmeCalculateChannelQuality(pAd
, NULL
, pAd
->Mlme
.Now32
);
1266 /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */
1267 /* Radio is currently in noisy environment */
1268 if (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS
))
1269 AsicAdjustTxPower(pAd
);
1271 if (INFRA_ON(pAd
)) {
1273 /* Is PSM bit consistent with user power management policy? */
1274 /* This is the only place that will set PSM bit ON. */
1275 if (!OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
))
1276 MlmeCheckPsmChange(pAd
, pAd
->Mlme
.Now32
);
1278 pAd
->RalinkCounters
.LastOneSecTotalTxCount
= TxTotalCnt
;
1280 if ((RTMP_TIME_AFTER
1282 pAd
->StaCfg
.LastBeaconRxTime
+ (1 * OS_HZ
)))
1284 (!RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS
))
1286 (((TxTotalCnt
+ pAd
->RalinkCounters
.OneSecRxOkCnt
) <
1288 RTMPSetAGCInitValue(pAd
, BW_20
);
1289 DBGPRINT(RT_DEBUG_TRACE
,
1290 ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n",
1291 (0x2E + GET_LNA_GAIN(pAd
))));
1293 /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */
1294 /* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */
1296 if (pAd
->CommonCfg
.bAPSDCapable
1297 && pAd
->CommonCfg
.APEdcaParm
.bAPSDCapable
) {
1298 /* When APSD is enabled, the period changes as 20 sec */
1299 if ((pAd
->Mlme
.OneSecPeriodicRound
% 20) == 8)
1300 RTMPSendNullFrame(pAd
,
1301 pAd
->CommonCfg
.TxRate
,
1304 /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */
1305 if ((pAd
->Mlme
.OneSecPeriodicRound
% 10) == 8) {
1306 if (pAd
->CommonCfg
.bWmmCapable
)
1307 RTMPSendNullFrame(pAd
,
1312 RTMPSendNullFrame(pAd
,
1321 if (CQI_IS_DEAD(pAd
->Mlme
.ChannelQuality
)) {
1322 DBGPRINT(RT_DEBUG_TRACE
,
1323 ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n",
1324 pAd
->RalinkCounters
.BadCQIAutoRecoveryCount
));
1326 /* Lost AP, send disconnect & link down event */
1327 LinkDown(pAd
, FALSE
);
1329 RtmpOSWrielessEventSend(pAd
, SIOCGIWAP
, -1, NULL
, NULL
,
1332 /* RTMPPatchMacBbpBug(pAd); */
1333 MlmeAutoReconnectLastSSID(pAd
);
1334 } else if (CQI_IS_BAD(pAd
->Mlme
.ChannelQuality
)) {
1335 pAd
->RalinkCounters
.BadCQIAutoRecoveryCount
++;
1336 DBGPRINT(RT_DEBUG_TRACE
,
1337 ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n",
1338 pAd
->RalinkCounters
.BadCQIAutoRecoveryCount
));
1339 MlmeAutoReconnectLastSSID(pAd
);
1342 if (pAd
->StaCfg
.bAutoRoaming
) {
1344 char dBmToRoam
= pAd
->StaCfg
.dBmToRoam
;
1345 char MaxRssi
= RTMPMaxRssi(pAd
,
1346 pAd
->StaCfg
.RssiSample
.
1348 pAd
->StaCfg
.RssiSample
.
1350 pAd
->StaCfg
.RssiSample
.
1353 /* Scanning, ignore Roaming */
1355 (pAd
, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS
)
1356 && (pAd
->Mlme
.SyncMachine
.CurrState
== SYNC_IDLE
)
1357 && (MaxRssi
<= dBmToRoam
)) {
1358 DBGPRINT(RT_DEBUG_TRACE
,
1359 ("Rssi=%d, dBmToRoam=%d\n", MaxRssi
,
1362 /* Add auto seamless roaming */
1364 rv
= MlmeCheckForFastRoaming(pAd
);
1367 if ((pAd
->StaCfg
.LastScanTime
+
1368 10 * OS_HZ
) < pAd
->Mlme
.Now32
) {
1369 DBGPRINT(RT_DEBUG_TRACE
,
1370 ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1371 pAd
->StaCfg
.ScanCnt
= 2;
1372 pAd
->StaCfg
.LastScanTime
=
1379 } else if (ADHOC_ON(pAd
)) {
1380 /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */
1381 /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */
1385 pAd
->StaCfg
.LastBeaconRxTime
+ ADHOC_BEACON_LOST_TIME
)
1386 && OPSTATUS_TEST_FLAG(pAd
,
1387 fOP_STATUS_MEDIA_STATE_CONNECTED
)) {
1388 struct rt_mlme_start_req StartReq
;
1390 DBGPRINT(RT_DEBUG_TRACE
,
1391 ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1392 LinkDown(pAd
, FALSE
);
1394 StartParmFill(pAd
, &StartReq
,
1395 (char *) pAd
->MlmeAux
.Ssid
,
1396 pAd
->MlmeAux
.SsidLen
);
1397 MlmeEnqueue(pAd
, SYNC_STATE_MACHINE
, MT2_MLME_START_REQ
,
1398 sizeof(struct rt_mlme_start_req
), &StartReq
);
1399 pAd
->Mlme
.CntlMachine
.CurrState
= CNTL_WAIT_START
;
1402 for (i
= 1; i
< MAX_LEN_OF_MAC_TABLE
; i
++) {
1403 struct rt_mac_table_entry
*pEntry
= &pAd
->MacTab
.Content
[i
];
1405 if (pEntry
->ValidAsCLI
== FALSE
)
1410 pEntry
->LastBeaconRxTime
+ ADHOC_BEACON_LOST_TIME
))
1411 MacTableDeleteEntry(pAd
, pEntry
->Aid
,
1414 } else /* no INFRA nor ADHOC connection */
1417 if (pAd
->StaCfg
.bScanReqIsFromWebUI
&&
1418 RTMP_TIME_BEFORE(pAd
->Mlme
.Now32
,
1419 pAd
->StaCfg
.LastScanTime
+ (30 * OS_HZ
)))
1420 goto SKIP_AUTO_SCAN_CONN
;
1422 pAd
->StaCfg
.bScanReqIsFromWebUI
= FALSE
;
1424 if ((pAd
->StaCfg
.bAutoReconnect
== TRUE
)
1425 && RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_START_UP
)
1428 (pAd
->MlmeAux
.AutoReconnectSsid
,
1429 pAd
->MlmeAux
.AutoReconnectSsidLen
) == TRUE
)) {
1430 if ((pAd
->ScanTab
.BssNr
== 0)
1431 && (pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
)) {
1432 struct rt_mlme_scan_req ScanReq
;
1436 pAd
->StaCfg
.LastScanTime
+ (10 * OS_HZ
))) {
1437 DBGPRINT(RT_DEBUG_TRACE
,
1438 ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n",
1440 AutoReconnectSsid
));
1441 ScanParmFill(pAd
, &ScanReq
,
1442 (char *)pAd
->MlmeAux
.
1445 AutoReconnectSsidLen
,
1446 BSS_ANY
, SCAN_ACTIVE
);
1447 MlmeEnqueue(pAd
, SYNC_STATE_MACHINE
,
1450 (struct rt_mlme_scan_req
),
1452 pAd
->Mlme
.CntlMachine
.CurrState
=
1453 CNTL_WAIT_OID_LIST_SCAN
;
1454 /* Reset Missed scan number */
1455 pAd
->StaCfg
.LastScanTime
=
1457 } else if (pAd
->StaCfg
.BssType
== BSS_ADHOC
) /* Quit the forever scan when in a very clean room */
1458 MlmeAutoReconnectLastSSID(pAd
);
1459 } else if (pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
) {
1460 if ((pAd
->Mlme
.OneSecPeriodicRound
% 7) == 0) {
1462 pAd
->StaCfg
.LastScanTime
=
1465 MlmeAutoReconnectLastSSID(pAd
);
1471 SKIP_AUTO_SCAN_CONN
:
1473 if ((pAd
->MacTab
.Content
[BSSID_WCID
].TXBAbitmap
!= 0)
1474 && (pAd
->MacTab
.fAnyBASession
== FALSE
)) {
1475 pAd
->MacTab
.fAnyBASession
= TRUE
;
1476 AsicUpdateProtect(pAd
, HT_FORCERTSCTS
, ALLN_SETPROTECT
, FALSE
,
1478 } else if ((pAd
->MacTab
.Content
[BSSID_WCID
].TXBAbitmap
== 0)
1479 && (pAd
->MacTab
.fAnyBASession
== TRUE
)) {
1480 pAd
->MacTab
.fAnyBASession
= FALSE
;
1481 AsicUpdateProtect(pAd
,
1482 pAd
->MlmeAux
.AddHtInfo
.AddHtInfo2
.
1483 OperaionMode
, ALLN_SETPROTECT
, FALSE
, FALSE
);
1489 /* Link down report */
1490 void LinkDownExec(void *SystemSpecific1
,
1491 void *FunctionContext
,
1492 void *SystemSpecific2
, void *SystemSpecific3
)
1494 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)FunctionContext
;
1497 struct rt_mlme_disassoc_req DisassocReq
;
1499 if ((pAd
->StaCfg
.PortSecured
== WPA_802_1X_PORT_NOT_SECURED
) &&
1501 DBGPRINT(RT_DEBUG_TRACE
,
1502 ("LinkDownExec(): disassociate with current AP...\n"));
1503 DisassocParmFill(pAd
, &DisassocReq
,
1504 pAd
->CommonCfg
.Bssid
,
1505 REASON_DISASSOC_STA_LEAVING
);
1506 MlmeEnqueue(pAd
, ASSOC_STATE_MACHINE
,
1507 MT2_MLME_DISASSOC_REQ
,
1508 sizeof(struct rt_mlme_disassoc_req
),
1510 pAd
->Mlme
.CntlMachine
.CurrState
= CNTL_WAIT_DISASSOC
;
1512 pAd
->IndicateMediaState
= NdisMediaStateDisconnected
;
1513 RTMP_IndicateMediaState(pAd
);
1514 pAd
->ExtraInfo
= GENERAL_LINK_DOWN
;
1519 /* IRQL = DISPATCH_LEVEL */
1520 void MlmeAutoScan(struct rt_rtmp_adapter
*pAd
)
1522 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1523 if (pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
) {
1524 DBGPRINT(RT_DEBUG_TRACE
, ("MMCHK - Driver auto scan\n"));
1526 MLME_CNTL_STATE_MACHINE
,
1527 OID_802_11_BSSID_LIST_SCAN
,
1528 pAd
->MlmeAux
.AutoReconnectSsidLen
,
1529 pAd
->MlmeAux
.AutoReconnectSsid
);
1530 RTMP_MLME_HANDLER(pAd
);
1534 /* IRQL = DISPATCH_LEVEL */
1535 void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter
*pAd
)
1537 if (pAd
->StaCfg
.bAutoConnectByBssid
) {
1538 DBGPRINT(RT_DEBUG_TRACE
,
1539 ("Driver auto reconnect to last OID_802_11_BSSID "
1541 &pAd
->MlmeAux
.Bssid
[0]));
1543 pAd
->MlmeAux
.Channel
= pAd
->CommonCfg
.Channel
;
1545 MLME_CNTL_STATE_MACHINE
,
1546 OID_802_11_BSSID
, MAC_ADDR_LEN
, pAd
->MlmeAux
.Bssid
);
1548 pAd
->Mlme
.CntlMachine
.CurrState
= CNTL_IDLE
;
1550 RTMP_MLME_HANDLER(pAd
);
1552 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1553 else if ((pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
) &&
1555 (pAd
->MlmeAux
.AutoReconnectSsid
,
1556 pAd
->MlmeAux
.AutoReconnectSsidLen
) == TRUE
)) {
1557 struct rt_ndis_802_11_ssid OidSsid
;
1558 OidSsid
.SsidLength
= pAd
->MlmeAux
.AutoReconnectSsidLen
;
1559 NdisMoveMemory(OidSsid
.Ssid
, pAd
->MlmeAux
.AutoReconnectSsid
,
1560 pAd
->MlmeAux
.AutoReconnectSsidLen
);
1562 DBGPRINT(RT_DEBUG_TRACE
,
1563 ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
1564 pAd
->MlmeAux
.AutoReconnectSsid
,
1565 pAd
->MlmeAux
.AutoReconnectSsidLen
));
1566 MlmeEnqueue(pAd
, MLME_CNTL_STATE_MACHINE
, OID_802_11_SSID
,
1567 sizeof(struct rt_ndis_802_11_ssid
), &OidSsid
);
1568 RTMP_MLME_HANDLER(pAd
);
1573 ==========================================================================
1575 This routine checks if there're other APs out there capable for
1576 roaming. Caller should call this routine only when Link up in INFRA mode
1577 and channel quality is below CQI_GOOD_THRESHOLD.
1579 IRQL = DISPATCH_LEVEL
1582 ==========================================================================
1584 void MlmeCheckForRoaming(struct rt_rtmp_adapter
*pAd
, unsigned long Now32
)
1587 struct rt_bss_table
*pRoamTab
= &pAd
->MlmeAux
.RoamTab
;
1588 struct rt_bss_entry
*pBss
;
1590 DBGPRINT(RT_DEBUG_TRACE
, ("==> MlmeCheckForRoaming\n"));
1591 /* put all roaming candidates into RoamTab, and sort in RSSI order */
1592 BssTableInit(pRoamTab
);
1593 for (i
= 0; i
< pAd
->ScanTab
.BssNr
; i
++) {
1594 pBss
= &pAd
->ScanTab
.BssEntry
[i
];
1596 if ((pBss
->LastBeaconRxTime
+ pAd
->StaCfg
.BeaconLostTime
) <
1598 continue; /* AP disappear */
1599 if (pBss
->Rssi
<= RSSI_THRESHOLD_FOR_ROAMING
)
1600 continue; /* RSSI too weak. forget it. */
1601 if (MAC_ADDR_EQUAL(pBss
->Bssid
, pAd
->CommonCfg
.Bssid
))
1602 continue; /* skip current AP */
1604 (pAd
->StaCfg
.RssiSample
.LastRssi0
+ RSSI_DELTA
))
1605 continue; /* only AP with stronger RSSI is eligible for roaming */
1607 /* AP passing all above rules is put into roaming candidate table */
1608 NdisMoveMemory(&pRoamTab
->BssEntry
[pRoamTab
->BssNr
], pBss
,
1609 sizeof(struct rt_bss_entry
));
1610 pRoamTab
->BssNr
+= 1;
1613 if (pRoamTab
->BssNr
> 0) {
1614 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1615 if (pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
) {
1616 pAd
->RalinkCounters
.PoorCQIRoamingCount
++;
1617 DBGPRINT(RT_DEBUG_TRACE
,
1618 ("MMCHK - Roaming attempt #%ld\n",
1619 pAd
->RalinkCounters
.PoorCQIRoamingCount
));
1620 MlmeEnqueue(pAd
, MLME_CNTL_STATE_MACHINE
,
1621 MT2_MLME_ROAMING_REQ
, 0, NULL
);
1622 RTMP_MLME_HANDLER(pAd
);
1625 DBGPRINT(RT_DEBUG_TRACE
,
1626 ("<== MlmeCheckForRoaming(# of candidate= %d)\n",
1631 ==========================================================================
1633 This routine checks if there're other APs out there capable for
1634 roaming. Caller should call this routine only when link up in INFRA mode
1635 and channel quality is below CQI_GOOD_THRESHOLD.
1637 IRQL = DISPATCH_LEVEL
1640 ==========================================================================
1642 BOOLEAN
MlmeCheckForFastRoaming(struct rt_rtmp_adapter
*pAd
)
1645 struct rt_bss_table
*pRoamTab
= &pAd
->MlmeAux
.RoamTab
;
1646 struct rt_bss_entry
*pBss
;
1648 DBGPRINT(RT_DEBUG_TRACE
, ("==> MlmeCheckForFastRoaming\n"));
1649 /* put all roaming candidates into RoamTab, and sort in RSSI order */
1650 BssTableInit(pRoamTab
);
1651 for (i
= 0; i
< pAd
->ScanTab
.BssNr
; i
++) {
1652 pBss
= &pAd
->ScanTab
.BssEntry
[i
];
1654 if ((pBss
->Rssi
<= -50)
1655 && (pBss
->Channel
== pAd
->CommonCfg
.Channel
))
1656 continue; /* RSSI too weak. forget it. */
1657 if (MAC_ADDR_EQUAL(pBss
->Bssid
, pAd
->CommonCfg
.Bssid
))
1658 continue; /* skip current AP */
1660 (pBss
->Ssid
, pBss
->SsidLen
, pAd
->CommonCfg
.Ssid
,
1661 pAd
->CommonCfg
.SsidLen
))
1662 continue; /* skip different SSID */
1665 (pAd
, pAd
->StaCfg
.RssiSample
.LastRssi0
,
1666 pAd
->StaCfg
.RssiSample
.LastRssi1
,
1667 pAd
->StaCfg
.RssiSample
.LastRssi2
) + RSSI_DELTA
))
1668 continue; /* skip AP without better RSSI */
1670 DBGPRINT(RT_DEBUG_TRACE
,
1671 ("LastRssi0 = %d, pBss->Rssi = %d\n",
1672 RTMPMaxRssi(pAd
, pAd
->StaCfg
.RssiSample
.LastRssi0
,
1673 pAd
->StaCfg
.RssiSample
.LastRssi1
,
1674 pAd
->StaCfg
.RssiSample
.LastRssi2
),
1676 /* AP passing all above rules is put into roaming candidate table */
1677 NdisMoveMemory(&pRoamTab
->BssEntry
[pRoamTab
->BssNr
], pBss
,
1678 sizeof(struct rt_bss_entry
));
1679 pRoamTab
->BssNr
+= 1;
1682 DBGPRINT(RT_DEBUG_TRACE
,
1683 ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab
->BssNr
));
1684 if (pRoamTab
->BssNr
> 0) {
1685 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1686 if (pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
) {
1687 pAd
->RalinkCounters
.PoorCQIRoamingCount
++;
1688 DBGPRINT(RT_DEBUG_TRACE
,
1689 ("MMCHK - Roaming attempt #%ld\n",
1690 pAd
->RalinkCounters
.PoorCQIRoamingCount
));
1691 MlmeEnqueue(pAd
, MLME_CNTL_STATE_MACHINE
,
1692 MT2_MLME_ROAMING_REQ
, 0, NULL
);
1693 RTMP_MLME_HANDLER(pAd
);
1701 void MlmeSetTxRate(struct rt_rtmp_adapter
*pAd
,
1702 struct rt_mac_table_entry
*pEntry
, struct rt_rtmp_tx_rate_switch
* pTxRate
)
1704 u8 MaxMode
= MODE_OFDM
;
1706 MaxMode
= MODE_HTGREENFIELD
;
1708 if (pTxRate
->STBC
&& (pAd
->StaCfg
.MaxHTPhyMode
.field
.STBC
)
1709 && (pAd
->Antenna
.field
.TxPath
== 2))
1710 pAd
->StaCfg
.HTPhyMode
.field
.STBC
= STBC_USE
;
1712 pAd
->StaCfg
.HTPhyMode
.field
.STBC
= STBC_NONE
;
1714 if (pTxRate
->CurrMCS
< MCS_AUTO
)
1715 pAd
->StaCfg
.HTPhyMode
.field
.MCS
= pTxRate
->CurrMCS
;
1717 if (pAd
->StaCfg
.HTPhyMode
.field
.MCS
> 7)
1718 pAd
->StaCfg
.HTPhyMode
.field
.STBC
= STBC_NONE
;
1720 if (ADHOC_ON(pAd
)) {
1721 /* If peer adhoc is b-only mode, we can't send 11g rate. */
1722 pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
= GI_800
;
1723 pEntry
->HTPhyMode
.field
.STBC
= STBC_NONE
;
1726 /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */
1728 pEntry
->HTPhyMode
.field
.MODE
= pTxRate
->Mode
;
1729 pEntry
->HTPhyMode
.field
.ShortGI
=
1730 pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
;
1731 pEntry
->HTPhyMode
.field
.MCS
= pAd
->StaCfg
.HTPhyMode
.field
.MCS
;
1733 /* Patch speed error in status page */
1734 pAd
->StaCfg
.HTPhyMode
.field
.MODE
= pEntry
->HTPhyMode
.field
.MODE
;
1736 if (pTxRate
->Mode
<= MaxMode
)
1737 pAd
->StaCfg
.HTPhyMode
.field
.MODE
= pTxRate
->Mode
;
1739 if (pTxRate
->ShortGI
1740 && (pAd
->StaCfg
.MaxHTPhyMode
.field
.ShortGI
))
1741 pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
= GI_400
;
1743 pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
= GI_800
;
1745 /* Reexam each bandwidth's SGI support. */
1746 if (pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
== GI_400
) {
1747 if ((pEntry
->HTPhyMode
.field
.BW
== BW_20
)
1749 (!CLIENT_STATUS_TEST_FLAG
1750 (pEntry
, fCLIENT_STATUS_SGI20_CAPABLE
)))
1751 pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
= GI_800
;
1752 if ((pEntry
->HTPhyMode
.field
.BW
== BW_40
)
1754 (!CLIENT_STATUS_TEST_FLAG
1755 (pEntry
, fCLIENT_STATUS_SGI40_CAPABLE
)))
1756 pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
= GI_800
;
1758 /* Turn RTS/CTS rate to 6Mbps. */
1759 if ((pEntry
->HTPhyMode
.field
.MCS
== 0)
1760 && (pAd
->StaCfg
.HTPhyMode
.field
.MCS
!= 0)) {
1761 pEntry
->HTPhyMode
.field
.MCS
=
1762 pAd
->StaCfg
.HTPhyMode
.field
.MCS
;
1763 if (pAd
->MacTab
.fAnyBASession
) {
1764 AsicUpdateProtect(pAd
, HT_FORCERTSCTS
,
1765 ALLN_SETPROTECT
, TRUE
,
1766 (BOOLEAN
) pAd
->MlmeAux
.
1767 AddHtInfo
.AddHtInfo2
.
1770 AsicUpdateProtect(pAd
,
1771 pAd
->MlmeAux
.AddHtInfo
.
1772 AddHtInfo2
.OperaionMode
,
1773 ALLN_SETPROTECT
, TRUE
,
1774 (BOOLEAN
) pAd
->MlmeAux
.
1775 AddHtInfo
.AddHtInfo2
.
1778 } else if ((pEntry
->HTPhyMode
.field
.MCS
== 8)
1779 && (pAd
->StaCfg
.HTPhyMode
.field
.MCS
!= 8)) {
1780 pEntry
->HTPhyMode
.field
.MCS
=
1781 pAd
->StaCfg
.HTPhyMode
.field
.MCS
;
1782 if (pAd
->MacTab
.fAnyBASession
) {
1783 AsicUpdateProtect(pAd
, HT_FORCERTSCTS
,
1784 ALLN_SETPROTECT
, TRUE
,
1785 (BOOLEAN
) pAd
->MlmeAux
.
1786 AddHtInfo
.AddHtInfo2
.
1789 AsicUpdateProtect(pAd
,
1790 pAd
->MlmeAux
.AddHtInfo
.
1791 AddHtInfo2
.OperaionMode
,
1792 ALLN_SETPROTECT
, TRUE
,
1793 (BOOLEAN
) pAd
->MlmeAux
.
1794 AddHtInfo
.AddHtInfo2
.
1797 } else if ((pEntry
->HTPhyMode
.field
.MCS
!= 0)
1798 && (pAd
->StaCfg
.HTPhyMode
.field
.MCS
== 0)) {
1799 AsicUpdateProtect(pAd
, HT_RTSCTS_6M
, ALLN_SETPROTECT
,
1801 (BOOLEAN
) pAd
->MlmeAux
.AddHtInfo
.
1802 AddHtInfo2
.NonGfPresent
);
1804 } else if ((pEntry
->HTPhyMode
.field
.MCS
!= 8)
1805 && (pAd
->StaCfg
.HTPhyMode
.field
.MCS
== 8)) {
1806 AsicUpdateProtect(pAd
, HT_RTSCTS_6M
, ALLN_SETPROTECT
,
1808 (BOOLEAN
) pAd
->MlmeAux
.AddHtInfo
.
1809 AddHtInfo2
.NonGfPresent
);
1812 pEntry
->HTPhyMode
.field
.STBC
= pAd
->StaCfg
.HTPhyMode
.field
.STBC
;
1813 pEntry
->HTPhyMode
.field
.ShortGI
=
1814 pAd
->StaCfg
.HTPhyMode
.field
.ShortGI
;
1815 pEntry
->HTPhyMode
.field
.MCS
= pAd
->StaCfg
.HTPhyMode
.field
.MCS
;
1816 pEntry
->HTPhyMode
.field
.MODE
= pAd
->StaCfg
.HTPhyMode
.field
.MODE
;
1817 if ((pAd
->StaCfg
.MaxHTPhyMode
.field
.MODE
== MODE_HTGREENFIELD
)
1818 && pAd
->WIFItestbed
.bGreenField
)
1819 pEntry
->HTPhyMode
.field
.MODE
= MODE_HTGREENFIELD
;
1822 pAd
->LastTxRate
= (u16
)(pEntry
->HTPhyMode
.word
);
1826 ==========================================================================
1828 This routine calculates the acumulated TxPER of eaxh TxRate. And
1829 according to the calculation result, change CommonCfg.TxRate which
1830 is the stable TX Rate we expect the Radio situation could sustained.
1832 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1836 IRQL = DISPATCH_LEVEL
1839 call this routine every second
1840 ==========================================================================
1842 void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter
*pAd
)
1844 u8 UpRateIdx
= 0, DownRateIdx
= 0, CurrRateIdx
;
1845 unsigned long i
, AccuTxTotalCnt
= 0, TxTotalCnt
;
1846 unsigned long TxErrorRatio
= 0;
1847 BOOLEAN bTxRateChanged
= FALSE
, bUpgradeQuality
= FALSE
;
1848 struct rt_rtmp_tx_rate_switch
*pCurrTxRate
, *pNextTxRate
= NULL
;
1851 u8 InitTxRateIdx
= 0, TrainUp
, TrainDown
;
1852 char Rssi
, RssiOffset
= 0;
1853 TX_STA_CNT1_STRUC StaTx1
;
1854 TX_STA_CNT0_STRUC TxStaCnt0
;
1855 unsigned long TxRetransmit
= 0, TxSuccess
= 0, TxFailCount
= 0;
1856 struct rt_mac_table_entry
*pEntry
;
1857 struct rt_rssi_sample
*pRssi
= &pAd
->StaCfg
.RssiSample
;
1860 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
1862 for (i
= 1; i
< MAX_LEN_OF_MAC_TABLE
; i
++) {
1863 pEntry
= &pAd
->MacTab
.Content
[i
];
1865 /* check if this entry need to switch rate automatically */
1866 if (RTMPCheckEntryEnableAutoRateSwitch(pAd
, pEntry
) == FALSE
)
1869 if ((pAd
->MacTab
.Size
== 1) || (pEntry
->ValidAsDls
)) {
1870 Rssi
= RTMPMaxRssi(pAd
,
1872 pRssi
->AvgRssi1
, pRssi
->AvgRssi2
);
1874 /* Update statistic counter */
1875 RTMP_IO_READ32(pAd
, TX_STA_CNT0
, &TxStaCnt0
.word
);
1876 RTMP_IO_READ32(pAd
, TX_STA_CNT1
, &StaTx1
.word
);
1877 pAd
->bUpdateBcnCntDone
= TRUE
;
1878 TxRetransmit
= StaTx1
.field
.TxRetransmit
;
1879 TxSuccess
= StaTx1
.field
.TxSuccess
;
1880 TxFailCount
= TxStaCnt0
.field
.TxFailCount
;
1881 TxTotalCnt
= TxRetransmit
+ TxSuccess
+ TxFailCount
;
1883 pAd
->RalinkCounters
.OneSecTxRetryOkCount
+=
1884 StaTx1
.field
.TxRetransmit
;
1885 pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
+=
1886 StaTx1
.field
.TxSuccess
;
1887 pAd
->RalinkCounters
.OneSecTxFailCount
+=
1888 TxStaCnt0
.field
.TxFailCount
;
1889 pAd
->WlanCounters
.TransmittedFragmentCount
.u
.LowPart
+=
1890 StaTx1
.field
.TxSuccess
;
1891 pAd
->WlanCounters
.RetryCount
.u
.LowPart
+=
1892 StaTx1
.field
.TxRetransmit
;
1893 pAd
->WlanCounters
.FailedCount
.u
.LowPart
+=
1894 TxStaCnt0
.field
.TxFailCount
;
1896 /* if no traffic in the past 1-sec period, don't change TX rate, */
1897 /* but clear all bad history. because the bad history may affect the next */
1898 /* Chariot throughput test */
1900 pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
+
1901 pAd
->RalinkCounters
.OneSecTxRetryOkCount
+
1902 pAd
->RalinkCounters
.OneSecTxFailCount
;
1907 TxFailCount
) * 100) / TxTotalCnt
;
1909 if (INFRA_ON(pAd
) && (i
== 1))
1910 Rssi
= RTMPMaxRssi(pAd
,
1915 Rssi
= RTMPMaxRssi(pAd
,
1916 pEntry
->RssiSample
.AvgRssi0
,
1917 pEntry
->RssiSample
.AvgRssi1
,
1918 pEntry
->RssiSample
.AvgRssi2
);
1920 TxTotalCnt
= pEntry
->OneSecTxNoRetryOkCount
+
1921 pEntry
->OneSecTxRetryOkCount
+
1922 pEntry
->OneSecTxFailCount
;
1926 ((pEntry
->OneSecTxRetryOkCount
+
1927 pEntry
->OneSecTxFailCount
) * 100) /
1933 Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1934 We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1936 if (TxErrorRatio
== 100) {
1937 TX_RTY_CFG_STRUC TxRtyCfg
, TxRtyCfgtmp
;
1938 unsigned long Index
;
1939 unsigned long MACValue
;
1941 RTMP_IO_READ32(pAd
, TX_RTY_CFG
, &TxRtyCfg
.word
);
1942 TxRtyCfgtmp
.word
= TxRtyCfg
.word
;
1943 TxRtyCfg
.field
.LongRtyLimit
= 0x0;
1944 TxRtyCfg
.field
.ShortRtyLimit
= 0x0;
1945 RTMP_IO_WRITE32(pAd
, TX_RTY_CFG
, TxRtyCfg
.word
);
1952 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
,
1954 if ((MACValue
& 0xffffff) == 0)
1957 RTMPusecDelay(1000);
1958 } while ((Index
< 330)
1962 fRTMP_ADAPTER_HALT_IN_PROGRESS
)));
1964 RTMP_IO_READ32(pAd
, TX_RTY_CFG
, &TxRtyCfg
.word
);
1965 TxRtyCfg
.field
.LongRtyLimit
=
1966 TxRtyCfgtmp
.field
.LongRtyLimit
;
1967 TxRtyCfg
.field
.ShortRtyLimit
=
1968 TxRtyCfgtmp
.field
.ShortRtyLimit
;
1969 RTMP_IO_WRITE32(pAd
, TX_RTY_CFG
, TxRtyCfg
.word
);
1973 CurrRateIdx
= pEntry
->CurrTxRateIndex
;
1975 MlmeSelectTxRateTable(pAd
, pEntry
, &pTable
, &TableSize
,
1978 if (CurrRateIdx
>= TableSize
) {
1979 CurrRateIdx
= TableSize
- 1;
1981 /* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */
1982 /* So need to sync here. */
1984 (struct rt_rtmp_tx_rate_switch
*) & pTable
[(CurrRateIdx
+ 1) * 5];
1985 if ((pEntry
->HTPhyMode
.field
.MCS
!= pCurrTxRate
->CurrMCS
)
1986 /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */
1989 /* Need to sync Real Tx rate and our record. */
1990 /* Then return for next DRS. */
1992 (struct rt_rtmp_tx_rate_switch
*) & pTable
[(InitTxRateIdx
+ 1)
1994 pEntry
->CurrTxRateIndex
= InitTxRateIdx
;
1995 MlmeSetTxRate(pAd
, pEntry
, pCurrTxRate
);
1997 /* reset all OneSecTx counters */
1998 RESET_ONE_SEC_TX_CNT(pEntry
);
2001 /* decide the next upgrade rate and downgrade rate, if any */
2002 if ((CurrRateIdx
> 0) && (CurrRateIdx
< (TableSize
- 1))) {
2003 UpRateIdx
= CurrRateIdx
+ 1;
2004 DownRateIdx
= CurrRateIdx
- 1;
2005 } else if (CurrRateIdx
== 0) {
2006 UpRateIdx
= CurrRateIdx
+ 1;
2007 DownRateIdx
= CurrRateIdx
;
2008 } else if (CurrRateIdx
== (TableSize
- 1)) {
2009 UpRateIdx
= CurrRateIdx
;
2010 DownRateIdx
= CurrRateIdx
- 1;
2014 (struct rt_rtmp_tx_rate_switch
*) & pTable
[(CurrRateIdx
+ 1) * 5];
2016 if ((Rssi
> -65) && (pCurrTxRate
->Mode
>= MODE_HTMIX
)) {
2018 (pCurrTxRate
->TrainUp
+
2019 (pCurrTxRate
->TrainUp
>> 1));
2021 (pCurrTxRate
->TrainDown
+
2022 (pCurrTxRate
->TrainDown
>> 1));
2024 TrainUp
= pCurrTxRate
->TrainUp
;
2025 TrainDown
= pCurrTxRate
->TrainDown
;
2028 /*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */
2031 /* Keep the last time TxRateChangeAction status. */
2033 pEntry
->LastTimeTxRateChangeAction
=
2034 pEntry
->LastSecTxRateChangeAction
;
2037 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2038 /* (criteria copied from RT2500 for Netopia case) */
2040 if (TxTotalCnt
<= 15) {
2043 u8 MCS0
= 0, MCS1
= 0, MCS2
= 0, MCS3
= 0, MCS4
=
2044 0, MCS5
= 0, MCS6
= 0, MCS7
= 0;
2045 u8 MCS12
= 0, MCS13
= 0, MCS14
= 0, MCS15
= 0;
2046 u8 MCS20
= 0, MCS21
= 0, MCS22
= 0, MCS23
= 0; /* 3*3 */
2048 /* check the existence and index of each needed MCS */
2049 while (idx
< pTable
[0]) {
2051 (struct rt_rtmp_tx_rate_switch
*) & pTable
[(idx
+ 1) *
2054 if (pCurrTxRate
->CurrMCS
== MCS_0
) {
2056 } else if (pCurrTxRate
->CurrMCS
== MCS_1
) {
2058 } else if (pCurrTxRate
->CurrMCS
== MCS_2
) {
2060 } else if (pCurrTxRate
->CurrMCS
== MCS_3
) {
2062 } else if (pCurrTxRate
->CurrMCS
== MCS_4
) {
2064 } else if (pCurrTxRate
->CurrMCS
== MCS_5
) {
2066 } else if (pCurrTxRate
->CurrMCS
== MCS_6
) {
2069 /*else if (pCurrTxRate->CurrMCS == MCS_7) */
2070 else if ((pCurrTxRate
->CurrMCS
== MCS_7
) && (pCurrTxRate
->ShortGI
== GI_800
)) /* prevent the highest MCS using short GI when 1T and low throughput */
2073 } else if (pCurrTxRate
->CurrMCS
== MCS_12
) {
2075 } else if (pCurrTxRate
->CurrMCS
== MCS_13
) {
2077 } else if (pCurrTxRate
->CurrMCS
== MCS_14
) {
2080 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 */
2083 } else if (pCurrTxRate
->CurrMCS
== MCS_20
) /* 3*3 */
2086 } else if (pCurrTxRate
->CurrMCS
== MCS_21
) {
2088 } else if (pCurrTxRate
->CurrMCS
== MCS_22
) {
2090 } else if (pCurrTxRate
->CurrMCS
== MCS_23
) {
2096 if (pAd
->LatchRfRegs
.Channel
<= 14) {
2097 if (pAd
->NicConfig2
.field
.ExternalLNAForG
) {
2103 if (pAd
->NicConfig2
.field
.ExternalLNAForA
) {
2111 if ((pTable
== RateSwitchTable11BGN3S
) || (pTable
== RateSwitchTable11N3S
) || (pTable
== RateSwitchTable
)) { /* N mode with 3 stream // 3*3 */
2112 if (MCS23
&& (Rssi
>= -70))
2114 else if (MCS22
&& (Rssi
>= -72))
2116 else if (MCS21
&& (Rssi
>= -76))
2118 else if (MCS20
&& (Rssi
>= -78))
2120 else if (MCS4
&& (Rssi
>= -82))
2122 else if (MCS3
&& (Rssi
>= -84))
2124 else if (MCS2
&& (Rssi
>= -86))
2126 else if (MCS1
&& (Rssi
>= -88))
2131 /* else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */
2132 else if ((pTable
== RateSwitchTable11BGN2S
) || (pTable
== RateSwitchTable11BGN2SForABand
) || (pTable
== RateSwitchTable11N2S
) || (pTable
== RateSwitchTable11N2SForABand
)) /* 3*3 */
2133 { /* N mode with 2 stream */
2134 if (MCS15
&& (Rssi
>= (-70 + RssiOffset
)))
2136 else if (MCS14
&& (Rssi
>= (-72 + RssiOffset
)))
2138 else if (MCS13
&& (Rssi
>= (-76 + RssiOffset
)))
2140 else if (MCS12
&& (Rssi
>= (-78 + RssiOffset
)))
2142 else if (MCS4
&& (Rssi
>= (-82 + RssiOffset
)))
2144 else if (MCS3
&& (Rssi
>= (-84 + RssiOffset
)))
2146 else if (MCS2
&& (Rssi
>= (-86 + RssiOffset
)))
2148 else if (MCS1
&& (Rssi
>= (-88 + RssiOffset
)))
2152 } else if ((pTable
== RateSwitchTable11BGN1S
) || (pTable
== RateSwitchTable11N1S
)) { /* N mode with 1 stream */
2153 if (MCS7
&& (Rssi
> (-72 + RssiOffset
)))
2155 else if (MCS6
&& (Rssi
> (-74 + RssiOffset
)))
2157 else if (MCS5
&& (Rssi
> (-77 + RssiOffset
)))
2159 else if (MCS4
&& (Rssi
> (-79 + RssiOffset
)))
2161 else if (MCS3
&& (Rssi
> (-81 + RssiOffset
)))
2163 else if (MCS2
&& (Rssi
> (-83 + RssiOffset
)))
2165 else if (MCS1
&& (Rssi
> (-86 + RssiOffset
)))
2169 } else { /* Legacy mode */
2170 if (MCS7
&& (Rssi
> -70))
2172 else if (MCS6
&& (Rssi
> -74))
2174 else if (MCS5
&& (Rssi
> -78))
2176 else if (MCS4
&& (Rssi
> -82))
2178 else if (MCS4
== 0) /* for B-only mode */
2180 else if (MCS3
&& (Rssi
> -85))
2182 else if (MCS2
&& (Rssi
> -87))
2184 else if (MCS1
&& (Rssi
> -90))
2190 /* if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */
2192 pEntry
->CurrTxRateIndex
= TxRateIdx
;
2194 (struct rt_rtmp_tx_rate_switch
*) &
2195 pTable
[(pEntry
->CurrTxRateIndex
+ 1) * 5];
2196 MlmeSetTxRate(pAd
, pEntry
, pNextTxRate
);
2199 NdisZeroMemory(pEntry
->TxQuality
,
2201 MAX_STEP_OF_TX_RATE_SWITCH
);
2202 NdisZeroMemory(pEntry
->PER
,
2204 MAX_STEP_OF_TX_RATE_SWITCH
);
2205 pEntry
->fLastSecAccordingRSSI
= TRUE
;
2206 /* reset all OneSecTx counters */
2207 RESET_ONE_SEC_TX_CNT(pEntry
);
2212 if (pEntry
->fLastSecAccordingRSSI
== TRUE
) {
2213 pEntry
->fLastSecAccordingRSSI
= FALSE
;
2214 pEntry
->LastSecTxRateChangeAction
= 0;
2215 /* reset all OneSecTx counters */
2216 RESET_ONE_SEC_TX_CNT(pEntry
);
2222 BOOLEAN bTrainUpDown
= FALSE
;
2224 pEntry
->CurrTxRateStableTime
++;
2226 /* downgrade TX quality if PER >= Rate-Down threshold */
2227 if (TxErrorRatio
>= TrainDown
) {
2228 bTrainUpDown
= TRUE
;
2229 pEntry
->TxQuality
[CurrRateIdx
] =
2230 DRS_TX_QUALITY_WORST_BOUND
;
2232 /* upgrade TX quality if PER <= Rate-Up threshold */
2233 else if (TxErrorRatio
<= TrainUp
) {
2234 bTrainUpDown
= TRUE
;
2235 bUpgradeQuality
= TRUE
;
2236 if (pEntry
->TxQuality
[CurrRateIdx
])
2237 pEntry
->TxQuality
[CurrRateIdx
]--; /* quality very good in CurrRate */
2239 if (pEntry
->TxRateUpPenalty
)
2240 pEntry
->TxRateUpPenalty
--;
2241 else if (pEntry
->TxQuality
[UpRateIdx
])
2242 pEntry
->TxQuality
[UpRateIdx
]--; /* may improve next UP rate's quality */
2245 pEntry
->PER
[CurrRateIdx
] = (u8
)TxErrorRatio
;
2248 /* perform DRS - consider TxRate Down first, then rate up. */
2249 if ((CurrRateIdx
!= DownRateIdx
)
2250 && (pEntry
->TxQuality
[CurrRateIdx
] >=
2251 DRS_TX_QUALITY_WORST_BOUND
)) {
2252 pEntry
->CurrTxRateIndex
= DownRateIdx
;
2253 } else if ((CurrRateIdx
!= UpRateIdx
)
2254 && (pEntry
->TxQuality
[UpRateIdx
] <=
2256 pEntry
->CurrTxRateIndex
= UpRateIdx
;
2261 /* if rate-up happen, clear all bad history of all TX rates */
2262 if (pEntry
->CurrTxRateIndex
> CurrRateIdx
) {
2263 pEntry
->CurrTxRateStableTime
= 0;
2264 pEntry
->TxRateUpPenalty
= 0;
2265 pEntry
->LastSecTxRateChangeAction
= 1; /* rate UP */
2266 NdisZeroMemory(pEntry
->TxQuality
,
2268 MAX_STEP_OF_TX_RATE_SWITCH
);
2269 NdisZeroMemory(pEntry
->PER
,
2271 MAX_STEP_OF_TX_RATE_SWITCH
);
2274 /* For TxRate fast train up */
2276 if (!pAd
->StaCfg
.StaQuickResponeForRateUpTimerRunning
) {
2277 RTMPSetTimer(&pAd
->StaCfg
.
2278 StaQuickResponeForRateUpTimer
,
2282 StaQuickResponeForRateUpTimerRunning
= TRUE
;
2284 bTxRateChanged
= TRUE
;
2286 /* if rate-down happen, only clear DownRate's bad history */
2287 else if (pEntry
->CurrTxRateIndex
< CurrRateIdx
) {
2288 pEntry
->CurrTxRateStableTime
= 0;
2289 pEntry
->TxRateUpPenalty
= 0; /* no penalty */
2290 pEntry
->LastSecTxRateChangeAction
= 2; /* rate DOWN */
2291 pEntry
->TxQuality
[pEntry
->CurrTxRateIndex
] = 0;
2292 pEntry
->PER
[pEntry
->CurrTxRateIndex
] = 0;
2295 /* For TxRate fast train down */
2297 if (!pAd
->StaCfg
.StaQuickResponeForRateUpTimerRunning
) {
2298 RTMPSetTimer(&pAd
->StaCfg
.
2299 StaQuickResponeForRateUpTimer
,
2303 StaQuickResponeForRateUpTimerRunning
= TRUE
;
2305 bTxRateChanged
= TRUE
;
2307 pEntry
->LastSecTxRateChangeAction
= 0; /* rate no change */
2308 bTxRateChanged
= FALSE
;
2311 pEntry
->LastTxOkCount
= TxSuccess
;
2315 /* to fix tcp ack issue */
2317 && (pAd
->RalinkCounters
.OneSecReceivedByteCount
>
2318 (pAd
->RalinkCounters
.
2319 OneSecTransmittedByteCount
* 5))) {
2320 tmpTxRate
= DownRateIdx
;
2321 DBGPRINT_RAW(RT_DEBUG_TRACE
,
2322 ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2323 pAd
->RalinkCounters
.
2324 OneSecReceivedByteCount
,
2325 pAd
->RalinkCounters
.
2326 OneSecTransmittedByteCount
,
2327 pEntry
->CurrTxRateIndex
,
2330 tmpTxRate
= pEntry
->CurrTxRateIndex
;
2334 (struct rt_rtmp_tx_rate_switch
*) & pTable
[(tmpTxRate
+ 1) *
2337 if (bTxRateChanged
&& pNextTxRate
) {
2338 MlmeSetTxRate(pAd
, pEntry
, pNextTxRate
);
2340 /* reset all OneSecTx counters */
2341 RESET_ONE_SEC_TX_CNT(pEntry
);
2346 ========================================================================
2347 Routine Description:
2348 Station side, Auto TxRate faster train up timer call back function.
2351 SystemSpecific1 - Not used.
2352 FunctionContext - Pointer to our Adapter context.
2353 SystemSpecific2 - Not used.
2354 SystemSpecific3 - Not used.
2359 ========================================================================
2361 void StaQuickResponeForRateUpExec(void *SystemSpecific1
,
2362 void *FunctionContext
,
2363 void *SystemSpecific2
,
2364 void *SystemSpecific3
)
2366 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)FunctionContext
;
2367 u8 UpRateIdx
= 0, DownRateIdx
= 0, CurrRateIdx
= 0;
2368 unsigned long TxTotalCnt
;
2369 unsigned long TxErrorRatio
= 0;
2370 BOOLEAN bTxRateChanged
; /*, bUpgradeQuality = FALSE; */
2371 struct rt_rtmp_tx_rate_switch
*pCurrTxRate
, *pNextTxRate
= NULL
;
2374 u8 InitTxRateIdx
= 0, TrainUp
, TrainDown
;
2375 TX_STA_CNT1_STRUC StaTx1
;
2376 TX_STA_CNT0_STRUC TxStaCnt0
;
2378 unsigned long TxRetransmit
= 0, TxSuccess
= 0, TxFailCount
= 0;
2379 struct rt_mac_table_entry
*pEntry
;
2382 pAd
->StaCfg
.StaQuickResponeForRateUpTimerRunning
= FALSE
;
2385 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
2387 for (i
= 1; i
< MAX_LEN_OF_MAC_TABLE
; i
++) {
2388 pEntry
= &pAd
->MacTab
.Content
[i
];
2390 /* check if this entry need to switch rate automatically */
2391 if (RTMPCheckEntryEnableAutoRateSwitch(pAd
, pEntry
) == FALSE
)
2394 if (INFRA_ON(pAd
) && (i
== 1))
2395 Rssi
= RTMPMaxRssi(pAd
,
2396 pAd
->StaCfg
.RssiSample
.AvgRssi0
,
2397 pAd
->StaCfg
.RssiSample
.AvgRssi1
,
2398 pAd
->StaCfg
.RssiSample
.AvgRssi2
);
2400 Rssi
= RTMPMaxRssi(pAd
,
2401 pEntry
->RssiSample
.AvgRssi0
,
2402 pEntry
->RssiSample
.AvgRssi1
,
2403 pEntry
->RssiSample
.AvgRssi2
);
2405 CurrRateIdx
= pAd
->CommonCfg
.TxRateIndex
;
2407 MlmeSelectTxRateTable(pAd
, pEntry
, &pTable
, &TableSize
,
2410 /* decide the next upgrade rate and downgrade rate, if any */
2411 if ((CurrRateIdx
> 0) && (CurrRateIdx
< (TableSize
- 1))) {
2412 UpRateIdx
= CurrRateIdx
+ 1;
2413 DownRateIdx
= CurrRateIdx
- 1;
2414 } else if (CurrRateIdx
== 0) {
2415 UpRateIdx
= CurrRateIdx
+ 1;
2416 DownRateIdx
= CurrRateIdx
;
2417 } else if (CurrRateIdx
== (TableSize
- 1)) {
2418 UpRateIdx
= CurrRateIdx
;
2419 DownRateIdx
= CurrRateIdx
- 1;
2423 (struct rt_rtmp_tx_rate_switch
*) & pTable
[(CurrRateIdx
+ 1) * 5];
2425 if ((Rssi
> -65) && (pCurrTxRate
->Mode
>= MODE_HTMIX
)) {
2427 (pCurrTxRate
->TrainUp
+
2428 (pCurrTxRate
->TrainUp
>> 1));
2430 (pCurrTxRate
->TrainDown
+
2431 (pCurrTxRate
->TrainDown
>> 1));
2433 TrainUp
= pCurrTxRate
->TrainUp
;
2434 TrainDown
= pCurrTxRate
->TrainDown
;
2437 if (pAd
->MacTab
.Size
== 1) {
2438 /* Update statistic counter */
2439 RTMP_IO_READ32(pAd
, TX_STA_CNT0
, &TxStaCnt0
.word
);
2440 RTMP_IO_READ32(pAd
, TX_STA_CNT1
, &StaTx1
.word
);
2442 TxRetransmit
= StaTx1
.field
.TxRetransmit
;
2443 TxSuccess
= StaTx1
.field
.TxSuccess
;
2444 TxFailCount
= TxStaCnt0
.field
.TxFailCount
;
2445 TxTotalCnt
= TxRetransmit
+ TxSuccess
+ TxFailCount
;
2447 pAd
->RalinkCounters
.OneSecTxRetryOkCount
+=
2448 StaTx1
.field
.TxRetransmit
;
2449 pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
+=
2450 StaTx1
.field
.TxSuccess
;
2451 pAd
->RalinkCounters
.OneSecTxFailCount
+=
2452 TxStaCnt0
.field
.TxFailCount
;
2453 pAd
->WlanCounters
.TransmittedFragmentCount
.u
.LowPart
+=
2454 StaTx1
.field
.TxSuccess
;
2455 pAd
->WlanCounters
.RetryCount
.u
.LowPart
+=
2456 StaTx1
.field
.TxRetransmit
;
2457 pAd
->WlanCounters
.FailedCount
.u
.LowPart
+=
2458 TxStaCnt0
.field
.TxFailCount
;
2463 TxFailCount
) * 100) / TxTotalCnt
;
2465 TxTotalCnt
= pEntry
->OneSecTxNoRetryOkCount
+
2466 pEntry
->OneSecTxRetryOkCount
+
2467 pEntry
->OneSecTxFailCount
;
2471 ((pEntry
->OneSecTxRetryOkCount
+
2472 pEntry
->OneSecTxFailCount
) * 100) /
2477 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2478 /* (criteria copied from RT2500 for Netopia case) */
2480 if (TxTotalCnt
<= 12) {
2481 NdisZeroMemory(pAd
->DrsCounters
.TxQuality
,
2483 MAX_STEP_OF_TX_RATE_SWITCH
);
2484 NdisZeroMemory(pAd
->DrsCounters
.PER
,
2486 MAX_STEP_OF_TX_RATE_SWITCH
);
2488 if ((pAd
->DrsCounters
.LastSecTxRateChangeAction
== 1)
2489 && (CurrRateIdx
!= DownRateIdx
)) {
2490 pAd
->CommonCfg
.TxRateIndex
= DownRateIdx
;
2491 pAd
->DrsCounters
.TxQuality
[CurrRateIdx
] =
2492 DRS_TX_QUALITY_WORST_BOUND
;
2494 if ((pAd
->DrsCounters
.LastSecTxRateChangeAction
==
2495 2) && (CurrRateIdx
!= UpRateIdx
)) {
2496 pAd
->CommonCfg
.TxRateIndex
= UpRateIdx
;
2499 DBGPRINT_RAW(RT_DEBUG_TRACE
,
2500 ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2505 unsigned long OneSecTxNoRetryOKRationCount
;
2507 if (pAd
->DrsCounters
.LastTimeTxRateChangeAction
== 0)
2512 /* downgrade TX quality if PER >= Rate-Down threshold */
2513 if (TxErrorRatio
>= TrainDown
) {
2514 pAd
->DrsCounters
.TxQuality
[CurrRateIdx
] =
2515 DRS_TX_QUALITY_WORST_BOUND
;
2518 pAd
->DrsCounters
.PER
[CurrRateIdx
] =
2521 OneSecTxNoRetryOKRationCount
= (TxSuccess
* ratio
);
2523 /* perform DRS - consider TxRate Down first, then rate up. */
2524 if ((pAd
->DrsCounters
.LastSecTxRateChangeAction
== 1)
2525 && (CurrRateIdx
!= DownRateIdx
)) {
2526 if ((pAd
->DrsCounters
.LastTxOkCount
+ 2) >=
2527 OneSecTxNoRetryOKRationCount
) {
2528 pAd
->CommonCfg
.TxRateIndex
=
2531 TxQuality
[CurrRateIdx
] =
2532 DRS_TX_QUALITY_WORST_BOUND
;
2537 if ((pAd
->DrsCounters
.LastSecTxRateChangeAction
==
2538 2) && (CurrRateIdx
!= UpRateIdx
)) {
2539 if ((TxErrorRatio
>= 50)
2540 || (TxErrorRatio
>= TrainDown
)) {
2542 } else if ((pAd
->DrsCounters
.LastTxOkCount
+ 2)
2543 >= OneSecTxNoRetryOKRationCount
) {
2544 pAd
->CommonCfg
.TxRateIndex
= UpRateIdx
;
2549 /* if rate-up happen, clear all bad history of all TX rates */
2550 if (pAd
->CommonCfg
.TxRateIndex
> CurrRateIdx
) {
2551 pAd
->DrsCounters
.TxRateUpPenalty
= 0;
2552 NdisZeroMemory(pAd
->DrsCounters
.TxQuality
,
2554 MAX_STEP_OF_TX_RATE_SWITCH
);
2555 NdisZeroMemory(pAd
->DrsCounters
.PER
,
2557 MAX_STEP_OF_TX_RATE_SWITCH
);
2558 bTxRateChanged
= TRUE
;
2560 /* if rate-down happen, only clear DownRate's bad history */
2561 else if (pAd
->CommonCfg
.TxRateIndex
< CurrRateIdx
) {
2562 DBGPRINT_RAW(RT_DEBUG_TRACE
,
2563 ("QuickDRS: --TX rate from %d to %d \n",
2564 CurrRateIdx
, pAd
->CommonCfg
.TxRateIndex
));
2566 pAd
->DrsCounters
.TxRateUpPenalty
= 0; /* no penalty */
2567 pAd
->DrsCounters
.TxQuality
[pAd
->CommonCfg
.TxRateIndex
] =
2569 pAd
->DrsCounters
.PER
[pAd
->CommonCfg
.TxRateIndex
] = 0;
2570 bTxRateChanged
= TRUE
;
2572 bTxRateChanged
= FALSE
;
2576 (struct rt_rtmp_tx_rate_switch
*) &
2577 pTable
[(pAd
->CommonCfg
.TxRateIndex
+ 1) * 5];
2578 if (bTxRateChanged
&& pNextTxRate
) {
2579 MlmeSetTxRate(pAd
, pEntry
, pNextTxRate
);
2585 ==========================================================================
2587 This routine is executed periodically inside MlmePeriodicExec() after
2588 association with an AP.
2589 It checks if StaCfg.Psm is consistent with user policy (recorded in
2590 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2591 there're some conditions to consider:
2592 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2593 the time when Mibss==TRUE
2594 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2595 if outgoing traffic available in TxRing or MgmtRing.
2597 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2599 IRQL = DISPATCH_LEVEL
2601 ==========================================================================
2603 void MlmeCheckPsmChange(struct rt_rtmp_adapter
*pAd
, unsigned long Now32
)
2605 unsigned long PowerMode
;
2608 /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */
2609 /* 2. user wants either MAX_PSP or FAST_PSP */
2610 /* 3. but current psm is not in PWR_SAVE */
2611 /* 4. CNTL state machine is not doing SCANning */
2612 /* 5. no TX SUCCESS event for the past 1-sec period */
2613 PowerMode
= pAd
->StaCfg
.WindowsPowerMode
;
2615 if (INFRA_ON(pAd
) &&
2616 (PowerMode
!= Ndis802_11PowerModeCAM
) &&
2617 (pAd
->StaCfg
.Psm
== PWR_ACTIVE
) &&
2618 /* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */
2619 (pAd
->Mlme
.CntlMachine
.CurrState
== CNTL_IDLE
) &&
2620 RTMP_TEST_PSFLAG(pAd
, fRTMP_PS_CAN_GO_SLEEP
)
2622 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2623 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2625 NdisGetSystemUpTime(&pAd
->Mlme
.LastSendNULLpsmTime
);
2626 pAd
->RalinkCounters
.RxCountSinceLastNULL
= 0;
2627 RTMP_SET_PSM_BIT(pAd
, PWR_SAVE
);
2629 (pAd
->CommonCfg
.bAPSDCapable
2630 && pAd
->CommonCfg
.APEdcaParm
.bAPSDCapable
)) {
2631 RTMPSendNullFrame(pAd
, pAd
->CommonCfg
.TxRate
, FALSE
);
2633 RTMPSendNullFrame(pAd
, pAd
->CommonCfg
.TxRate
, TRUE
);
2638 /* IRQL = PASSIVE_LEVEL */
2639 /* IRQL = DISPATCH_LEVEL */
2640 void MlmeSetPsmBit(struct rt_rtmp_adapter
*pAd
, u16 psm
)
2642 AUTO_RSP_CFG_STRUC csr4
;
2644 pAd
->StaCfg
.Psm
= psm
;
2645 RTMP_IO_READ32(pAd
, AUTO_RSP_CFG
, &csr4
.word
);
2646 csr4
.field
.AckCtsPsmBit
= (psm
== PWR_SAVE
) ? 1 : 0;
2647 RTMP_IO_WRITE32(pAd
, AUTO_RSP_CFG
, csr4
.word
);
2649 DBGPRINT(RT_DEBUG_TRACE
, ("MlmeSetPsmBit = %d\n", psm
));
2653 ==========================================================================
2655 This routine calculates TxPER, RxPER of the past N-sec period. And
2656 according to the calculation result, ChannelQuality is calculated here
2657 to decide if current AP is still doing the job.
2659 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2661 StaCfg.ChannelQuality - 0..100
2663 IRQL = DISPATCH_LEVEL
2665 NOTE: This routine decide channle quality based on RX CRC error ratio.
2666 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2667 is performed right before this routine, so that this routine can decide
2668 channel quality based on the most up-to-date information
2669 ==========================================================================
2671 void MlmeCalculateChannelQuality(struct rt_rtmp_adapter
*pAd
,
2672 struct rt_mac_table_entry
*pMacEntry
, unsigned long Now32
)
2674 unsigned long TxOkCnt
, TxCnt
, TxPER
, TxPRR
;
2675 unsigned long RxCnt
, RxPER
;
2678 struct rt_rssi_sample
*pRssiSample
= NULL
;
2679 u32 OneSecTxNoRetryOkCount
= 0;
2680 u32 OneSecTxRetryOkCount
= 0;
2681 u32 OneSecTxFailCount
= 0;
2682 u32 OneSecRxOkCnt
= 0;
2683 u32 OneSecRxFcsErrCnt
= 0;
2684 unsigned long ChannelQuality
= 0; /* 0..100, Channel Quality Indication for Roaming */
2685 unsigned long BeaconLostTime
= pAd
->StaCfg
.BeaconLostTime
;
2687 if (pAd
->OpMode
== OPMODE_STA
) {
2688 pRssiSample
= &pAd
->StaCfg
.RssiSample
;
2689 OneSecTxNoRetryOkCount
=
2690 pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
;
2691 OneSecTxRetryOkCount
= pAd
->RalinkCounters
.OneSecTxRetryOkCount
;
2692 OneSecTxFailCount
= pAd
->RalinkCounters
.OneSecTxFailCount
;
2693 OneSecRxOkCnt
= pAd
->RalinkCounters
.OneSecRxOkCnt
;
2694 OneSecRxFcsErrCnt
= pAd
->RalinkCounters
.OneSecRxFcsErrCnt
;
2697 MaxRssi
= RTMPMaxRssi(pAd
, pRssiSample
->LastRssi0
,
2698 pRssiSample
->LastRssi1
, pRssiSample
->LastRssi2
);
2701 /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */
2703 TxOkCnt
= OneSecTxNoRetryOkCount
+ OneSecTxRetryOkCount
;
2704 TxCnt
= TxOkCnt
+ OneSecTxFailCount
;
2709 TxPER
= (OneSecTxFailCount
* 100) / TxCnt
;
2710 TxPRR
= ((TxCnt
- OneSecTxNoRetryOkCount
) * 100) / TxCnt
;
2714 /* calculate RX PER - don't take RxPER into consideration if too few sample */
2716 RxCnt
= OneSecRxOkCnt
+ OneSecRxFcsErrCnt
;
2720 RxPER
= (OneSecRxFcsErrCnt
* 100) / RxCnt
;
2723 /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */
2725 if ((pAd
->OpMode
== OPMODE_STA
) && INFRA_ON(pAd
) && (OneSecTxNoRetryOkCount
< 2) && /* no heavy traffic */
2726 ((pAd
->StaCfg
.LastBeaconRxTime
+ BeaconLostTime
) < Now32
)) {
2727 DBGPRINT(RT_DEBUG_TRACE
,
2728 ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2729 BeaconLostTime
, TxOkCnt
));
2732 /* Normalize Rssi */
2735 else if (MaxRssi
< -90)
2738 NorRssi
= (MaxRssi
+ 90) * 2;
2740 /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */
2741 ChannelQuality
= (RSSI_WEIGHTING
* NorRssi
+
2742 TX_WEIGHTING
* (100 - TxPRR
) +
2743 RX_WEIGHTING
* (100 - RxPER
)) / 100;
2746 if (pAd
->OpMode
== OPMODE_STA
)
2747 pAd
->Mlme
.ChannelQuality
=
2748 (ChannelQuality
> 100) ? 100 : ChannelQuality
;
2752 /* IRQL = DISPATCH_LEVEL */
2753 void MlmeSetTxPreamble(struct rt_rtmp_adapter
*pAd
, u16 TxPreamble
)
2755 AUTO_RSP_CFG_STRUC csr4
;
2758 /* Always use Long preamble before verifiation short preamble functionality works well. */
2759 /* Todo: remove the following line if short preamble functionality works */
2761 /*TxPreamble = Rt802_11PreambleLong; */
2763 RTMP_IO_READ32(pAd
, AUTO_RSP_CFG
, &csr4
.word
);
2764 if (TxPreamble
== Rt802_11PreambleLong
) {
2765 DBGPRINT(RT_DEBUG_TRACE
,
2766 ("MlmeSetTxPreamble (= long PREAMBLE)\n"));
2767 OPSTATUS_CLEAR_FLAG(pAd
, fOP_STATUS_SHORT_PREAMBLE_INUSED
);
2768 csr4
.field
.AutoResponderPreamble
= 0;
2770 /* NOTE: 1Mbps should always use long preamble */
2771 DBGPRINT(RT_DEBUG_TRACE
,
2772 ("MlmeSetTxPreamble (= short PREAMBLE)\n"));
2773 OPSTATUS_SET_FLAG(pAd
, fOP_STATUS_SHORT_PREAMBLE_INUSED
);
2774 csr4
.field
.AutoResponderPreamble
= 1;
2777 RTMP_IO_WRITE32(pAd
, AUTO_RSP_CFG
, csr4
.word
);
2781 ==========================================================================
2783 Update basic rate bitmap
2784 ==========================================================================
2787 void UpdateBasicRateBitmap(struct rt_rtmp_adapter
*pAdapter
)
2790 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2791 u8 rate
[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2792 u8
*sup_p
= pAdapter
->CommonCfg
.SupRate
;
2793 u8
*ext_p
= pAdapter
->CommonCfg
.ExtRate
;
2794 unsigned long 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 */
2802 if (pAdapter
->CommonCfg
.BasicRateBitmap
> 4095) {
2803 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2807 for (i
= 0; i
< MAX_LEN_OF_SUPPORTED_RATES
; i
++) {
2812 for (i
= 0; i
< MAX_LEN_OF_SUPPORTED_RATES
; i
++) {
2813 if (bitmap
& (1 << i
)) {
2814 for (j
= 0; j
< MAX_LEN_OF_SUPPORTED_RATES
; j
++) {
2815 if (sup_p
[j
] == rate
[i
])
2820 for (j
= 0; j
< MAX_LEN_OF_SUPPORTED_RATES
; j
++) {
2821 if (ext_p
[j
] == rate
[i
])
2827 } /* End of UpdateBasicRateBitmap */
2829 /* IRQL = PASSIVE_LEVEL */
2830 /* IRQL = DISPATCH_LEVEL */
2831 /* bLinkUp is to identify the inital link speed. */
2832 /* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */
2833 void MlmeUpdateTxRates(struct rt_rtmp_adapter
*pAd
, IN BOOLEAN bLinkUp
, u8 apidx
)
2836 u8 Rate
= RATE_6
, MaxDesire
= RATE_1
, MaxSupport
= RATE_1
;
2837 u8 MinSupport
= RATE_54
;
2838 unsigned long BasicRateBitmap
= 0;
2839 u8 CurrBasicRate
= RATE_1
;
2840 u8
*pSupRate
, SupRateLen
, *pExtRate
, ExtRateLen
;
2841 PHTTRANSMIT_SETTING pHtPhy
= NULL
;
2842 PHTTRANSMIT_SETTING pMaxHtPhy
= NULL
;
2843 PHTTRANSMIT_SETTING pMinHtPhy
= NULL
;
2844 BOOLEAN
*auto_rate_cur_p
;
2845 u8 HtMcs
= MCS_AUTO
;
2847 /* find max desired rate */
2848 UpdateBasicRateBitmap(pAd
);
2851 auto_rate_cur_p
= NULL
;
2852 for (i
= 0; i
< MAX_LEN_OF_SUPPORTED_RATES
; i
++) {
2853 switch (pAd
->CommonCfg
.DesireRate
[i
] & 0x7f) {
2902 /*default: Rate = RATE_1; break; */
2904 if (MaxDesire
< Rate
)
2908 /*=========================================================================== */
2909 /*=========================================================================== */
2911 pHtPhy
= &pAd
->StaCfg
.HTPhyMode
;
2912 pMaxHtPhy
= &pAd
->StaCfg
.MaxHTPhyMode
;
2913 pMinHtPhy
= &pAd
->StaCfg
.MinHTPhyMode
;
2915 auto_rate_cur_p
= &pAd
->StaCfg
.bAutoTxRateSwitch
;
2916 HtMcs
= pAd
->StaCfg
.DesiredTransmitSetting
.field
.MCS
;
2918 if ((pAd
->StaCfg
.BssType
== BSS_ADHOC
) &&
2919 (pAd
->CommonCfg
.PhyMode
== PHY_11B
) &&
2920 (MaxDesire
> RATE_11
)) {
2921 MaxDesire
= RATE_11
;
2925 pAd
->CommonCfg
.MaxDesiredRate
= MaxDesire
;
2926 pMinHtPhy
->word
= 0;
2927 pMaxHtPhy
->word
= 0;
2930 /* Auto rate switching is enabled only if more than one DESIRED RATES are */
2931 /* specified; otherwise disabled */
2933 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2934 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
2935 *auto_rate_cur_p
= FALSE
;
2937 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2938 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
2939 *auto_rate_cur_p
= TRUE
;
2942 if (HtMcs
!= MCS_AUTO
) {
2943 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2944 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
2945 *auto_rate_cur_p
= FALSE
;
2947 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2948 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
2949 *auto_rate_cur_p
= TRUE
;
2952 if ((ADHOC_ON(pAd
) || INFRA_ON(pAd
)) && (pAd
->OpMode
== OPMODE_STA
)) {
2953 pSupRate
= &pAd
->StaActive
.SupRate
[0];
2954 pExtRate
= &pAd
->StaActive
.ExtRate
[0];
2955 SupRateLen
= pAd
->StaActive
.SupRateLen
;
2956 ExtRateLen
= pAd
->StaActive
.ExtRateLen
;
2958 pSupRate
= &pAd
->CommonCfg
.SupRate
[0];
2959 pExtRate
= &pAd
->CommonCfg
.ExtRate
[0];
2960 SupRateLen
= pAd
->CommonCfg
.SupRateLen
;
2961 ExtRateLen
= pAd
->CommonCfg
.ExtRateLen
;
2964 /* find max supported rate */
2965 for (i
= 0; i
< SupRateLen
; i
++) {
2966 switch (pSupRate
[i
] & 0x7f) {
2969 if (pSupRate
[i
] & 0x80)
2970 BasicRateBitmap
|= 0x0001;
2974 if (pSupRate
[i
] & 0x80)
2975 BasicRateBitmap
|= 0x0002;
2979 if (pSupRate
[i
] & 0x80)
2980 BasicRateBitmap
|= 0x0004;
2984 if (pSupRate
[i
] & 0x80)
2985 BasicRateBitmap
|= 0x0008;
2988 Rate
= RATE_6
; /*if (pSupRate[i] & 0x80) */
2989 BasicRateBitmap
|= 0x0010;
2993 if (pSupRate
[i
] & 0x80)
2994 BasicRateBitmap
|= 0x0020;
2997 Rate
= RATE_12
; /*if (pSupRate[i] & 0x80) */
2998 BasicRateBitmap
|= 0x0040;
3002 if (pSupRate
[i
] & 0x80)
3003 BasicRateBitmap
|= 0x0080;
3006 Rate
= RATE_24
; /*if (pSupRate[i] & 0x80) */
3007 BasicRateBitmap
|= 0x0100;
3011 if (pSupRate
[i
] & 0x80)
3012 BasicRateBitmap
|= 0x0200;
3016 if (pSupRate
[i
] & 0x80)
3017 BasicRateBitmap
|= 0x0400;
3021 if (pSupRate
[i
] & 0x80)
3022 BasicRateBitmap
|= 0x0800;
3028 if (MaxSupport
< Rate
)
3031 if (MinSupport
> Rate
)
3035 for (i
= 0; i
< ExtRateLen
; i
++) {
3036 switch (pExtRate
[i
] & 0x7f) {
3039 if (pExtRate
[i
] & 0x80)
3040 BasicRateBitmap
|= 0x0001;
3044 if (pExtRate
[i
] & 0x80)
3045 BasicRateBitmap
|= 0x0002;
3049 if (pExtRate
[i
] & 0x80)
3050 BasicRateBitmap
|= 0x0004;
3054 if (pExtRate
[i
] & 0x80)
3055 BasicRateBitmap
|= 0x0008;
3058 Rate
= RATE_6
; /*if (pExtRate[i] & 0x80) */
3059 BasicRateBitmap
|= 0x0010;
3063 if (pExtRate
[i
] & 0x80)
3064 BasicRateBitmap
|= 0x0020;
3067 Rate
= RATE_12
; /*if (pExtRate[i] & 0x80) */
3068 BasicRateBitmap
|= 0x0040;
3072 if (pExtRate
[i
] & 0x80)
3073 BasicRateBitmap
|= 0x0080;
3076 Rate
= RATE_24
; /*if (pExtRate[i] & 0x80) */
3077 BasicRateBitmap
|= 0x0100;
3081 if (pExtRate
[i
] & 0x80)
3082 BasicRateBitmap
|= 0x0200;
3086 if (pExtRate
[i
] & 0x80)
3087 BasicRateBitmap
|= 0x0400;
3091 if (pExtRate
[i
] & 0x80)
3092 BasicRateBitmap
|= 0x0800;
3098 if (MaxSupport
< Rate
)
3101 if (MinSupport
> Rate
)
3105 RTMP_IO_WRITE32(pAd
, LEGACY_BASIC_RATE
, BasicRateBitmap
);
3108 /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */
3110 /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */
3111 /* the DURATION field of outgoing uniicast DATA/MGMT frame */
3112 for (i
= 0; i
< MAX_LEN_OF_SUPPORTED_RATES
; i
++) {
3113 if (BasicRateBitmap
& (0x01 << i
))
3114 CurrBasicRate
= (u8
)i
;
3115 pAd
->CommonCfg
.ExpectedACKRate
[i
] = CurrBasicRate
;
3118 DBGPRINT(RT_DEBUG_TRACE
,
3119 ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3120 RateIdToMbps
[MaxSupport
], RateIdToMbps
[MaxDesire
]));
3121 /* max tx rate = min {max desire rate, max supported rate} */
3122 if (MaxSupport
< MaxDesire
)
3123 pAd
->CommonCfg
.MaxTxRate
= MaxSupport
;
3125 pAd
->CommonCfg
.MaxTxRate
= MaxDesire
;
3127 pAd
->CommonCfg
.MinTxRate
= MinSupport
;
3128 /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */
3129 /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */
3130 /* on average RSSI */
3131 /* 1. RSSI >= -70db, start at 54 Mbps (short distance) */
3132 /* 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */
3133 /* 3. -75 > RSSI, start at 11 Mbps (long distance) */
3134 if (*auto_rate_cur_p
) {
3137 dbm
= pAd
->StaCfg
.RssiSample
.AvgRssi0
- pAd
->BbpRssiToDbmDelta
;
3139 if (bLinkUp
== TRUE
)
3140 pAd
->CommonCfg
.TxRate
= RATE_24
;
3142 pAd
->CommonCfg
.TxRate
= pAd
->CommonCfg
.MaxTxRate
;
3145 pAd
->CommonCfg
.TxRate
= RATE_11
;
3147 pAd
->CommonCfg
.TxRate
= RATE_24
;
3149 /* should never exceed MaxTxRate (consider 11B-only mode) */
3150 if (pAd
->CommonCfg
.TxRate
> pAd
->CommonCfg
.MaxTxRate
)
3151 pAd
->CommonCfg
.TxRate
= pAd
->CommonCfg
.MaxTxRate
;
3153 pAd
->CommonCfg
.TxRateIndex
= 0;
3155 pAd
->CommonCfg
.TxRate
= pAd
->CommonCfg
.MaxTxRate
;
3157 (pAd
->CommonCfg
.MaxTxRate
>
3158 3) ? (pAd
->CommonCfg
.MaxTxRate
-
3159 4) : pAd
->CommonCfg
.MaxTxRate
;
3160 pHtPhy
->field
.MODE
=
3161 (pAd
->CommonCfg
.MaxTxRate
> 3) ? MODE_OFDM
: MODE_CCK
;
3163 pAd
->MacTab
.Content
[BSSID_WCID
].HTPhyMode
.field
.STBC
=
3165 pAd
->MacTab
.Content
[BSSID_WCID
].HTPhyMode
.field
.ShortGI
=
3166 pHtPhy
->field
.ShortGI
;
3167 pAd
->MacTab
.Content
[BSSID_WCID
].HTPhyMode
.field
.MCS
=
3169 pAd
->MacTab
.Content
[BSSID_WCID
].HTPhyMode
.field
.MODE
=
3173 if (pAd
->CommonCfg
.TxRate
<= RATE_11
) {
3174 pMaxHtPhy
->field
.MODE
= MODE_CCK
;
3175 pMaxHtPhy
->field
.MCS
= pAd
->CommonCfg
.TxRate
;
3176 pMinHtPhy
->field
.MCS
= pAd
->CommonCfg
.MinTxRate
;
3178 pMaxHtPhy
->field
.MODE
= MODE_OFDM
;
3179 pMaxHtPhy
->field
.MCS
= OfdmRateToRxwiMCS
[pAd
->CommonCfg
.TxRate
];
3180 if (pAd
->CommonCfg
.MinTxRate
>= RATE_6
3181 && (pAd
->CommonCfg
.MinTxRate
<= RATE_54
)) {
3182 pMinHtPhy
->field
.MCS
=
3183 OfdmRateToRxwiMCS
[pAd
->CommonCfg
.MinTxRate
];
3185 pMinHtPhy
->field
.MCS
= pAd
->CommonCfg
.MinTxRate
;
3189 pHtPhy
->word
= (pMaxHtPhy
->word
);
3190 if (bLinkUp
&& (pAd
->OpMode
== OPMODE_STA
)) {
3191 pAd
->MacTab
.Content
[BSSID_WCID
].HTPhyMode
.word
= pHtPhy
->word
;
3192 pAd
->MacTab
.Content
[BSSID_WCID
].MaxHTPhyMode
.word
=
3194 pAd
->MacTab
.Content
[BSSID_WCID
].MinHTPhyMode
.word
=
3197 switch (pAd
->CommonCfg
.PhyMode
) {
3198 case PHY_11BG_MIXED
:
3200 case PHY_11BGN_MIXED
:
3201 pAd
->CommonCfg
.MlmeRate
= RATE_1
;
3202 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
= MODE_CCK
;
3203 pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
= RATE_1
;
3205 /*#ifdef WIFI_TEST */
3206 pAd
->CommonCfg
.RtsRate
= RATE_11
;
3208 /* pAd->CommonCfg.RtsRate = RATE_1; */
3213 case PHY_11AGN_MIXED
:
3214 case PHY_11GN_MIXED
:
3216 case PHY_11AN_MIXED
:
3218 pAd
->CommonCfg
.MlmeRate
= RATE_6
;
3219 pAd
->CommonCfg
.RtsRate
= RATE_6
;
3220 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
= MODE_OFDM
;
3221 pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
=
3222 OfdmRateToRxwiMCS
[pAd
->CommonCfg
.MlmeRate
];
3224 case PHY_11ABG_MIXED
:
3225 case PHY_11ABGN_MIXED
:
3226 if (pAd
->CommonCfg
.Channel
<= 14) {
3227 pAd
->CommonCfg
.MlmeRate
= RATE_1
;
3228 pAd
->CommonCfg
.RtsRate
= RATE_1
;
3229 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
=
3231 pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
= RATE_1
;
3233 pAd
->CommonCfg
.MlmeRate
= RATE_6
;
3234 pAd
->CommonCfg
.RtsRate
= RATE_6
;
3235 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
=
3237 pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
=
3238 OfdmRateToRxwiMCS
[pAd
->CommonCfg
.MlmeRate
];
3241 default: /* error */
3242 pAd
->CommonCfg
.MlmeRate
= RATE_6
;
3243 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
= MODE_OFDM
;
3244 pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
=
3245 OfdmRateToRxwiMCS
[pAd
->CommonCfg
.MlmeRate
];
3246 pAd
->CommonCfg
.RtsRate
= RATE_1
;
3250 /* Keep Basic Mlme Rate. */
3252 pAd
->MacTab
.Content
[MCAST_WCID
].HTPhyMode
.word
=
3253 pAd
->CommonCfg
.MlmeTransmit
.word
;
3254 if (pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
== MODE_OFDM
)
3255 pAd
->MacTab
.Content
[MCAST_WCID
].HTPhyMode
.field
.MCS
=
3256 OfdmRateToRxwiMCS
[RATE_24
];
3258 pAd
->MacTab
.Content
[MCAST_WCID
].HTPhyMode
.field
.MCS
=
3260 pAd
->CommonCfg
.BasicMlmeRate
= pAd
->CommonCfg
.MlmeRate
;
3263 DBGPRINT(RT_DEBUG_TRACE
,
3264 (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3265 RateIdToMbps
[MaxDesire
], RateIdToMbps
[MaxSupport
],
3266 RateIdToMbps
[pAd
->CommonCfg
.MaxTxRate
],
3267 RateIdToMbps
[pAd
->CommonCfg
.MinTxRate
],
3268 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3270 DBGPRINT(RT_DEBUG_TRACE
,
3271 (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3272 RateIdToMbps
[pAd
->CommonCfg
.TxRate
],
3273 RateIdToMbps
[pAd
->CommonCfg
.RtsRate
], BasicRateBitmap
));
3274 DBGPRINT(RT_DEBUG_TRACE
,
3275 ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3276 pAd
->CommonCfg
.MlmeTransmit
.word
,
3277 pAd
->MacTab
.Content
[BSSID_WCID
].MinHTPhyMode
.word
,
3278 pAd
->MacTab
.Content
[BSSID_WCID
].MaxHTPhyMode
.word
,
3279 pAd
->MacTab
.Content
[BSSID_WCID
].HTPhyMode
.word
));
3283 ==========================================================================
3285 This function update HT Rate setting.
3286 Input Wcid value is valid for 2 case :
3287 1. it's used for Station in infra mode that copy AP rate to Mactable.
3288 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3290 IRQL = DISPATCH_LEVEL
3292 ==========================================================================
3294 void MlmeUpdateHtTxRates(struct rt_rtmp_adapter
*pAd
, u8 apidx
)
3296 u8 StbcMcs
; /*j, StbcMcs, bitmask; */
3298 struct rt_ht_capability
*pRtHtCap
= NULL
;
3299 struct rt_ht_phy_info
*pActiveHtPhy
= NULL
;
3300 unsigned long BasicMCS
;
3302 struct rt_ht_phy_info
*pDesireHtPhy
= NULL
;
3303 PHTTRANSMIT_SETTING pHtPhy
= NULL
;
3304 PHTTRANSMIT_SETTING pMaxHtPhy
= NULL
;
3305 PHTTRANSMIT_SETTING pMinHtPhy
= NULL
;
3306 BOOLEAN
*auto_rate_cur_p
;
3308 DBGPRINT(RT_DEBUG_TRACE
, ("MlmeUpdateHtTxRates===> \n"));
3310 auto_rate_cur_p
= NULL
;
3313 pDesireHtPhy
= &pAd
->StaCfg
.DesiredHtPhyInfo
;
3314 pActiveHtPhy
= &pAd
->StaCfg
.DesiredHtPhyInfo
;
3315 pHtPhy
= &pAd
->StaCfg
.HTPhyMode
;
3316 pMaxHtPhy
= &pAd
->StaCfg
.MaxHTPhyMode
;
3317 pMinHtPhy
= &pAd
->StaCfg
.MinHTPhyMode
;
3319 auto_rate_cur_p
= &pAd
->StaCfg
.bAutoTxRateSwitch
;
3322 if ((ADHOC_ON(pAd
) || INFRA_ON(pAd
)) && (pAd
->OpMode
== OPMODE_STA
)) {
3323 if (pAd
->StaActive
.SupportedPhyInfo
.bHtEnable
== FALSE
)
3326 pRtHtCap
= &pAd
->StaActive
.SupportedHtPhy
;
3327 pActiveHtPhy
= &pAd
->StaActive
.SupportedPhyInfo
;
3328 StbcMcs
= (u8
)pAd
->MlmeAux
.AddHtInfo
.AddHtInfo3
.StbcMcs
;
3330 pAd
->MlmeAux
.AddHtInfo
.MCSSet
[0] +
3331 (pAd
->MlmeAux
.AddHtInfo
.MCSSet
[1] << 8) + (StbcMcs
<< 16);
3332 if ((pAd
->CommonCfg
.DesiredHtPhy
.TxSTBC
) && (pRtHtCap
->RxSTBC
)
3333 && (pAd
->Antenna
.field
.TxPath
== 2))
3334 pMaxHtPhy
->field
.STBC
= STBC_USE
;
3336 pMaxHtPhy
->field
.STBC
= STBC_NONE
;
3338 if (pDesireHtPhy
->bHtEnable
== FALSE
)
3341 pRtHtCap
= &pAd
->CommonCfg
.DesiredHtPhy
;
3342 StbcMcs
= (u8
)pAd
->CommonCfg
.AddHTInfo
.AddHtInfo3
.StbcMcs
;
3344 pAd
->CommonCfg
.AddHTInfo
.MCSSet
[0] +
3345 (pAd
->CommonCfg
.AddHTInfo
.MCSSet
[1] << 8) + (StbcMcs
<< 16);
3346 if ((pAd
->CommonCfg
.DesiredHtPhy
.TxSTBC
) && (pRtHtCap
->RxSTBC
)
3347 && (pAd
->Antenna
.field
.TxPath
== 2))
3348 pMaxHtPhy
->field
.STBC
= STBC_USE
;
3350 pMaxHtPhy
->field
.STBC
= STBC_NONE
;
3353 /* Decide MAX ht rate. */
3354 if ((pRtHtCap
->GF
) && (pAd
->CommonCfg
.DesiredHtPhy
.GF
))
3355 pMaxHtPhy
->field
.MODE
= MODE_HTGREENFIELD
;
3357 pMaxHtPhy
->field
.MODE
= MODE_HTMIX
;
3359 if ((pAd
->CommonCfg
.DesiredHtPhy
.ChannelWidth
)
3360 && (pRtHtCap
->ChannelWidth
))
3361 pMaxHtPhy
->field
.BW
= BW_40
;
3363 pMaxHtPhy
->field
.BW
= BW_20
;
3365 if (pMaxHtPhy
->field
.BW
== BW_20
)
3366 pMaxHtPhy
->field
.ShortGI
=
3367 (pAd
->CommonCfg
.DesiredHtPhy
.ShortGIfor20
& pRtHtCap
->
3370 pMaxHtPhy
->field
.ShortGI
=
3371 (pAd
->CommonCfg
.DesiredHtPhy
.ShortGIfor40
& pRtHtCap
->
3374 if (pDesireHtPhy
->MCSSet
[4] != 0) {
3375 pMaxHtPhy
->field
.MCS
= 32;
3378 for (i
= 23; i
>= 0; i
--) /* 3*3 */
3381 bitmask
= (1 << (i
- (j
* 8)));
3383 if ((pActiveHtPhy
->MCSSet
[j
] & bitmask
)
3384 && (pDesireHtPhy
->MCSSet
[j
] & bitmask
)) {
3385 pMaxHtPhy
->field
.MCS
= i
;
3393 /* Copy MIN ht rate. rt2860??? */
3394 pMinHtPhy
->field
.BW
= BW_20
;
3395 pMinHtPhy
->field
.MCS
= 0;
3396 pMinHtPhy
->field
.STBC
= 0;
3397 pMinHtPhy
->field
.ShortGI
= 0;
3398 /*If STA assigns fixed rate. update to fixed here. */
3399 if ((pAd
->OpMode
== OPMODE_STA
) && (pDesireHtPhy
->MCSSet
[0] != 0xff)) {
3400 if (pDesireHtPhy
->MCSSet
[4] != 0) {
3401 pMaxHtPhy
->field
.MCS
= 32;
3402 pMinHtPhy
->field
.MCS
= 32;
3403 DBGPRINT(RT_DEBUG_TRACE
,
3404 ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3405 pMinHtPhy
->field
.MCS
));
3408 for (i
= 23; (char)i
>= 0; i
--) /* 3*3 */
3411 bitmask
= (1 << (i
- (j
* 8)));
3412 if ((pDesireHtPhy
->MCSSet
[j
] & bitmask
)
3413 && (pActiveHtPhy
->MCSSet
[j
] & bitmask
)) {
3414 pMaxHtPhy
->field
.MCS
= i
;
3415 pMinHtPhy
->field
.MCS
= i
;
3423 /* Decide ht rate */
3424 pHtPhy
->field
.STBC
= pMaxHtPhy
->field
.STBC
;
3425 pHtPhy
->field
.BW
= pMaxHtPhy
->field
.BW
;
3426 pHtPhy
->field
.MODE
= pMaxHtPhy
->field
.MODE
;
3427 pHtPhy
->field
.MCS
= pMaxHtPhy
->field
.MCS
;
3428 pHtPhy
->field
.ShortGI
= pMaxHtPhy
->field
.ShortGI
;
3430 /* use default now. rt2860 */
3431 if (pDesireHtPhy
->MCSSet
[0] != 0xff)
3432 *auto_rate_cur_p
= FALSE
;
3434 *auto_rate_cur_p
= TRUE
;
3436 DBGPRINT(RT_DEBUG_TRACE
,
3437 (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n",
3438 pAd
->CommonCfg
.DesiredHtPhy
.AmsduSize
));
3439 DBGPRINT(RT_DEBUG_TRACE
,
3440 ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n",
3441 pActiveHtPhy
->MCSSet
[0], pHtPhy
->field
.MCS
, pHtPhy
->field
.BW
,
3442 pHtPhy
->field
.ShortGI
, pHtPhy
->field
.MODE
));
3443 DBGPRINT(RT_DEBUG_TRACE
, ("MlmeUpdateHtTxRates<=== \n"));
3446 void BATableInit(struct rt_rtmp_adapter
*pAd
, struct rt_ba_table
*Tab
)
3450 Tab
->numAsOriginator
= 0;
3451 Tab
->numAsRecipient
= 0;
3452 Tab
->numDoneOriginator
= 0;
3453 NdisAllocateSpinLock(&pAd
->BATabLock
);
3454 for (i
= 0; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++) {
3455 Tab
->BARecEntry
[i
].REC_BA_Status
= Recipient_NONE
;
3456 NdisAllocateSpinLock(&(Tab
->BARecEntry
[i
].RxReRingLock
));
3458 for (i
= 0; i
< MAX_LEN_OF_BA_ORI_TABLE
; i
++) {
3459 Tab
->BAOriEntry
[i
].ORI_BA_Status
= Originator_NONE
;
3463 /* IRQL = DISPATCH_LEVEL */
3464 void MlmeRadioOff(struct rt_rtmp_adapter
*pAd
)
3466 RTMP_MLME_RADIO_OFF(pAd
);
3469 /* IRQL = DISPATCH_LEVEL */
3470 void MlmeRadioOn(struct rt_rtmp_adapter
*pAd
)
3472 RTMP_MLME_RADIO_ON(pAd
);
3475 /* =========================================================================================== */
3477 /* =========================================================================================== */
3479 /*! \brief initialize BSS table
3480 * \param p_tab pointer to the table
3485 IRQL = PASSIVE_LEVEL
3486 IRQL = DISPATCH_LEVEL
3489 void BssTableInit(struct rt_bss_table
*Tab
)
3494 Tab
->BssOverlapNr
= 0;
3495 for (i
= 0; i
< MAX_LEN_OF_BSS_TABLE
; i
++) {
3496 NdisZeroMemory(&Tab
->BssEntry
[i
], sizeof(struct rt_bss_entry
));
3497 Tab
->BssEntry
[i
].Rssi
= -127; /* initial the rssi as a minimum value */
3501 /*! \brief search the BSS table by SSID
3502 * \param p_tab pointer to the bss table
3503 * \param ssid SSID string
3504 * \return index of the table, BSS_NOT_FOUND if not in the table
3507 * \note search by sequential search
3509 IRQL = DISPATCH_LEVEL
3512 unsigned long BssTableSearch(struct rt_bss_table
*Tab
, u8
*pBssid
, u8 Channel
)
3516 for (i
= 0; i
< Tab
->BssNr
; i
++) {
3518 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3519 /* We should distinguish this case. */
3521 if ((((Tab
->BssEntry
[i
].Channel
<= 14) && (Channel
<= 14)) ||
3522 ((Tab
->BssEntry
[i
].Channel
> 14) && (Channel
> 14))) &&
3523 MAC_ADDR_EQUAL(Tab
->BssEntry
[i
].Bssid
, pBssid
)) {
3527 return (unsigned long)BSS_NOT_FOUND
;
3530 unsigned long BssSsidTableSearch(struct rt_bss_table
*Tab
,
3532 u8
*pSsid
, u8 SsidLen
, u8 Channel
)
3536 for (i
= 0; i
< Tab
->BssNr
; i
++) {
3538 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3539 /* We should distinguish this case. */
3541 if ((((Tab
->BssEntry
[i
].Channel
<= 14) && (Channel
<= 14)) ||
3542 ((Tab
->BssEntry
[i
].Channel
> 14) && (Channel
> 14))) &&
3543 MAC_ADDR_EQUAL(Tab
->BssEntry
[i
].Bssid
, pBssid
) &&
3544 SSID_EQUAL(pSsid
, SsidLen
, Tab
->BssEntry
[i
].Ssid
,
3545 Tab
->BssEntry
[i
].SsidLen
)) {
3549 return (unsigned long)BSS_NOT_FOUND
;
3552 unsigned long BssTableSearchWithSSID(struct rt_bss_table
*Tab
,
3555 u8 SsidLen
, u8 Channel
)
3559 for (i
= 0; i
< Tab
->BssNr
; i
++) {
3560 if ((((Tab
->BssEntry
[i
].Channel
<= 14) && (Channel
<= 14)) ||
3561 ((Tab
->BssEntry
[i
].Channel
> 14) && (Channel
> 14))) &&
3562 MAC_ADDR_EQUAL(&(Tab
->BssEntry
[i
].Bssid
), Bssid
) &&
3564 (pSsid
, SsidLen
, Tab
->BssEntry
[i
].Ssid
,
3565 Tab
->BssEntry
[i
].SsidLen
)
3566 || (NdisEqualMemory(pSsid
, ZeroSsid
, SsidLen
))
3569 (Tab
->BssEntry
[i
].Ssid
, ZeroSsid
,
3570 Tab
->BssEntry
[i
].SsidLen
)))) {
3574 return (unsigned long)BSS_NOT_FOUND
;
3577 unsigned long BssSsidTableSearchBySSID(struct rt_bss_table
*Tab
,
3578 u8
*pSsid
, u8 SsidLen
)
3582 for (i
= 0; i
< Tab
->BssNr
; i
++) {
3584 (pSsid
, SsidLen
, Tab
->BssEntry
[i
].Ssid
,
3585 Tab
->BssEntry
[i
].SsidLen
)) {
3589 return (unsigned long)BSS_NOT_FOUND
;
3592 /* IRQL = DISPATCH_LEVEL */
3593 void BssTableDeleteEntry(struct rt_bss_table
*Tab
,
3594 u8
*pBssid
, u8 Channel
)
3598 for (i
= 0; i
< Tab
->BssNr
; i
++) {
3599 if ((Tab
->BssEntry
[i
].Channel
== Channel
) &&
3600 (MAC_ADDR_EQUAL(Tab
->BssEntry
[i
].Bssid
, pBssid
))) {
3601 for (j
= i
; j
< Tab
->BssNr
- 1; j
++) {
3602 NdisMoveMemory(&(Tab
->BssEntry
[j
]),
3603 &(Tab
->BssEntry
[j
+ 1]),
3604 sizeof(struct rt_bss_entry
));
3606 NdisZeroMemory(&(Tab
->BssEntry
[Tab
->BssNr
- 1]),
3607 sizeof(struct rt_bss_entry
));
3615 ========================================================================
3616 Routine Description:
3617 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3620 // IRQL = DISPATCH_LEVEL
3621 ========================================================================
3623 void BATableDeleteORIEntry(struct rt_rtmp_adapter
*pAd
,
3624 struct rt_ba_ori_entry
*pBAORIEntry
)
3627 if (pBAORIEntry
->ORI_BA_Status
!= Originator_NONE
) {
3628 NdisAcquireSpinLock(&pAd
->BATabLock
);
3629 if (pBAORIEntry
->ORI_BA_Status
== Originator_Done
) {
3630 pAd
->BATable
.numAsOriginator
-= 1;
3631 DBGPRINT(RT_DEBUG_TRACE
,
3632 ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3633 pAd
->BATable
.numAsRecipient
));
3634 /* Erase Bitmap flag. */
3636 pAd
->MacTab
.Content
[pBAORIEntry
->Wcid
].TXBAbitmap
&= (~(1 << (pBAORIEntry
->TID
))); /* If STA mode, erase flag here */
3637 pAd
->MacTab
.Content
[pBAORIEntry
->Wcid
].BAOriWcidArray
[pBAORIEntry
->TID
] = 0; /* If STA mode, erase flag here */
3638 pBAORIEntry
->ORI_BA_Status
= Originator_NONE
;
3639 pBAORIEntry
->Token
= 1;
3640 /* Not clear Sequence here. */
3641 NdisReleaseSpinLock(&pAd
->BATabLock
);
3651 IRQL = DISPATCH_LEVEL
3654 void BssEntrySet(struct rt_rtmp_adapter
*pAd
, struct rt_bss_entry
*pBss
, u8
*pBssid
, char Ssid
[], u8 SsidLen
, u8 BssType
, u16 BeaconPeriod
, struct rt_cf_parm
* pCfParm
, u16 AtimWin
, u16 CapabilityInfo
, u8 SupRate
[], u8 SupRateLen
, u8 ExtRate
[], u8 ExtRateLen
, struct rt_ht_capability_ie
* pHtCapability
, struct rt_add_ht_info_ie
* pAddHtInfo
, /* AP might use this additional ht info IE */
3657 u8 NewExtChanOffset
,
3660 IN LARGE_INTEGER TimeStamp
,
3662 struct rt_edca_parm
*pEdcaParm
,
3663 struct rt_qos_capability_parm
*pQosCapability
,
3664 struct rt_qbss_load_parm
*pQbssLoad
,
3665 u16 LengthVIE
, struct rt_ndis_802_11_variable_ies
*pVIE
)
3667 COPY_MAC_ADDR(pBss
->Bssid
, pBssid
);
3668 /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */
3671 /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */
3672 /* Or send beacon /probe response with SSID len matching real SSID length, */
3673 /* but SSID is all zero. such as "00-00-00-00" with length 4. */
3674 /* We have to prevent this case overwrite correct table */
3675 if (NdisEqualMemory(Ssid
, ZeroSsid
, SsidLen
) == 0) {
3676 NdisZeroMemory(pBss
->Ssid
, MAX_LEN_OF_SSID
);
3677 NdisMoveMemory(pBss
->Ssid
, Ssid
, SsidLen
);
3678 pBss
->SsidLen
= SsidLen
;
3683 pBss
->BssType
= BssType
;
3684 pBss
->BeaconPeriod
= BeaconPeriod
;
3685 if (BssType
== BSS_INFRA
) {
3686 if (pCfParm
->bValid
) {
3687 pBss
->CfpCount
= pCfParm
->CfpCount
;
3688 pBss
->CfpPeriod
= pCfParm
->CfpPeriod
;
3689 pBss
->CfpMaxDuration
= pCfParm
->CfpMaxDuration
;
3690 pBss
->CfpDurRemaining
= pCfParm
->CfpDurRemaining
;
3693 pBss
->AtimWin
= AtimWin
;
3696 pBss
->CapabilityInfo
= CapabilityInfo
;
3697 /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */
3698 /* Combine with AuthMode, they will decide the connection methods. */
3699 pBss
->Privacy
= CAP_IS_PRIVACY_ON(pBss
->CapabilityInfo
);
3700 ASSERT(SupRateLen
<= MAX_LEN_OF_SUPPORTED_RATES
);
3701 if (SupRateLen
<= MAX_LEN_OF_SUPPORTED_RATES
)
3702 NdisMoveMemory(pBss
->SupRate
, SupRate
, SupRateLen
);
3704 NdisMoveMemory(pBss
->SupRate
, SupRate
,
3705 MAX_LEN_OF_SUPPORTED_RATES
);
3706 pBss
->SupRateLen
= SupRateLen
;
3707 ASSERT(ExtRateLen
<= MAX_LEN_OF_SUPPORTED_RATES
);
3708 NdisMoveMemory(pBss
->ExtRate
, ExtRate
, ExtRateLen
);
3709 pBss
->NewExtChanOffset
= NewExtChanOffset
;
3710 pBss
->ExtRateLen
= ExtRateLen
;
3711 pBss
->Channel
= Channel
;
3712 pBss
->CentralChannel
= Channel
;
3714 /* Update CkipFlag. if not exists, the value is 0x0 */
3715 pBss
->CkipFlag
= CkipFlag
;
3717 /* New for microsoft Fixed IEs */
3718 NdisMoveMemory(pBss
->FixIEs
.Timestamp
, &TimeStamp
, 8);
3719 pBss
->FixIEs
.BeaconInterval
= BeaconPeriod
;
3720 pBss
->FixIEs
.Capabilities
= CapabilityInfo
;
3722 /* New for microsoft Variable IEs */
3723 if (LengthVIE
!= 0) {
3724 pBss
->VarIELen
= LengthVIE
;
3725 NdisMoveMemory(pBss
->VarIEs
, pVIE
, pBss
->VarIELen
);
3730 pBss
->AddHtInfoLen
= 0;
3731 pBss
->HtCapabilityLen
= 0;
3732 if (HtCapabilityLen
> 0) {
3733 pBss
->HtCapabilityLen
= HtCapabilityLen
;
3734 NdisMoveMemory(&pBss
->HtCapability
, pHtCapability
,
3736 if (AddHtInfoLen
> 0) {
3737 pBss
->AddHtInfoLen
= AddHtInfoLen
;
3738 NdisMoveMemory(&pBss
->AddHtInfo
, pAddHtInfo
,
3741 if ((pAddHtInfo
->ControlChan
> 2)
3742 && (pAddHtInfo
->AddHtInfo
.ExtChanOffset
==
3744 && (pHtCapability
->HtCapInfo
.ChannelWidth
==
3746 pBss
->CentralChannel
=
3747 pAddHtInfo
->ControlChan
- 2;
3749 if ((pAddHtInfo
->AddHtInfo
.ExtChanOffset
==
3751 && (pHtCapability
->HtCapInfo
.ChannelWidth
==
3753 pBss
->CentralChannel
=
3754 pAddHtInfo
->ControlChan
+ 2;
3759 BssCipherParse(pBss
);
3763 NdisMoveMemory(&pBss
->EdcaParm
, pEdcaParm
, sizeof(struct rt_edca_parm
));
3765 pBss
->EdcaParm
.bValid
= FALSE
;
3767 NdisMoveMemory(&pBss
->QosCapability
, pQosCapability
,
3768 sizeof(struct rt_qos_capability_parm
));
3770 pBss
->QosCapability
.bValid
= FALSE
;
3772 NdisMoveMemory(&pBss
->QbssLoad
, pQbssLoad
,
3773 sizeof(struct rt_qbss_load_parm
));
3775 pBss
->QbssLoad
.bValid
= FALSE
;
3778 struct rt_eid
* pEid
;
3781 NdisZeroMemory(&pBss
->WpaIE
.IE
[0], MAX_CUSTOM_LEN
);
3782 NdisZeroMemory(&pBss
->RsnIE
.IE
[0], MAX_CUSTOM_LEN
);
3783 pEid
= (struct rt_eid
*) pVIE
;
3784 while ((Length
+ 2 + (u16
)pEid
->Len
) <= LengthVIE
) {
3785 switch (pEid
->Eid
) {
3787 if (NdisEqualMemory(pEid
->Octet
, WPA_OUI
, 4)) {
3788 if ((pEid
->Len
+ 2) > MAX_CUSTOM_LEN
) {
3789 pBss
->WpaIE
.IELen
= 0;
3792 pBss
->WpaIE
.IELen
= pEid
->Len
+ 2;
3793 NdisMoveMemory(pBss
->WpaIE
.IE
, pEid
,
3799 (pEid
->Octet
+ 2, RSN_OUI
, 3)) {
3800 if ((pEid
->Len
+ 2) > MAX_CUSTOM_LEN
) {
3801 pBss
->RsnIE
.IELen
= 0;
3804 pBss
->RsnIE
.IELen
= pEid
->Len
+ 2;
3805 NdisMoveMemory(pBss
->RsnIE
.IE
, pEid
,
3810 Length
= Length
+ 2 + (u16
)pEid
->Len
; /* Eid[1] + Len[1]+ content[Len] */
3811 pEid
= (struct rt_eid
*) ((u8
*) pEid
+ 2 + pEid
->Len
);
3817 * \brief insert an entry into the bss table
3818 * \param p_tab The BSS table
3819 * \param Bssid BSSID
3821 * \param ssid_len Length of SSID
3823 * \param beacon_period
3830 * \param channel_idx
3834 * \note If SSID is identical, the old entry will be replaced by the new one
3836 IRQL = DISPATCH_LEVEL
3839 unsigned long BssTableSetEntry(struct rt_rtmp_adapter
*pAd
, struct rt_bss_table
*Tab
, u8
*pBssid
, char Ssid
[], u8 SsidLen
, u8 BssType
, u16 BeaconPeriod
, struct rt_cf_parm
* CfParm
, u16 AtimWin
, u16 CapabilityInfo
, u8 SupRate
[], u8 SupRateLen
, u8 ExtRate
[], u8 ExtRateLen
, struct rt_ht_capability_ie
* pHtCapability
, struct rt_add_ht_info_ie
* pAddHtInfo
, /* AP might use this additional ht info IE */
3842 u8 NewExtChanOffset
,
3845 IN LARGE_INTEGER TimeStamp
,
3847 struct rt_edca_parm
*pEdcaParm
,
3848 struct rt_qos_capability_parm
*pQosCapability
,
3849 struct rt_qbss_load_parm
*pQbssLoad
,
3850 u16 LengthVIE
, struct rt_ndis_802_11_variable_ies
*pVIE
)
3855 BssTableSearchWithSSID(Tab
, pBssid
, (u8
*) Ssid
, SsidLen
,
3857 if (Idx
== BSS_NOT_FOUND
) {
3858 if (Tab
->BssNr
>= MAX_LEN_OF_BSS_TABLE
) {
3860 /* It may happen when BSS Table was full. */
3861 /* The desired AP will not be added into BSS Table */
3862 /* In this case, if we found the desired AP then overwrite BSS Table. */
3864 if (!OPSTATUS_TEST_FLAG
3865 (pAd
, fOP_STATUS_MEDIA_STATE_CONNECTED
)) {
3866 if (MAC_ADDR_EQUAL(pAd
->MlmeAux
.Bssid
, pBssid
)
3867 || SSID_EQUAL(pAd
->MlmeAux
.Ssid
,
3868 pAd
->MlmeAux
.SsidLen
, Ssid
,
3870 Idx
= Tab
->BssOverlapNr
;
3871 BssEntrySet(pAd
, &Tab
->BssEntry
[Idx
],
3872 pBssid
, Ssid
, SsidLen
,
3873 BssType
, BeaconPeriod
,
3875 CapabilityInfo
, SupRate
,
3876 SupRateLen
, ExtRate
,
3877 ExtRateLen
, pHtCapability
,
3878 pAddHtInfo
, HtCapabilityLen
,
3880 NewExtChanOffset
, ChannelNo
,
3881 Rssi
, TimeStamp
, CkipFlag
,
3882 pEdcaParm
, pQosCapability
,
3883 pQbssLoad
, LengthVIE
, pVIE
);
3885 (Tab
->BssOverlapNr
++) %
3886 MAX_LEN_OF_BSS_TABLE
;
3890 return BSS_NOT_FOUND
;
3894 BssEntrySet(pAd
, &Tab
->BssEntry
[Idx
], pBssid
, Ssid
, SsidLen
,
3895 BssType
, BeaconPeriod
, CfParm
, AtimWin
,
3896 CapabilityInfo
, SupRate
, SupRateLen
, ExtRate
,
3897 ExtRateLen
, pHtCapability
, pAddHtInfo
,
3898 HtCapabilityLen
, AddHtInfoLen
, NewExtChanOffset
,
3899 ChannelNo
, Rssi
, TimeStamp
, CkipFlag
, pEdcaParm
,
3900 pQosCapability
, pQbssLoad
, LengthVIE
, pVIE
);
3903 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3905 (Ssid
, SsidLen
, Tab
->BssEntry
[Idx
].Ssid
,
3906 Tab
->BssEntry
[Idx
].SsidLen
))
3909 (Tab
->BssEntry
[Idx
].Ssid
, ZeroSsid
,
3910 Tab
->BssEntry
[Idx
].SsidLen
))) {
3911 BssEntrySet(pAd
, &Tab
->BssEntry
[Idx
], pBssid
, Ssid
,
3912 SsidLen
, BssType
, BeaconPeriod
, CfParm
,
3913 AtimWin
, CapabilityInfo
, SupRate
,
3914 SupRateLen
, ExtRate
, ExtRateLen
,
3915 pHtCapability
, pAddHtInfo
, HtCapabilityLen
,
3916 AddHtInfoLen
, NewExtChanOffset
, ChannelNo
,
3917 Rssi
, TimeStamp
, CkipFlag
, pEdcaParm
,
3918 pQosCapability
, pQbssLoad
, LengthVIE
, pVIE
);
3925 /* IRQL = DISPATCH_LEVEL */
3926 void BssTableSsidSort(struct rt_rtmp_adapter
*pAd
,
3927 struct rt_bss_table
*OutTab
, char Ssid
[], u8 SsidLen
)
3930 BssTableInit(OutTab
);
3932 for (i
= 0; i
< pAd
->ScanTab
.BssNr
; i
++) {
3933 struct rt_bss_entry
*pInBss
= &pAd
->ScanTab
.BssEntry
[i
];
3934 BOOLEAN bIsHiddenApIncluded
= FALSE
;
3936 if (((pAd
->CommonCfg
.bIEEE80211H
== 1) &&
3937 (pAd
->MlmeAux
.Channel
> 14) &&
3938 RadarChannelCheck(pAd
, pInBss
->Channel
))
3941 bIsHiddenApIncluded
= TRUE
;
3944 if ((pInBss
->BssType
== pAd
->StaCfg
.BssType
) &&
3945 (SSID_EQUAL(Ssid
, SsidLen
, pInBss
->Ssid
, pInBss
->SsidLen
)
3946 || bIsHiddenApIncluded
)) {
3947 struct rt_bss_entry
*pOutBss
= &OutTab
->BssEntry
[OutTab
->BssNr
];
3949 /* 2.4G/5G N only mode */
3950 if ((pInBss
->HtCapabilityLen
== 0) &&
3951 ((pAd
->CommonCfg
.PhyMode
== PHY_11N_2_4G
)
3952 || (pAd
->CommonCfg
.PhyMode
== PHY_11N_5G
))) {
3953 DBGPRINT(RT_DEBUG_TRACE
,
3954 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3958 /* Check the Authmode first */
3959 if (pAd
->StaCfg
.AuthMode
>= Ndis802_11AuthModeWPA
) {
3960 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
3961 if ((pAd
->StaCfg
.AuthMode
!= pInBss
->AuthMode
)
3962 && (pAd
->StaCfg
.AuthMode
!=
3963 pInBss
->AuthModeAux
))
3967 /* Check cipher suite, AP must have more secured cipher than station setting */
3968 if ((pAd
->StaCfg
.AuthMode
==
3969 Ndis802_11AuthModeWPA
)
3970 || (pAd
->StaCfg
.AuthMode
==
3971 Ndis802_11AuthModeWPAPSK
)) {
3972 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
3973 if (pInBss
->WPA
.bMixMode
== FALSE
)
3974 if (pAd
->StaCfg
.WepStatus
!=
3975 pInBss
->WPA
.GroupCipher
)
3978 /* check group cipher */
3979 if ((pAd
->StaCfg
.WepStatus
<
3980 pInBss
->WPA
.GroupCipher
)
3981 && (pInBss
->WPA
.GroupCipher
!=
3982 Ndis802_11GroupWEP40Enabled
)
3983 && (pInBss
->WPA
.GroupCipher
!=
3984 Ndis802_11GroupWEP104Enabled
))
3987 /* check pairwise cipher, skip if none matched */
3988 /* If profile set to AES, let it pass without question. */
3989 /* If profile set to TKIP, we must find one mateched */
3990 if ((pAd
->StaCfg
.WepStatus
==
3991 Ndis802_11Encryption2Enabled
)
3992 && (pAd
->StaCfg
.WepStatus
!=
3993 pInBss
->WPA
.PairCipher
)
3994 && (pAd
->StaCfg
.WepStatus
!=
3995 pInBss
->WPA
.PairCipherAux
))
3998 if ((pAd
->StaCfg
.AuthMode
==
3999 Ndis802_11AuthModeWPA2
)
4000 || (pAd
->StaCfg
.AuthMode
==
4001 Ndis802_11AuthModeWPA2PSK
)) {
4002 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4003 if (pInBss
->WPA2
.bMixMode
== FALSE
)
4004 if (pAd
->StaCfg
.WepStatus
!=
4005 pInBss
->WPA2
.GroupCipher
)
4008 /* check group cipher */
4009 if ((pAd
->StaCfg
.WepStatus
<
4010 pInBss
->WPA
.GroupCipher
)
4011 && (pInBss
->WPA2
.GroupCipher
!=
4012 Ndis802_11GroupWEP40Enabled
)
4013 && (pInBss
->WPA2
.GroupCipher
!=
4014 Ndis802_11GroupWEP104Enabled
))
4017 /* check pairwise cipher, skip if none matched */
4018 /* If profile set to AES, let it pass without question. */
4019 /* If profile set to TKIP, we must find one mateched */
4020 if ((pAd
->StaCfg
.WepStatus
==
4021 Ndis802_11Encryption2Enabled
)
4022 && (pAd
->StaCfg
.WepStatus
!=
4023 pInBss
->WPA2
.PairCipher
)
4024 && (pAd
->StaCfg
.WepStatus
!=
4025 pInBss
->WPA2
.PairCipherAux
))
4029 /* Bss Type matched, SSID matched. */
4030 /* We will check wepstatus for qualification Bss */
4031 else if (pAd
->StaCfg
.WepStatus
!= pInBss
->WepStatus
) {
4032 DBGPRINT(RT_DEBUG_TRACE
,
4033 ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4034 pAd
->StaCfg
.WepStatus
,
4035 pInBss
->WepStatus
));
4037 /* For the SESv2 case, we will not qualify WepStatus. */
4042 /* Since the AP is using hidden SSID, and we are trying to connect to ANY */
4043 /* It definitely will fail. So, skip it. */
4044 /* CCX also require not even try to connect it! */
4048 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4049 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4050 if ((pInBss
->CentralChannel
!= pInBss
->Channel
) &&
4051 (pAd
->CommonCfg
.RegTransmitSetting
.field
.BW
==
4053 if (RTMPCheckChannel
4054 (pAd
, pInBss
->CentralChannel
,
4055 pInBss
->Channel
) == FALSE
) {
4056 pAd
->CommonCfg
.RegTransmitSetting
.field
.
4059 pAd
->CommonCfg
.RegTransmitSetting
.field
.
4062 if (pAd
->CommonCfg
.DesiredHtPhy
.
4063 ChannelWidth
== BAND_WIDTH_20
) {
4068 /* copy matching BSS from InTab to OutTab */
4069 NdisMoveMemory(pOutBss
, pInBss
, sizeof(struct rt_bss_entry
));
4072 } else if ((pInBss
->BssType
== pAd
->StaCfg
.BssType
)
4073 && (SsidLen
== 0)) {
4074 struct rt_bss_entry
*pOutBss
= &OutTab
->BssEntry
[OutTab
->BssNr
];
4076 /* 2.4G/5G N only mode */
4077 if ((pInBss
->HtCapabilityLen
== 0) &&
4078 ((pAd
->CommonCfg
.PhyMode
== PHY_11N_2_4G
)
4079 || (pAd
->CommonCfg
.PhyMode
== PHY_11N_5G
))) {
4080 DBGPRINT(RT_DEBUG_TRACE
,
4081 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4085 /* Check the Authmode first */
4086 if (pAd
->StaCfg
.AuthMode
>= Ndis802_11AuthModeWPA
) {
4087 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
4088 if ((pAd
->StaCfg
.AuthMode
!= pInBss
->AuthMode
)
4089 && (pAd
->StaCfg
.AuthMode
!=
4090 pInBss
->AuthModeAux
))
4094 /* Check cipher suite, AP must have more secured cipher than station setting */
4095 if ((pAd
->StaCfg
.AuthMode
==
4096 Ndis802_11AuthModeWPA
)
4097 || (pAd
->StaCfg
.AuthMode
==
4098 Ndis802_11AuthModeWPAPSK
)) {
4099 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4100 if (pInBss
->WPA
.bMixMode
== FALSE
)
4101 if (pAd
->StaCfg
.WepStatus
!=
4102 pInBss
->WPA
.GroupCipher
)
4105 /* check group cipher */
4106 if (pAd
->StaCfg
.WepStatus
<
4107 pInBss
->WPA
.GroupCipher
)
4110 /* check pairwise cipher, skip if none matched */
4111 /* If profile set to AES, let it pass without question. */
4112 /* If profile set to TKIP, we must find one mateched */
4113 if ((pAd
->StaCfg
.WepStatus
==
4114 Ndis802_11Encryption2Enabled
)
4115 && (pAd
->StaCfg
.WepStatus
!=
4116 pInBss
->WPA
.PairCipher
)
4117 && (pAd
->StaCfg
.WepStatus
!=
4118 pInBss
->WPA
.PairCipherAux
))
4121 if ((pAd
->StaCfg
.AuthMode
==
4122 Ndis802_11AuthModeWPA2
)
4123 || (pAd
->StaCfg
.AuthMode
==
4124 Ndis802_11AuthModeWPA2PSK
)) {
4125 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4126 if (pInBss
->WPA2
.bMixMode
== FALSE
)
4127 if (pAd
->StaCfg
.WepStatus
!=
4128 pInBss
->WPA2
.GroupCipher
)
4131 /* check group cipher */
4132 if (pAd
->StaCfg
.WepStatus
<
4133 pInBss
->WPA2
.GroupCipher
)
4136 /* check pairwise cipher, skip if none matched */
4137 /* If profile set to AES, let it pass without question. */
4138 /* If profile set to TKIP, we must find one mateched */
4139 if ((pAd
->StaCfg
.WepStatus
==
4140 Ndis802_11Encryption2Enabled
)
4141 && (pAd
->StaCfg
.WepStatus
!=
4142 pInBss
->WPA2
.PairCipher
)
4143 && (pAd
->StaCfg
.WepStatus
!=
4144 pInBss
->WPA2
.PairCipherAux
))
4148 /* Bss Type matched, SSID matched. */
4149 /* We will check wepstatus for qualification Bss */
4150 else if (pAd
->StaCfg
.WepStatus
!= pInBss
->WepStatus
)
4153 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4154 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4155 if ((pInBss
->CentralChannel
!= pInBss
->Channel
) &&
4156 (pAd
->CommonCfg
.RegTransmitSetting
.field
.BW
==
4158 if (RTMPCheckChannel
4159 (pAd
, pInBss
->CentralChannel
,
4160 pInBss
->Channel
) == FALSE
) {
4161 pAd
->CommonCfg
.RegTransmitSetting
.field
.
4164 pAd
->CommonCfg
.RegTransmitSetting
.field
.
4168 /* copy matching BSS from InTab to OutTab */
4169 NdisMoveMemory(pOutBss
, pInBss
, sizeof(struct rt_bss_entry
));
4174 if (OutTab
->BssNr
>= MAX_LEN_OF_BSS_TABLE
)
4178 BssTableSortByRssi(OutTab
);
4181 /* IRQL = DISPATCH_LEVEL */
4182 void BssTableSortByRssi(struct rt_bss_table
*OutTab
)
4185 struct rt_bss_entry TmpBss
;
4187 for (i
= 0; i
< OutTab
->BssNr
- 1; i
++) {
4188 for (j
= i
+ 1; j
< OutTab
->BssNr
; j
++) {
4189 if (OutTab
->BssEntry
[j
].Rssi
> OutTab
->BssEntry
[i
].Rssi
) {
4190 NdisMoveMemory(&TmpBss
, &OutTab
->BssEntry
[j
],
4191 sizeof(struct rt_bss_entry
));
4192 NdisMoveMemory(&OutTab
->BssEntry
[j
],
4193 &OutTab
->BssEntry
[i
],
4194 sizeof(struct rt_bss_entry
));
4195 NdisMoveMemory(&OutTab
->BssEntry
[i
], &TmpBss
,
4196 sizeof(struct rt_bss_entry
));
4202 void BssCipherParse(struct rt_bss_entry
*pBss
)
4204 struct rt_eid
* pEid
;
4206 struct rt_rsn_ie_header
* pRsnHeader
;
4207 struct rt_cipher_suite_struct
* pCipher
;
4208 struct rt_akm_suite
* pAKM
;
4211 NDIS_802_11_ENCRYPTION_STATUS TmpCipher
;
4214 /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */
4216 if (pBss
->Privacy
) {
4217 pBss
->WepStatus
= Ndis802_11WEPEnabled
;
4219 pBss
->WepStatus
= Ndis802_11WEPDisabled
;
4221 /* Set default to disable & open authentication before parsing variable IE */
4222 pBss
->AuthMode
= Ndis802_11AuthModeOpen
;
4223 pBss
->AuthModeAux
= Ndis802_11AuthModeOpen
;
4225 /* Init WPA setting */
4226 pBss
->WPA
.PairCipher
= Ndis802_11WEPDisabled
;
4227 pBss
->WPA
.PairCipherAux
= Ndis802_11WEPDisabled
;
4228 pBss
->WPA
.GroupCipher
= Ndis802_11WEPDisabled
;
4229 pBss
->WPA
.RsnCapability
= 0;
4230 pBss
->WPA
.bMixMode
= FALSE
;
4232 /* Init WPA2 setting */
4233 pBss
->WPA2
.PairCipher
= Ndis802_11WEPDisabled
;
4234 pBss
->WPA2
.PairCipherAux
= Ndis802_11WEPDisabled
;
4235 pBss
->WPA2
.GroupCipher
= Ndis802_11WEPDisabled
;
4236 pBss
->WPA2
.RsnCapability
= 0;
4237 pBss
->WPA2
.bMixMode
= FALSE
;
4239 Length
= (int)pBss
->VarIELen
;
4241 while (Length
> 0) {
4242 /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */
4243 pTmp
= ((u8
*)pBss
->VarIEs
) + pBss
->VarIELen
- Length
;
4244 pEid
= (struct rt_eid
*) pTmp
;
4245 switch (pEid
->Eid
) {
4247 if (NdisEqualMemory(pEid
->Octet
, SES_OUI
, 3)
4248 && (pEid
->Len
== 7)) {
4251 } else if (NdisEqualMemory(pEid
->Octet
, WPA_OUI
, 4) !=
4253 /* if unsupported vendor specific IE */
4256 /* Skip OUI, version, and multicast suite */
4257 /* This part should be improved in the future when AP supported multiple cipher suite. */
4258 /* For now, it's OK since almost all APs have fixed cipher suite supported. */
4259 /* pTmp = (u8 *)pEid->Octet; */
4262 /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
4270 /* Parse group cipher */
4273 pBss
->WPA
.GroupCipher
=
4274 Ndis802_11GroupWEP40Enabled
;
4277 pBss
->WPA
.GroupCipher
=
4278 Ndis802_11GroupWEP104Enabled
;
4281 pBss
->WPA
.GroupCipher
=
4282 Ndis802_11Encryption2Enabled
;
4285 pBss
->WPA
.GroupCipher
=
4286 Ndis802_11Encryption3Enabled
;
4291 /* number of unicast suite */
4294 /* skip all unicast cipher suites */
4295 /*Count = *(u16 *)pTmp; */
4296 Count
= (pTmp
[1] << 8) + pTmp
[0];
4297 pTmp
+= sizeof(u16
);
4299 /* Parsing all unicast cipher suite */
4303 TmpCipher
= Ndis802_11WEPDisabled
;
4306 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4308 Ndis802_11Encryption1Enabled
;
4312 Ndis802_11Encryption2Enabled
;
4316 Ndis802_11Encryption3Enabled
;
4321 if (TmpCipher
> pBss
->WPA
.PairCipher
) {
4322 /* Move the lower cipher suite to PairCipherAux */
4323 pBss
->WPA
.PairCipherAux
=
4324 pBss
->WPA
.PairCipher
;
4325 pBss
->WPA
.PairCipher
= TmpCipher
;
4327 pBss
->WPA
.PairCipherAux
= TmpCipher
;
4333 /* 4. get AKM suite counts */
4334 /*Count = *(u16 *)pTmp; */
4335 Count
= (pTmp
[1] << 8) + pTmp
[0];
4336 pTmp
+= sizeof(u16
);
4341 /* Set AP support WPA-enterprise mode */
4342 if (pBss
->AuthMode
== Ndis802_11AuthModeOpen
)
4343 pBss
->AuthMode
= Ndis802_11AuthModeWPA
;
4346 Ndis802_11AuthModeWPA
;
4349 /* Set AP support WPA-PSK mode */
4350 if (pBss
->AuthMode
== Ndis802_11AuthModeOpen
)
4352 Ndis802_11AuthModeWPAPSK
;
4355 Ndis802_11AuthModeWPAPSK
;
4362 /* Fixed for WPA-None */
4363 if (pBss
->BssType
== BSS_ADHOC
) {
4364 pBss
->AuthMode
= Ndis802_11AuthModeWPANone
;
4365 pBss
->AuthModeAux
= Ndis802_11AuthModeWPANone
;
4366 pBss
->WepStatus
= pBss
->WPA
.GroupCipher
;
4367 /* Patched bugs for old driver */
4368 if (pBss
->WPA
.PairCipherAux
==
4369 Ndis802_11WEPDisabled
)
4370 pBss
->WPA
.PairCipherAux
=
4371 pBss
->WPA
.GroupCipher
;
4373 pBss
->WepStatus
= pBss
->WPA
.PairCipher
;
4375 /* Check the Pair & Group, if different, turn on mixed mode flag */
4376 if (pBss
->WPA
.GroupCipher
!= pBss
->WPA
.PairCipher
)
4377 pBss
->WPA
.bMixMode
= TRUE
;
4382 pRsnHeader
= (struct rt_rsn_ie_header
*) pTmp
;
4384 /* 0. Version must be 1 */
4385 if (le2cpu16(pRsnHeader
->Version
) != 1)
4387 pTmp
+= sizeof(struct rt_rsn_ie_header
);
4389 /* 1. Check group cipher */
4390 pCipher
= (struct rt_cipher_suite_struct
*) pTmp
;
4391 if (!RTMPEqualMemory(pTmp
, RSN_OUI
, 3))
4394 /* Parse group cipher */
4395 switch (pCipher
->Type
) {
4397 pBss
->WPA2
.GroupCipher
=
4398 Ndis802_11GroupWEP40Enabled
;
4401 pBss
->WPA2
.GroupCipher
=
4402 Ndis802_11GroupWEP104Enabled
;
4405 pBss
->WPA2
.GroupCipher
=
4406 Ndis802_11Encryption2Enabled
;
4409 pBss
->WPA2
.GroupCipher
=
4410 Ndis802_11Encryption3Enabled
;
4415 /* set to correct offset for next parsing */
4416 pTmp
+= sizeof(struct rt_cipher_suite_struct
);
4418 /* 2. Get pairwise cipher counts */
4419 /*Count = *(u16 *)pTmp; */
4420 Count
= (pTmp
[1] << 8) + pTmp
[0];
4421 pTmp
+= sizeof(u16
);
4423 /* 3. Get pairwise cipher */
4424 /* Parsing all unicast cipher suite */
4427 pCipher
= (struct rt_cipher_suite_struct
*) pTmp
;
4428 TmpCipher
= Ndis802_11WEPDisabled
;
4429 switch (pCipher
->Type
) {
4431 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4433 Ndis802_11Encryption1Enabled
;
4437 Ndis802_11Encryption2Enabled
;
4441 Ndis802_11Encryption3Enabled
;
4446 if (TmpCipher
> pBss
->WPA2
.PairCipher
) {
4447 /* Move the lower cipher suite to PairCipherAux */
4448 pBss
->WPA2
.PairCipherAux
=
4449 pBss
->WPA2
.PairCipher
;
4450 pBss
->WPA2
.PairCipher
= TmpCipher
;
4452 pBss
->WPA2
.PairCipherAux
= TmpCipher
;
4454 pTmp
+= sizeof(struct rt_cipher_suite_struct
);
4458 /* 4. get AKM suite counts */
4459 /*Count = *(u16 *)pTmp; */
4460 Count
= (pTmp
[1] << 8) + pTmp
[0];
4461 pTmp
+= sizeof(u16
);
4463 /* 5. Get AKM ciphers */
4464 /* Parsing all AKM ciphers */
4466 pAKM
= (struct rt_akm_suite
*) pTmp
;
4467 if (!RTMPEqualMemory(pTmp
, RSN_OUI
, 3))
4470 switch (pAKM
->Type
) {
4472 /* Set AP support WPA-enterprise mode */
4473 if (pBss
->AuthMode
==
4474 Ndis802_11AuthModeOpen
)
4476 Ndis802_11AuthModeWPA2
;
4479 Ndis802_11AuthModeWPA2
;
4482 /* Set AP support WPA-PSK mode */
4483 if (pBss
->AuthMode
==
4484 Ndis802_11AuthModeOpen
)
4486 Ndis802_11AuthModeWPA2PSK
;
4489 Ndis802_11AuthModeWPA2PSK
;
4492 if (pBss
->AuthMode
==
4493 Ndis802_11AuthModeOpen
)
4495 Ndis802_11AuthModeMax
;
4498 Ndis802_11AuthModeMax
;
4501 pTmp
+= (Count
* sizeof(struct rt_akm_suite
));
4505 /* Fixed for WPA-None */
4506 if (pBss
->BssType
== BSS_ADHOC
) {
4507 pBss
->AuthMode
= Ndis802_11AuthModeWPANone
;
4508 pBss
->AuthModeAux
= Ndis802_11AuthModeWPANone
;
4509 pBss
->WPA
.PairCipherAux
=
4510 pBss
->WPA2
.PairCipherAux
;
4511 pBss
->WPA
.GroupCipher
= pBss
->WPA2
.GroupCipher
;
4512 pBss
->WepStatus
= pBss
->WPA
.GroupCipher
;
4513 /* Patched bugs for old driver */
4514 if (pBss
->WPA
.PairCipherAux
==
4515 Ndis802_11WEPDisabled
)
4516 pBss
->WPA
.PairCipherAux
=
4517 pBss
->WPA
.GroupCipher
;
4519 pBss
->WepStatus
= pBss
->WPA2
.PairCipher
;
4521 /* 6. Get RSN capability */
4522 /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */
4523 pBss
->WPA2
.RsnCapability
= (pTmp
[1] << 8) + pTmp
[0];
4524 pTmp
+= sizeof(u16
);
4526 /* Check the Pair & Group, if different, turn on mixed mode flag */
4527 if (pBss
->WPA2
.GroupCipher
!= pBss
->WPA2
.PairCipher
)
4528 pBss
->WPA2
.bMixMode
= TRUE
;
4534 Length
-= (pEid
->Len
+ 2);
4538 /* =========================================================================================== */
4540 /* =========================================================================================== */
4542 /*! \brief generates a random mac address value for IBSS BSSID
4543 * \param Addr the bssid location
4548 void MacAddrRandomBssid(struct rt_rtmp_adapter
*pAd
, u8
*pAddr
)
4552 for (i
= 0; i
< MAC_ADDR_LEN
; i
++) {
4553 pAddr
[i
] = RandomByte(pAd
);
4556 pAddr
[0] = (pAddr
[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx */
4559 /*! \brief init the management mac frame header
4560 * \param p_hdr mac header
4561 * \param subtype subtype of the frame
4562 * \param p_ds destination address, don't care if it is a broadcast address
4564 * \pre the station has the following information in the pAd->StaCfg
4568 * \note this function initializes the following field
4570 IRQL = PASSIVE_LEVEL
4571 IRQL = DISPATCH_LEVEL
4574 void MgtMacHeaderInit(struct rt_rtmp_adapter
*pAd
,
4575 struct rt_header_802_11
* pHdr80211
,
4577 u8 ToDs
, u8
*pDA
, u8
*pBssid
)
4579 NdisZeroMemory(pHdr80211
, sizeof(struct rt_header_802_11
));
4581 pHdr80211
->FC
.Type
= BTYPE_MGMT
;
4582 pHdr80211
->FC
.SubType
= SubType
;
4583 /* if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type */
4584 /* pHdr80211->FC.Type = BTYPE_CNTL; */
4585 pHdr80211
->FC
.ToDs
= ToDs
;
4586 COPY_MAC_ADDR(pHdr80211
->Addr1
, pDA
);
4587 COPY_MAC_ADDR(pHdr80211
->Addr2
, pAd
->CurrentAddress
);
4588 COPY_MAC_ADDR(pHdr80211
->Addr3
, pBssid
);
4591 /* =========================================================================================== */
4593 /* =========================================================================================== */
4595 /*!***************************************************************************
4596 * This routine build an outgoing frame, and fill all information specified
4597 * in argument list to the frame body. The actual frame size is the summation
4600 * Buffer - pointer to a pre-allocated memory segment
4601 * args - a list of <int arg_size, arg> pairs.
4602 * NOTE NOTE NOTE! the last argument must be NULL, otherwise this
4603 * function will FAIL!
4605 * Size of the buffer
4607 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4609 IRQL = PASSIVE_LEVEL
4610 IRQL = DISPATCH_LEVEL
4612 ****************************************************************************/
4613 unsigned long MakeOutgoingFrame(u8
* Buffer
, unsigned long * FrameLen
, ...)
4617 unsigned long TotLeng
;
4620 /* calculates the total length */
4622 va_start(Args
, FrameLen
);
4624 leng
= va_arg(Args
, int);
4625 if (leng
== END_OF_ARGS
) {
4628 p
= va_arg(Args
, void *);
4629 NdisMoveMemory(&Buffer
[TotLeng
], p
, leng
);
4630 TotLeng
= TotLeng
+ leng
;
4633 va_end(Args
); /* clean up */
4634 *FrameLen
= TotLeng
;
4638 /* =========================================================================================== */
4640 /* =========================================================================================== */
4642 /*! \brief Initialize The MLME Queue, used by MLME Functions
4643 * \param *Queue The MLME Queue
4644 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4647 * \note Because this is done only once (at the init stage), no need to be locked
4649 IRQL = PASSIVE_LEVEL
4652 int MlmeQueueInit(struct rt_mlme_queue
*Queue
)
4656 NdisAllocateSpinLock(&Queue
->Lock
);
4662 for (i
= 0; i
< MAX_LEN_OF_MLME_QUEUE
; i
++) {
4663 Queue
->Entry
[i
].Occupied
= FALSE
;
4664 Queue
->Entry
[i
].MsgLen
= 0;
4665 NdisZeroMemory(Queue
->Entry
[i
].Msg
, MGMT_DMA_BUFFER_SIZE
);
4668 return NDIS_STATUS_SUCCESS
;
4671 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4672 * \param *Queue The MLME Queue
4673 * \param Machine The State Machine Id
4674 * \param MsgType The Message Type
4675 * \param MsgLen The Message length
4676 * \param *Msg The message pointer
4677 * \return TRUE if enqueue is successful, FALSE if the queue is full
4680 * \note The message has to be initialized
4682 IRQL = PASSIVE_LEVEL
4683 IRQL = DISPATCH_LEVEL
4686 BOOLEAN
MlmeEnqueue(struct rt_rtmp_adapter
*pAd
,
4687 unsigned long Machine
,
4688 unsigned long MsgType
, unsigned long MsgLen
, void * Msg
)
4691 struct rt_mlme_queue
*Queue
= (struct rt_mlme_queue
*)& pAd
->Mlme
.Queue
;
4693 /* Do nothing if the driver is starting halt state. */
4694 /* This might happen when timer already been fired before cancel timer with mlmehalt */
4696 (pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
))
4699 /* First check the size, it MUST not exceed the mlme queue size */
4700 if (MsgLen
> MGMT_DMA_BUFFER_SIZE
) {
4701 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n",
4706 if (MlmeQueueFull(Queue
)) {
4710 NdisAcquireSpinLock(&(Queue
->Lock
));
4714 if (Queue
->Tail
== MAX_LEN_OF_MLME_QUEUE
) {
4718 Queue
->Entry
[Tail
].Wcid
= RESERVED_WCID
;
4719 Queue
->Entry
[Tail
].Occupied
= TRUE
;
4720 Queue
->Entry
[Tail
].Machine
= Machine
;
4721 Queue
->Entry
[Tail
].MsgType
= MsgType
;
4722 Queue
->Entry
[Tail
].MsgLen
= MsgLen
;
4725 NdisMoveMemory(Queue
->Entry
[Tail
].Msg
, Msg
, MsgLen
);
4728 NdisReleaseSpinLock(&(Queue
->Lock
));
4732 /*! \brief This function is used when Recv gets a MLME message
4733 * \param *Queue The MLME Queue
4734 * \param TimeStampHigh The upper 32 bit of timestamp
4735 * \param TimeStampLow The lower 32 bit of timestamp
4736 * \param Rssi The receiving RSSI strength
4737 * \param MsgLen The length of the message
4738 * \param *Msg The message pointer
4739 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4743 IRQL = DISPATCH_LEVEL
4746 BOOLEAN
MlmeEnqueueForRecv(struct rt_rtmp_adapter
*pAd
,
4748 unsigned long TimeStampHigh
,
4749 unsigned long TimeStampLow
,
4753 unsigned long MsgLen
, void * Msg
, u8 Signal
)
4756 struct rt_frame_802_11
* pFrame
= (struct rt_frame_802_11
*) Msg
;
4758 struct rt_mlme_queue
*Queue
= (struct rt_mlme_queue
*)& pAd
->Mlme
.Queue
;
4760 /* Do nothing if the driver is starting halt state. */
4761 /* This might happen when timer already been fired before cancel timer with mlmehalt */
4764 fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
)) {
4765 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4768 /* First check the size, it MUST not exceed the mlme queue size */
4769 if (MsgLen
> MGMT_DMA_BUFFER_SIZE
) {
4770 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen
));
4774 if (MlmeQueueFull(Queue
)) {
4779 if (!MsgTypeSubst(pAd
, pFrame
, &Machine
, &MsgType
)) {
4780 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame
->Hdr
.FC
.SubType
));
4785 /* OK, we got all the informations, it is time to put things into queue */
4786 NdisAcquireSpinLock(&(Queue
->Lock
));
4790 if (Queue
->Tail
== MAX_LEN_OF_MLME_QUEUE
) {
4793 Queue
->Entry
[Tail
].Occupied
= TRUE
;
4794 Queue
->Entry
[Tail
].Machine
= Machine
;
4795 Queue
->Entry
[Tail
].MsgType
= MsgType
;
4796 Queue
->Entry
[Tail
].MsgLen
= MsgLen
;
4797 Queue
->Entry
[Tail
].TimeStamp
.u
.LowPart
= TimeStampLow
;
4798 Queue
->Entry
[Tail
].TimeStamp
.u
.HighPart
= TimeStampHigh
;
4799 Queue
->Entry
[Tail
].Rssi0
= Rssi0
;
4800 Queue
->Entry
[Tail
].Rssi1
= Rssi1
;
4801 Queue
->Entry
[Tail
].Rssi2
= Rssi2
;
4802 Queue
->Entry
[Tail
].Signal
= Signal
;
4803 Queue
->Entry
[Tail
].Wcid
= (u8
)Wcid
;
4805 Queue
->Entry
[Tail
].Channel
= pAd
->LatchRfRegs
.Channel
;
4808 NdisMoveMemory(Queue
->Entry
[Tail
].Msg
, Msg
, MsgLen
);
4811 NdisReleaseSpinLock(&(Queue
->Lock
));
4813 RTMP_MLME_HANDLER(pAd
);
4818 /*! \brief Dequeue a message from the MLME Queue
4819 * \param *Queue The MLME Queue
4820 * \param *Elem The message dequeued from MLME Queue
4821 * \return TRUE if the Elem contains something, FALSE otherwise
4825 IRQL = DISPATCH_LEVEL
4828 BOOLEAN
MlmeDequeue(struct rt_mlme_queue
*Queue
, struct rt_mlme_queue_elem
** Elem
)
4830 NdisAcquireSpinLock(&(Queue
->Lock
));
4831 *Elem
= &(Queue
->Entry
[Queue
->Head
]);
4834 if (Queue
->Head
== MAX_LEN_OF_MLME_QUEUE
) {
4837 NdisReleaseSpinLock(&(Queue
->Lock
));
4841 /* IRQL = DISPATCH_LEVEL */
4842 void MlmeRestartStateMachine(struct rt_rtmp_adapter
*pAd
)
4845 struct rt_mlme_queue_elem
*Elem
= NULL
;
4846 #endif /* RTMP_MAC_PCI // */
4849 DBGPRINT(RT_DEBUG_TRACE
, ("MlmeRestartStateMachine \n"));
4852 NdisAcquireSpinLock(&pAd
->Mlme
.TaskLock
);
4853 if (pAd
->Mlme
.bRunning
) {
4854 NdisReleaseSpinLock(&pAd
->Mlme
.TaskLock
);
4857 pAd
->Mlme
.bRunning
= TRUE
;
4859 NdisReleaseSpinLock(&pAd
->Mlme
.TaskLock
);
4861 /* Remove all Mlme queues elements */
4862 while (!MlmeQueueEmpty(&pAd
->Mlme
.Queue
)) {
4863 /*From message type, determine which state machine I should drive */
4864 if (MlmeDequeue(&pAd
->Mlme
.Queue
, &Elem
)) {
4865 /* free MLME element */
4866 Elem
->Occupied
= FALSE
;
4870 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4873 #endif /* RTMP_MAC_PCI // */
4876 /* Cancel all timer events */
4877 /* Be careful to cancel new added timer */
4878 RTMPCancelTimer(&pAd
->MlmeAux
.AssocTimer
, &Cancelled
);
4879 RTMPCancelTimer(&pAd
->MlmeAux
.ReassocTimer
, &Cancelled
);
4880 RTMPCancelTimer(&pAd
->MlmeAux
.DisassocTimer
, &Cancelled
);
4881 RTMPCancelTimer(&pAd
->MlmeAux
.AuthTimer
, &Cancelled
);
4882 RTMPCancelTimer(&pAd
->MlmeAux
.BeaconTimer
, &Cancelled
);
4883 RTMPCancelTimer(&pAd
->MlmeAux
.ScanTimer
, &Cancelled
);
4887 /* Change back to original channel in case of doing scan */
4888 AsicSwitchChannel(pAd
, pAd
->CommonCfg
.Channel
, FALSE
);
4889 AsicLockChannel(pAd
, pAd
->CommonCfg
.Channel
);
4891 /* Resume MSDU which is turned off durning scan */
4892 RTMPResumeMsduTransmission(pAd
);
4895 /* Set all state machines back IDLE */
4896 pAd
->Mlme
.CntlMachine
.CurrState
= CNTL_IDLE
;
4897 pAd
->Mlme
.AssocMachine
.CurrState
= ASSOC_IDLE
;
4898 pAd
->Mlme
.AuthMachine
.CurrState
= AUTH_REQ_IDLE
;
4899 pAd
->Mlme
.AuthRspMachine
.CurrState
= AUTH_RSP_IDLE
;
4900 pAd
->Mlme
.SyncMachine
.CurrState
= SYNC_IDLE
;
4901 pAd
->Mlme
.ActMachine
.CurrState
= ACT_IDLE
;
4905 /* Remove running state */
4906 NdisAcquireSpinLock(&pAd
->Mlme
.TaskLock
);
4907 pAd
->Mlme
.bRunning
= FALSE
;
4908 NdisReleaseSpinLock(&pAd
->Mlme
.TaskLock
);
4909 #endif /* RTMP_MAC_PCI // */
4912 /*! \brief test if the MLME Queue is empty
4913 * \param *Queue The MLME Queue
4914 * \return TRUE if the Queue is empty, FALSE otherwise
4918 IRQL = DISPATCH_LEVEL
4921 BOOLEAN
MlmeQueueEmpty(struct rt_mlme_queue
*Queue
)
4925 NdisAcquireSpinLock(&(Queue
->Lock
));
4926 Ans
= (Queue
->Num
== 0);
4927 NdisReleaseSpinLock(&(Queue
->Lock
));
4932 /*! \brief test if the MLME Queue is full
4933 * \param *Queue The MLME Queue
4934 * \return TRUE if the Queue is empty, FALSE otherwise
4938 IRQL = PASSIVE_LEVEL
4939 IRQL = DISPATCH_LEVEL
4942 BOOLEAN
MlmeQueueFull(struct rt_mlme_queue
*Queue
)
4946 NdisAcquireSpinLock(&(Queue
->Lock
));
4947 Ans
= (Queue
->Num
== MAX_LEN_OF_MLME_QUEUE
4948 || Queue
->Entry
[Queue
->Tail
].Occupied
);
4949 NdisReleaseSpinLock(&(Queue
->Lock
));
4954 /*! \brief The destructor of MLME Queue
4959 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4961 IRQL = PASSIVE_LEVEL
4964 void MlmeQueueDestroy(struct rt_mlme_queue
*pQueue
)
4966 NdisAcquireSpinLock(&(pQueue
->Lock
));
4970 NdisReleaseSpinLock(&(pQueue
->Lock
));
4971 NdisFreeSpinLock(&(pQueue
->Lock
));
4974 /*! \brief To substitute the message type if the message is coming from external
4975 * \param pFrame The frame received
4976 * \param *Machine The state machine
4977 * \param *MsgType the message type for the state machine
4978 * \return TRUE if the substitution is successful, FALSE otherwise
4982 IRQL = DISPATCH_LEVEL
4985 BOOLEAN
MsgTypeSubst(struct rt_rtmp_adapter
*pAd
,
4986 struct rt_frame_802_11
* pFrame
,
4987 int * Machine
, int * MsgType
)
4993 /* Pointer to start of data frames including SNAP header */
4994 pData
= (u8
*)pFrame
+ LENGTH_802_11
;
4996 /* The only data type will pass to this function is EAPOL frame */
4997 if (pFrame
->Hdr
.FC
.Type
== BTYPE_DATA
) {
4999 *Machine
= WPA_STATE_MACHINE
;
5001 *((u8
*) pFrame
+ LENGTH_802_11
+
5002 LENGTH_802_1_H
+ 1);
5003 return (WpaMsgTypeSubst(EAPType
, (int *) MsgType
));
5007 switch (pFrame
->Hdr
.FC
.SubType
) {
5008 case SUBTYPE_ASSOC_REQ
:
5009 *Machine
= ASSOC_STATE_MACHINE
;
5010 *MsgType
= MT2_PEER_ASSOC_REQ
;
5012 case SUBTYPE_ASSOC_RSP
:
5013 *Machine
= ASSOC_STATE_MACHINE
;
5014 *MsgType
= MT2_PEER_ASSOC_RSP
;
5016 case SUBTYPE_REASSOC_REQ
:
5017 *Machine
= ASSOC_STATE_MACHINE
;
5018 *MsgType
= MT2_PEER_REASSOC_REQ
;
5020 case SUBTYPE_REASSOC_RSP
:
5021 *Machine
= ASSOC_STATE_MACHINE
;
5022 *MsgType
= MT2_PEER_REASSOC_RSP
;
5024 case SUBTYPE_PROBE_REQ
:
5025 *Machine
= SYNC_STATE_MACHINE
;
5026 *MsgType
= MT2_PEER_PROBE_REQ
;
5028 case SUBTYPE_PROBE_RSP
:
5029 *Machine
= SYNC_STATE_MACHINE
;
5030 *MsgType
= MT2_PEER_PROBE_RSP
;
5032 case SUBTYPE_BEACON
:
5033 *Machine
= SYNC_STATE_MACHINE
;
5034 *MsgType
= MT2_PEER_BEACON
;
5037 *Machine
= SYNC_STATE_MACHINE
;
5038 *MsgType
= MT2_PEER_ATIM
;
5040 case SUBTYPE_DISASSOC
:
5041 *Machine
= ASSOC_STATE_MACHINE
;
5042 *MsgType
= MT2_PEER_DISASSOC_REQ
;
5045 /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
5046 NdisMoveMemory(&Seq
, &pFrame
->Octet
[2], sizeof(u16
));
5047 NdisMoveMemory(&Alg
, &pFrame
->Octet
[0], sizeof(u16
));
5048 if (Seq
== 1 || Seq
== 3) {
5049 *Machine
= AUTH_RSP_STATE_MACHINE
;
5050 *MsgType
= MT2_PEER_AUTH_ODD
;
5051 } else if (Seq
== 2 || Seq
== 4) {
5052 if (Alg
== AUTH_MODE_OPEN
|| Alg
== AUTH_MODE_KEY
) {
5053 *Machine
= AUTH_STATE_MACHINE
;
5054 *MsgType
= MT2_PEER_AUTH_EVEN
;
5060 case SUBTYPE_DEAUTH
:
5061 *Machine
= AUTH_RSP_STATE_MACHINE
;
5062 *MsgType
= MT2_PEER_DEAUTH
;
5064 case SUBTYPE_ACTION
:
5065 *Machine
= ACTION_STATE_MACHINE
;
5066 /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
5067 if ((pFrame
->Octet
[0] & 0x7F) > MAX_PEER_CATE_MSG
) {
5068 *MsgType
= MT2_ACT_INVALID
;
5070 *MsgType
= (pFrame
->Octet
[0] & 0x7F);
5081 /* =========================================================================================== */
5082 /* state_machine.c */
5083 /* =========================================================================================== */
5085 /*! \brief Initialize the state machine.
5086 * \param *S pointer to the state machine
5087 * \param Trans State machine transition function
5088 * \param StNr number of states
5089 * \param MsgNr number of messages
5090 * \param DefFunc default function, when there is invalid state/message combination
5091 * \param InitState initial state of the state machine
5092 * \param Base StateMachine base, internal use only
5093 * \pre p_sm should be a legal pointer
5096 IRQL = PASSIVE_LEVEL
5099 void StateMachineInit(struct rt_state_machine
*S
,
5100 IN STATE_MACHINE_FUNC Trans
[],
5102 unsigned long MsgNr
,
5103 IN STATE_MACHINE_FUNC DefFunc
,
5104 unsigned long InitState
, unsigned long Base
)
5108 /* set number of states and messages */
5113 S
->TransFunc
= Trans
;
5115 /* init all state transition to default function */
5116 for (i
= 0; i
< StNr
; i
++) {
5117 for (j
= 0; j
< MsgNr
; j
++) {
5118 S
->TransFunc
[i
* MsgNr
+ j
] = DefFunc
;
5122 /* set the starting state */
5123 S
->CurrState
= InitState
;
5126 /*! \brief This function fills in the function pointer into the cell in the state machine
5127 * \param *S pointer to the state machine
5129 * \param Msg incoming message
5130 * \param f the function to be executed when (state, message) combination occurs at the state machine
5131 * \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
5134 IRQL = PASSIVE_LEVEL
5137 void StateMachineSetAction(struct rt_state_machine
*S
,
5139 unsigned long Msg
, IN STATE_MACHINE_FUNC Func
)
5141 unsigned long MsgIdx
;
5143 MsgIdx
= Msg
- S
->Base
;
5145 if (St
< S
->NrState
&& MsgIdx
< S
->NrMsg
) {
5146 /* boundary checking before setting the action */
5147 S
->TransFunc
[St
* S
->NrMsg
+ MsgIdx
] = Func
;
5151 /*! \brief This function does the state transition
5152 * \param *Adapter the NIC adapter pointer
5153 * \param *S the state machine
5154 * \param *Elem the message to be executed
5157 IRQL = DISPATCH_LEVEL
5160 void StateMachinePerformAction(struct rt_rtmp_adapter
*pAd
,
5161 struct rt_state_machine
*S
, struct rt_mlme_queue_elem
*Elem
)
5163 (*(S
->TransFunc
[S
->CurrState
* S
->NrMsg
+ Elem
->MsgType
- S
->Base
]))
5168 ==========================================================================
5170 The drop function, when machine executes this, the message is simply
5171 ignored. This function does nothing, the message is freed in
5172 StateMachinePerformAction()
5173 ==========================================================================
5175 void Drop(struct rt_rtmp_adapter
*pAd
, struct rt_mlme_queue_elem
*Elem
)
5179 /* =========================================================================================== */
5181 /* =========================================================================================== */
5184 ==========================================================================
5187 IRQL = PASSIVE_LEVEL
5189 ==========================================================================
5191 void LfsrInit(struct rt_rtmp_adapter
*pAd
, unsigned long Seed
)
5194 pAd
->Mlme
.ShiftReg
= 1;
5196 pAd
->Mlme
.ShiftReg
= Seed
;
5200 ==========================================================================
5202 ==========================================================================
5204 u8
RandomByte(struct rt_rtmp_adapter
*pAd
)
5211 if (pAd
->Mlme
.ShiftReg
== 0)
5212 NdisGetSystemUpTime((unsigned long *) & pAd
->Mlme
.ShiftReg
);
5214 for (i
= 0; i
< 8; i
++) {
5215 if (pAd
->Mlme
.ShiftReg
& 0x00000001) {
5216 pAd
->Mlme
.ShiftReg
=
5218 ShiftReg
^ LFSR_MASK
) >> 1) | 0x80000000;
5221 pAd
->Mlme
.ShiftReg
= pAd
->Mlme
.ShiftReg
>> 1;
5224 R
= (R
<< 1) | Result
;
5231 ========================================================================
5233 Routine Description:
5234 Verify the support rate for different PHY type
5237 pAd Pointer to our adapter
5242 IRQL = PASSIVE_LEVEL
5244 ========================================================================
5246 void RTMPCheckRates(struct rt_rtmp_adapter
*pAd
,
5247 IN u8 SupRate
[], IN u8
* SupRateLen
)
5250 u8 NewRate
[12], NewRateLen
;
5254 if (pAd
->CommonCfg
.PhyMode
== PHY_11B
)
5259 /* Check for support rates exclude basic rate bit */
5260 for (i
= 0; i
< *SupRateLen
; i
++)
5261 for (j
= 0; j
< RateIdx
; j
++)
5262 if ((SupRate
[i
] & 0x7f) == RateIdTo500Kbps
[j
])
5263 NewRate
[NewRateLen
++] = SupRate
[i
];
5265 *SupRateLen
= NewRateLen
;
5266 NdisMoveMemory(SupRate
, NewRate
, NewRateLen
);
5269 BOOLEAN
RTMPCheckChannel(struct rt_rtmp_adapter
*pAd
,
5270 u8 CentralChannel
, u8 Channel
)
5273 u8 UpperChannel
= 0, LowerChannel
= 0;
5274 u8 NoEffectChannelinList
= 0;
5276 /* Find upper and lower channel according to 40MHz current operation. */
5277 if (CentralChannel
< Channel
) {
5278 UpperChannel
= Channel
;
5279 if (CentralChannel
> 2)
5280 LowerChannel
= CentralChannel
- 2;
5283 } else if (CentralChannel
> Channel
) {
5284 UpperChannel
= CentralChannel
+ 2;
5285 LowerChannel
= Channel
;
5288 for (k
= 0; k
< pAd
->ChannelListNum
; k
++) {
5289 if (pAd
->ChannelList
[k
].Channel
== UpperChannel
) {
5290 NoEffectChannelinList
++;
5292 if (pAd
->ChannelList
[k
].Channel
== LowerChannel
) {
5293 NoEffectChannelinList
++;
5297 DBGPRINT(RT_DEBUG_TRACE
,
5298 ("Total Channel in Channel List = [%d]\n",
5299 NoEffectChannelinList
));
5300 if (NoEffectChannelinList
== 2)
5307 ========================================================================
5309 Routine Description:
5310 Verify the support rate for HT phy type
5313 pAd Pointer to our adapter
5316 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
5318 IRQL = PASSIVE_LEVEL
5320 ========================================================================
5322 BOOLEAN
RTMPCheckHt(struct rt_rtmp_adapter
*pAd
,
5324 struct rt_ht_capability_ie
* pHtCapability
,
5325 struct rt_add_ht_info_ie
* pAddHtInfo
)
5327 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
)
5330 /* If use AMSDU, set flag. */
5331 if (pAd
->CommonCfg
.DesiredHtPhy
.AmsduEnable
)
5332 CLIENT_STATUS_SET_FLAG(&pAd
->MacTab
.Content
[Wcid
],
5333 fCLIENT_STATUS_AMSDU_INUSED
);
5334 /* Save Peer Capability */
5335 if (pHtCapability
->HtCapInfo
.ShortGIfor20
)
5336 CLIENT_STATUS_SET_FLAG(&pAd
->MacTab
.Content
[Wcid
],
5337 fCLIENT_STATUS_SGI20_CAPABLE
);
5338 if (pHtCapability
->HtCapInfo
.ShortGIfor40
)
5339 CLIENT_STATUS_SET_FLAG(&pAd
->MacTab
.Content
[Wcid
],
5340 fCLIENT_STATUS_SGI40_CAPABLE
);
5341 if (pHtCapability
->HtCapInfo
.TxSTBC
)
5342 CLIENT_STATUS_SET_FLAG(&pAd
->MacTab
.Content
[Wcid
],
5343 fCLIENT_STATUS_TxSTBC_CAPABLE
);
5344 if (pHtCapability
->HtCapInfo
.RxSTBC
)
5345 CLIENT_STATUS_SET_FLAG(&pAd
->MacTab
.Content
[Wcid
],
5346 fCLIENT_STATUS_RxSTBC_CAPABLE
);
5347 if (pAd
->CommonCfg
.bRdg
&& pHtCapability
->ExtHtCapInfo
.RDGSupport
) {
5348 CLIENT_STATUS_SET_FLAG(&pAd
->MacTab
.Content
[Wcid
],
5349 fCLIENT_STATUS_RDG_CAPABLE
);
5352 if (Wcid
< MAX_LEN_OF_MAC_TABLE
) {
5353 pAd
->MacTab
.Content
[Wcid
].MpduDensity
=
5354 pHtCapability
->HtCapParm
.MpduDensity
;
5356 /* Will check ChannelWidth for MCSSet[4] below */
5357 pAd
->MlmeAux
.HtCapability
.MCSSet
[4] = 0x1;
5358 switch (pAd
->CommonCfg
.RxStream
) {
5360 pAd
->MlmeAux
.HtCapability
.MCSSet
[0] = 0xff;
5361 pAd
->MlmeAux
.HtCapability
.MCSSet
[1] = 0x00;
5362 pAd
->MlmeAux
.HtCapability
.MCSSet
[2] = 0x00;
5363 pAd
->MlmeAux
.HtCapability
.MCSSet
[3] = 0x00;
5366 pAd
->MlmeAux
.HtCapability
.MCSSet
[0] = 0xff;
5367 pAd
->MlmeAux
.HtCapability
.MCSSet
[1] = 0xff;
5368 pAd
->MlmeAux
.HtCapability
.MCSSet
[2] = 0x00;
5369 pAd
->MlmeAux
.HtCapability
.MCSSet
[3] = 0x00;
5372 pAd
->MlmeAux
.HtCapability
.MCSSet
[0] = 0xff;
5373 pAd
->MlmeAux
.HtCapability
.MCSSet
[1] = 0xff;
5374 pAd
->MlmeAux
.HtCapability
.MCSSet
[2] = 0xff;
5375 pAd
->MlmeAux
.HtCapability
.MCSSet
[3] = 0x00;
5379 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.ChannelWidth
=
5380 pAddHtInfo
->AddHtInfo
.RecomWidth
& pAd
->CommonCfg
.DesiredHtPhy
.
5383 DBGPRINT(RT_DEBUG_TRACE
,
5384 ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5385 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.ChannelWidth
,
5386 pAddHtInfo
->AddHtInfo
.RecomWidth
,
5387 pAd
->CommonCfg
.DesiredHtPhy
.ChannelWidth
,
5388 pAd
->NicConfig2
.field
.BW40MAvailForA
,
5389 pAd
->NicConfig2
.field
.BW40MAvailForG
,
5390 pAd
->CommonCfg
.PhyMode
));
5392 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.GF
=
5393 pHtCapability
->HtCapInfo
.GF
& pAd
->CommonCfg
.DesiredHtPhy
.GF
;
5395 /* Send Assoc Req with my HT capability. */
5396 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.AMsduSize
=
5397 pAd
->CommonCfg
.DesiredHtPhy
.AmsduSize
;
5398 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.MimoPs
=
5399 pAd
->CommonCfg
.DesiredHtPhy
.MimoPs
;
5400 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.ShortGIfor20
=
5401 (pAd
->CommonCfg
.DesiredHtPhy
.ShortGIfor20
) & (pHtCapability
->
5404 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.ShortGIfor40
=
5405 (pAd
->CommonCfg
.DesiredHtPhy
.ShortGIfor40
) & (pHtCapability
->
5408 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.TxSTBC
=
5409 (pAd
->CommonCfg
.DesiredHtPhy
.TxSTBC
) & (pHtCapability
->HtCapInfo
.
5411 pAd
->MlmeAux
.HtCapability
.HtCapInfo
.RxSTBC
=
5412 (pAd
->CommonCfg
.DesiredHtPhy
.RxSTBC
) & (pHtCapability
->HtCapInfo
.
5414 pAd
->MlmeAux
.HtCapability
.HtCapParm
.MaxRAmpduFactor
=
5415 pAd
->CommonCfg
.DesiredHtPhy
.MaxRAmpduFactor
;
5416 pAd
->MlmeAux
.HtCapability
.HtCapParm
.MpduDensity
=
5417 pAd
->CommonCfg
.HtCapability
.HtCapParm
.MpduDensity
;
5418 pAd
->MlmeAux
.HtCapability
.ExtHtCapInfo
.PlusHTC
=
5419 pHtCapability
->ExtHtCapInfo
.PlusHTC
;
5420 pAd
->MacTab
.Content
[Wcid
].HTCapability
.ExtHtCapInfo
.PlusHTC
=
5421 pHtCapability
->ExtHtCapInfo
.PlusHTC
;
5422 if (pAd
->CommonCfg
.bRdg
) {
5423 pAd
->MlmeAux
.HtCapability
.ExtHtCapInfo
.RDGSupport
=
5424 pHtCapability
->ExtHtCapInfo
.RDGSupport
;
5425 pAd
->MlmeAux
.HtCapability
.ExtHtCapInfo
.PlusHTC
= 1;
5428 if (pAd
->MlmeAux
.HtCapability
.HtCapInfo
.ChannelWidth
== BW_20
)
5429 pAd
->MlmeAux
.HtCapability
.MCSSet
[4] = 0x0; /* BW20 can't transmit MCS32 */
5431 COPY_AP_HTSETTINGS_FROM_BEACON(pAd
, pHtCapability
);
5436 ========================================================================
5438 Routine Description:
5439 Verify the support rate for different PHY type
5442 pAd Pointer to our adapter
5447 IRQL = PASSIVE_LEVEL
5449 ========================================================================
5451 void RTMPUpdateMlmeRate(struct rt_rtmp_adapter
*pAd
)
5454 u8 ProperMlmeRate
; /*= RATE_54; */
5455 u8 i
, j
, RateIdx
= 12; /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
5456 BOOLEAN bMatch
= FALSE
;
5458 switch (pAd
->CommonCfg
.PhyMode
) {
5460 ProperMlmeRate
= RATE_11
;
5461 MinimumRate
= RATE_1
;
5463 case PHY_11BG_MIXED
:
5464 case PHY_11ABGN_MIXED
:
5465 case PHY_11BGN_MIXED
:
5466 if ((pAd
->MlmeAux
.SupRateLen
== 4) &&
5467 (pAd
->MlmeAux
.ExtRateLen
== 0))
5469 ProperMlmeRate
= RATE_11
;
5471 ProperMlmeRate
= RATE_24
;
5473 if (pAd
->MlmeAux
.Channel
<= 14)
5474 MinimumRate
= RATE_1
;
5476 MinimumRate
= RATE_6
;
5479 case PHY_11N_2_4G
: /* rt2860 need to check mlmerate for 802.11n */
5480 case PHY_11GN_MIXED
:
5481 case PHY_11AGN_MIXED
:
5482 case PHY_11AN_MIXED
:
5484 ProperMlmeRate
= RATE_24
;
5485 MinimumRate
= RATE_6
;
5487 case PHY_11ABG_MIXED
:
5488 ProperMlmeRate
= RATE_24
;
5489 if (pAd
->MlmeAux
.Channel
<= 14)
5490 MinimumRate
= RATE_1
;
5492 MinimumRate
= RATE_6
;
5494 default: /* error */
5495 ProperMlmeRate
= RATE_1
;
5496 MinimumRate
= RATE_1
;
5500 for (i
= 0; i
< pAd
->MlmeAux
.SupRateLen
; i
++) {
5501 for (j
= 0; j
< RateIdx
; j
++) {
5502 if ((pAd
->MlmeAux
.SupRate
[i
] & 0x7f) ==
5503 RateIdTo500Kbps
[j
]) {
5504 if (j
== ProperMlmeRate
) {
5515 if (bMatch
== FALSE
) {
5516 for (i
= 0; i
< pAd
->MlmeAux
.ExtRateLen
; i
++) {
5517 for (j
= 0; j
< RateIdx
; j
++) {
5518 if ((pAd
->MlmeAux
.ExtRate
[i
] & 0x7f) ==
5519 RateIdTo500Kbps
[j
]) {
5520 if (j
== ProperMlmeRate
) {
5532 if (bMatch
== FALSE
) {
5533 ProperMlmeRate
= MinimumRate
;
5536 pAd
->CommonCfg
.MlmeRate
= MinimumRate
;
5537 pAd
->CommonCfg
.RtsRate
= ProperMlmeRate
;
5538 if (pAd
->CommonCfg
.MlmeRate
>= RATE_6
) {
5539 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
= MODE_OFDM
;
5540 pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
=
5541 OfdmRateToRxwiMCS
[pAd
->CommonCfg
.MlmeRate
];
5542 pAd
->MacTab
.Content
[BSS0Mcast_WCID
].HTPhyMode
.field
.MODE
=
5544 pAd
->MacTab
.Content
[BSS0Mcast_WCID
].HTPhyMode
.field
.MCS
=
5545 OfdmRateToRxwiMCS
[pAd
->CommonCfg
.MlmeRate
];
5547 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
= MODE_CCK
;
5548 pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
= pAd
->CommonCfg
.MlmeRate
;
5549 pAd
->MacTab
.Content
[BSS0Mcast_WCID
].HTPhyMode
.field
.MODE
=
5551 pAd
->MacTab
.Content
[BSS0Mcast_WCID
].HTPhyMode
.field
.MCS
=
5552 pAd
->CommonCfg
.MlmeRate
;
5555 DBGPRINT(RT_DEBUG_TRACE
,
5556 ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n",
5557 pAd
->CommonCfg
.MlmeTransmit
.word
));
5560 char RTMPMaxRssi(struct rt_rtmp_adapter
*pAd
,
5561 char Rssi0
, char Rssi1
, char Rssi2
)
5565 if ((pAd
->Antenna
.field
.RxPath
== 1) && (Rssi0
!= 0)) {
5569 if ((pAd
->Antenna
.field
.RxPath
>= 2) && (Rssi1
!= 0)) {
5570 larger
= max(Rssi0
, Rssi1
);
5573 if ((pAd
->Antenna
.field
.RxPath
== 3) && (Rssi2
!= 0)) {
5574 larger
= max(larger
, Rssi2
);
5584 ========================================================================
5585 Routine Description:
5586 Periodic evaluate antenna link status
5589 pAd - Adapter pointer
5594 ========================================================================
5596 void AsicEvaluateRxAnt(struct rt_rtmp_adapter
*pAd
)
5600 if (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_RESET_IN_PROGRESS
|
5601 fRTMP_ADAPTER_HALT_IN_PROGRESS
|
5602 fRTMP_ADAPTER_RADIO_OFF
|
5603 fRTMP_ADAPTER_NIC_NOT_EXIST
|
5604 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS
) ||
5605 OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
)
5607 || (pAd
->EepromAccess
)
5608 #endif /* RT30xx // */
5610 || (pAd
->bPCIclkOff
== TRUE
)
5611 #endif /* RT3090 // */
5616 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5621 if (pAd
->StaCfg
.Psm
== PWR_SAVE
)
5624 RTMP_BBP_IO_READ8_BY_REG_ID(pAd
, BBP_R3
, &BBPR3
);
5626 if (pAd
->Antenna
.field
.RxPath
== 3) {
5628 } else if (pAd
->Antenna
.field
.RxPath
== 2) {
5630 } else if (pAd
->Antenna
.field
.RxPath
== 1) {
5633 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd
, BBP_R3
, BBPR3
);
5635 pAd
->StaCfg
.BBPR3
= BBPR3
;
5636 #endif /* RTMP_MAC_PCI // */
5637 if (OPSTATUS_TEST_FLAG
5638 (pAd
, fOP_STATUS_MEDIA_STATE_CONNECTED
)
5640 unsigned long TxTotalCnt
=
5641 pAd
->RalinkCounters
.OneSecTxNoRetryOkCount
+
5642 pAd
->RalinkCounters
.OneSecTxRetryOkCount
+
5643 pAd
->RalinkCounters
.OneSecTxFailCount
;
5645 /* dynamic adjust antenna evaluation period according to the traffic */
5646 if (TxTotalCnt
> 50) {
5647 RTMPSetTimer(&pAd
->Mlme
.RxAntEvalTimer
,
5649 pAd
->Mlme
.bLowThroughput
= FALSE
;
5651 RTMPSetTimer(&pAd
->Mlme
.RxAntEvalTimer
,
5653 pAd
->Mlme
.bLowThroughput
= TRUE
;
5663 ========================================================================
5664 Routine Description:
5665 After evaluation, check antenna link status
5668 pAd - Adapter pointer
5673 ========================================================================
5675 void AsicRxAntEvalTimeout(void *SystemSpecific1
,
5676 void *FunctionContext
,
5677 void *SystemSpecific2
, void *SystemSpecific3
)
5679 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)FunctionContext
;
5681 char larger
= -127, rssi0
, rssi1
, rssi2
;
5683 if (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_RESET_IN_PROGRESS
|
5684 fRTMP_ADAPTER_HALT_IN_PROGRESS
|
5685 fRTMP_ADAPTER_RADIO_OFF
|
5686 fRTMP_ADAPTER_NIC_NOT_EXIST
) ||
5687 OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
)
5689 || (pAd
->EepromAccess
)
5690 #endif /* RT30xx // */
5692 || (pAd
->bPCIclkOff
== TRUE
)
5693 #endif /* RT3090 // */
5698 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5701 if (pAd
->StaCfg
.Psm
== PWR_SAVE
)
5704 /* if the traffic is low, use average rssi as the criteria */
5705 if (pAd
->Mlme
.bLowThroughput
== TRUE
) {
5706 rssi0
= pAd
->StaCfg
.RssiSample
.LastRssi0
;
5707 rssi1
= pAd
->StaCfg
.RssiSample
.LastRssi1
;
5708 rssi2
= pAd
->StaCfg
.RssiSample
.LastRssi2
;
5710 rssi0
= pAd
->StaCfg
.RssiSample
.AvgRssi0
;
5711 rssi1
= pAd
->StaCfg
.RssiSample
.AvgRssi1
;
5712 rssi2
= pAd
->StaCfg
.RssiSample
.AvgRssi2
;
5715 if (pAd
->Antenna
.field
.RxPath
== 3) {
5716 larger
= max(rssi0
, rssi1
);
5718 if (larger
> (rssi2
+ 20))
5719 pAd
->Mlme
.RealRxPath
= 2;
5721 pAd
->Mlme
.RealRxPath
= 3;
5722 } else if (pAd
->Antenna
.field
.RxPath
== 2) {
5723 if (rssi0
> (rssi1
+ 20))
5724 pAd
->Mlme
.RealRxPath
= 1;
5726 pAd
->Mlme
.RealRxPath
= 2;
5729 RTMP_BBP_IO_READ8_BY_REG_ID(pAd
, BBP_R3
, &BBPR3
);
5731 if (pAd
->Mlme
.RealRxPath
== 3) {
5733 } else if (pAd
->Mlme
.RealRxPath
== 2) {
5735 } else if (pAd
->Mlme
.RealRxPath
== 1) {
5738 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd
, BBP_R3
, BBPR3
);
5740 pAd
->StaCfg
.BBPR3
= BBPR3
;
5741 #endif /* RTMP_MAC_PCI // */
5747 void APSDPeriodicExec(void *SystemSpecific1
,
5748 void *FunctionContext
,
5749 void *SystemSpecific2
, void *SystemSpecific3
)
5751 struct rt_rtmp_adapter
*pAd
= (struct rt_rtmp_adapter
*)FunctionContext
;
5753 if (!OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_MEDIA_STATE_CONNECTED
))
5756 pAd
->CommonCfg
.TriggerTimerCount
++;
5758 /* Driver should not send trigger frame, it should be send by application layer */
5760 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5761 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5762 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5764 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5765 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5766 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5767 pAd->CommonCfg.TriggerTimerCount = 0;
5768 pAd->CommonCfg.bInServicePeriod = TRUE;
5773 ========================================================================
5774 Routine Description:
5775 Set/reset MAC registers according to bPiggyBack parameter
5778 pAd - Adapter pointer
5779 bPiggyBack - Enable / Disable Piggy-Back
5784 ========================================================================
5786 void RTMPSetPiggyBack(struct rt_rtmp_adapter
*pAd
, IN BOOLEAN bPiggyBack
)
5788 TX_LINK_CFG_STRUC TxLinkCfg
;
5790 RTMP_IO_READ32(pAd
, TX_LINK_CFG
, &TxLinkCfg
.word
);
5792 TxLinkCfg
.field
.TxCFAckEn
= bPiggyBack
;
5793 RTMP_IO_WRITE32(pAd
, TX_LINK_CFG
, TxLinkCfg
.word
);
5797 ========================================================================
5798 Routine Description:
5799 check if this entry need to switch rate automatically
5809 ========================================================================
5811 BOOLEAN
RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter
*pAd
,
5812 struct rt_mac_table_entry
*pEntry
)
5814 BOOLEAN result
= TRUE
;
5817 /* only associated STA counts */
5818 if (pEntry
&& (pEntry
->ValidAsCLI
)
5819 && (pEntry
->Sst
== SST_ASSOC
)) {
5820 result
= pAd
->StaCfg
.bAutoTxRateSwitch
;
5828 BOOLEAN
RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter
*pAd
)
5831 if (pAd
->StaCfg
.bAutoTxRateSwitch
)
5838 ========================================================================
5839 Routine Description:
5840 check if this entry need to fix tx legacy rate
5850 ========================================================================
5852 u8
RTMPStaFixedTxMode(struct rt_rtmp_adapter
*pAd
, struct rt_mac_table_entry
*pEntry
)
5854 u8 tx_mode
= FIXED_TXMODE_HT
;
5858 (u8
)pAd
->StaCfg
.DesiredTransmitSetting
.field
.
5866 ========================================================================
5867 Routine Description:
5868 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5878 ========================================================================
5880 void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode
, struct rt_mac_table_entry
*pEntry
)
5882 HTTRANSMIT_SETTING TransmitSetting
;
5884 if (fixed_tx_mode
== FIXED_TXMODE_HT
)
5887 TransmitSetting
.word
= 0;
5889 TransmitSetting
.field
.MODE
= pEntry
->HTPhyMode
.field
.MODE
;
5890 TransmitSetting
.field
.MCS
= pEntry
->HTPhyMode
.field
.MCS
;
5892 if (fixed_tx_mode
== FIXED_TXMODE_CCK
) {
5893 TransmitSetting
.field
.MODE
= MODE_CCK
;
5894 /* CCK mode allow MCS 0~3 */
5895 if (TransmitSetting
.field
.MCS
> MCS_3
)
5896 TransmitSetting
.field
.MCS
= MCS_3
;
5898 TransmitSetting
.field
.MODE
= MODE_OFDM
;
5899 /* OFDM mode allow MCS 0~7 */
5900 if (TransmitSetting
.field
.MCS
> MCS_7
)
5901 TransmitSetting
.field
.MCS
= MCS_7
;
5904 if (pEntry
->HTPhyMode
.field
.MODE
>= TransmitSetting
.field
.MODE
) {
5905 pEntry
->HTPhyMode
.word
= TransmitSetting
.word
;
5906 DBGPRINT(RT_DEBUG_TRACE
,
5907 ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5908 pEntry
->Aid
, GetPhyMode(pEntry
->HTPhyMode
.field
.MODE
),
5909 pEntry
->HTPhyMode
.field
.MCS
));
5914 ==========================================================================
5916 dynamic tune BBP R66 to find a balance between sensibility and
5919 IRQL = DISPATCH_LEVEL
5921 ==========================================================================
5923 void AsicStaBbpTuning(struct rt_rtmp_adapter
*pAd
)
5925 u8 OrigR66Value
= 0, R66
; /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */
5928 /* 2860C did not support Fase CCA, therefore can't tune */
5929 if (pAd
->MACVersion
== 0x28600100)
5935 if (pAd
->Mlme
.CntlMachine
.CurrState
!= CNTL_IDLE
) /* no R66 tuning when SCANNING */
5938 if ((pAd
->OpMode
== OPMODE_STA
)
5939 && (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_MEDIA_STATE_CONNECTED
)
5941 && !(OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
))
5943 && (pAd
->bPCIclkOff
== FALSE
)
5944 #endif /* RTMP_MAC_PCI // */
5946 RTMP_BBP_IO_READ8_BY_REG_ID(pAd
, BBP_R66
, &OrigR66Value
);
5949 if (pAd
->Antenna
.field
.RxPath
> 1)
5951 (pAd
->StaCfg
.RssiSample
.AvgRssi0
+
5952 pAd
->StaCfg
.RssiSample
.AvgRssi1
) >> 1;
5954 Rssi
= pAd
->StaCfg
.RssiSample
.AvgRssi0
;
5956 if (pAd
->LatchRfRegs
.Channel
<= 14) { /*BG band */
5958 /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */
5959 /* Otherwise, it will have some throughput side effect when low RSSI */
5961 if (IS_RT3070(pAd
) || IS_RT3090(pAd
) || IS_RT3572(pAd
)
5962 || IS_RT3390(pAd
)) {
5963 if (Rssi
> RSSI_FOR_MID_LOW_SENSIBILITY
) {
5965 0x1C + 2 * GET_LNA_GAIN(pAd
) + 0x20;
5966 if (OrigR66Value
!= R66
) {
5967 RTMP_BBP_IO_WRITE8_BY_REG_ID
5968 (pAd
, BBP_R66
, R66
);
5971 R66
= 0x1C + 2 * GET_LNA_GAIN(pAd
);
5972 if (OrigR66Value
!= R66
) {
5973 RTMP_BBP_IO_WRITE8_BY_REG_ID
5974 (pAd
, BBP_R66
, R66
);
5978 #endif /* RT30xx // */
5980 if (Rssi
> RSSI_FOR_MID_LOW_SENSIBILITY
) {
5981 R66
= (0x2E + GET_LNA_GAIN(pAd
)) + 0x10;
5982 if (OrigR66Value
!= R66
) {
5983 RTMP_BBP_IO_WRITE8_BY_REG_ID
5984 (pAd
, BBP_R66
, R66
);
5987 R66
= 0x2E + GET_LNA_GAIN(pAd
);
5988 if (OrigR66Value
!= R66
) {
5989 RTMP_BBP_IO_WRITE8_BY_REG_ID
5990 (pAd
, BBP_R66
, R66
);
5994 } else { /*A band */
5995 if (pAd
->CommonCfg
.BBPCurrentBW
== BW_20
) {
5996 if (Rssi
> RSSI_FOR_MID_LOW_SENSIBILITY
) {
5998 0x32 + (GET_LNA_GAIN(pAd
) * 5) / 3 +
6000 if (OrigR66Value
!= R66
) {
6001 RTMP_BBP_IO_WRITE8_BY_REG_ID
6002 (pAd
, BBP_R66
, R66
);
6006 0x32 + (GET_LNA_GAIN(pAd
) * 5) / 3;
6007 if (OrigR66Value
!= R66
) {
6008 RTMP_BBP_IO_WRITE8_BY_REG_ID
6009 (pAd
, BBP_R66
, R66
);
6013 if (Rssi
> RSSI_FOR_MID_LOW_SENSIBILITY
) {
6015 0x3A + (GET_LNA_GAIN(pAd
) * 5) / 3 +
6017 if (OrigR66Value
!= R66
) {
6018 RTMP_BBP_IO_WRITE8_BY_REG_ID
6019 (pAd
, BBP_R66
, R66
);
6023 0x3A + (GET_LNA_GAIN(pAd
) * 5) / 3;
6024 if (OrigR66Value
!= R66
) {
6025 RTMP_BBP_IO_WRITE8_BY_REG_ID
6026 (pAd
, BBP_R66
, R66
);
6035 void RTMPSetAGCInitValue(struct rt_rtmp_adapter
*pAd
, u8 BandWidth
)
6039 if (pAd
->LatchRfRegs
.Channel
<= 14) { /* BG band */
6041 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6043 if (IS_RT3070(pAd
) || IS_RT3090(pAd
) || IS_RT3572(pAd
)
6044 || IS_RT3390(pAd
)) {
6045 R66
= 0x1C + 2 * GET_LNA_GAIN(pAd
);
6046 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd
, BBP_R66
, R66
);
6048 #endif /* RT30xx // */
6050 R66
= 0x2E + GET_LNA_GAIN(pAd
);
6051 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd
, BBP_R66
, R66
);
6053 } else { /*A band */
6055 if (BandWidth
== BW_20
) {
6058 (GET_LNA_GAIN(pAd
) * 5) / 3);
6059 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd
, BBP_R66
, R66
);
6063 (GET_LNA_GAIN(pAd
) * 5) / 3);
6064 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd
, BBP_R66
, R66
);