Staging: rt28x0: run common/*.c files through Lindent
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2860 / common / mlme.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27         Module Name:
28         mlme.c
29
30         Abstract:
31
32         Revision History:
33         Who                     When                    What
34         --------        ----------              ----------------------------------------------
35         John Chang      2004-08-25              Modify from RT2500 code base
36         John Chang      2004-09-06              modified for RT2600
37 */
38
39 #include "../rt_config.h"
40 #include <stdarg.h>
41
42 UCHAR CISCO_OUI[] = { 0x00, 0x40, 0x96 };
43
44 UCHAR WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
45 UCHAR RSN_OUI[] = { 0x00, 0x0f, 0xac };
46 UCHAR WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
47 UCHAR WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
48 UCHAR Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 };
49 UCHAR RALINK_OUI[] = { 0x00, 0x0c, 0x43 };
50 UCHAR BROADCOM_OUI[] = { 0x00, 0x90, 0x4c };
51 UCHAR WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
52 UCHAR PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c };
53
54 UCHAR RateSwitchTable[] = {
55 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
56         0x11, 0x00, 0, 0, 0,    // Initial used item after association
57         0x00, 0x00, 0, 40, 101,
58         0x01, 0x00, 1, 40, 50,
59         0x02, 0x00, 2, 35, 45,
60         0x03, 0x00, 3, 20, 45,
61         0x04, 0x21, 0, 30, 50,
62         0x05, 0x21, 1, 20, 50,
63         0x06, 0x21, 2, 20, 50,
64         0x07, 0x21, 3, 15, 50,
65         0x08, 0x21, 4, 15, 30,
66         0x09, 0x21, 5, 10, 25,
67         0x0a, 0x21, 6, 8, 25,
68         0x0b, 0x21, 7, 8, 25,
69         0x0c, 0x20, 12, 15, 30,
70         0x0d, 0x20, 13, 8, 20,
71         0x0e, 0x20, 14, 8, 20,
72         0x0f, 0x20, 15, 8, 25,
73         0x10, 0x22, 15, 8, 25,
74         0x11, 0x00, 0, 0, 0,
75         0x12, 0x00, 0, 0, 0,
76         0x13, 0x00, 0, 0, 0,
77         0x14, 0x00, 0, 0, 0,
78         0x15, 0x00, 0, 0, 0,
79         0x16, 0x00, 0, 0, 0,
80         0x17, 0x00, 0, 0, 0,
81         0x18, 0x00, 0, 0, 0,
82         0x19, 0x00, 0, 0, 0,
83         0x1a, 0x00, 0, 0, 0,
84         0x1b, 0x00, 0, 0, 0,
85         0x1c, 0x00, 0, 0, 0,
86         0x1d, 0x00, 0, 0, 0,
87         0x1e, 0x00, 0, 0, 0,
88         0x1f, 0x00, 0, 0, 0,
89 };
90
91 UCHAR RateSwitchTable11B[] = {
92 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
93         0x04, 0x03, 0, 0, 0,    // Initial used item after association
94         0x00, 0x00, 0, 40, 101,
95         0x01, 0x00, 1, 40, 50,
96         0x02, 0x00, 2, 35, 45,
97         0x03, 0x00, 3, 20, 45,
98 };
99
100 UCHAR RateSwitchTable11BG[] = {
101 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
102         0x0a, 0x00, 0, 0, 0,    // Initial used item after association
103         0x00, 0x00, 0, 40, 101,
104         0x01, 0x00, 1, 40, 50,
105         0x02, 0x00, 2, 35, 45,
106         0x03, 0x00, 3, 20, 45,
107         0x04, 0x10, 2, 20, 35,
108         0x05, 0x10, 3, 16, 35,
109         0x06, 0x10, 4, 10, 25,
110         0x07, 0x10, 5, 16, 25,
111         0x08, 0x10, 6, 10, 25,
112         0x09, 0x10, 7, 10, 13,
113 };
114
115 UCHAR RateSwitchTable11G[] = {
116 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
117         0x08, 0x00, 0, 0, 0,    // Initial used item after association
118         0x00, 0x10, 0, 20, 101,
119         0x01, 0x10, 1, 20, 35,
120         0x02, 0x10, 2, 20, 35,
121         0x03, 0x10, 3, 16, 35,
122         0x04, 0x10, 4, 10, 25,
123         0x05, 0x10, 5, 16, 25,
124         0x06, 0x10, 6, 10, 25,
125         0x07, 0x10, 7, 10, 13,
126 };
127
128 UCHAR RateSwitchTable11N1S[] = {
129 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
130         0x0c, 0x0a, 0, 0, 0,    // Initial used item after association
131         0x00, 0x00, 0, 40, 101,
132         0x01, 0x00, 1, 40, 50,
133         0x02, 0x00, 2, 25, 45,
134         0x03, 0x21, 0, 20, 35,
135         0x04, 0x21, 1, 20, 35,
136         0x05, 0x21, 2, 20, 35,
137         0x06, 0x21, 3, 15, 35,
138         0x07, 0x21, 4, 15, 30,
139         0x08, 0x21, 5, 10, 25,
140         0x09, 0x21, 6, 8, 14,
141         0x0a, 0x21, 7, 8, 14,
142         0x0b, 0x23, 7, 8, 14,
143 };
144
145 UCHAR RateSwitchTable11N2S[] = {
146 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
147         0x0e, 0x0c, 0, 0, 0,    // Initial used item after association
148         0x00, 0x00, 0, 40, 101,
149         0x01, 0x00, 1, 40, 50,
150         0x02, 0x00, 2, 25, 45,
151         0x03, 0x21, 0, 20, 35,
152         0x04, 0x21, 1, 20, 35,
153         0x05, 0x21, 2, 20, 35,
154         0x06, 0x21, 3, 15, 35,
155         0x07, 0x21, 4, 15, 30,
156         0x08, 0x20, 11, 15, 30,
157         0x09, 0x20, 12, 15, 30,
158         0x0a, 0x20, 13, 8, 20,
159         0x0b, 0x20, 14, 8, 20,
160         0x0c, 0x20, 15, 8, 25,
161         0x0d, 0x22, 15, 8, 15,
162 };
163
164 UCHAR RateSwitchTable11N3S[] = {
165 // Item No.     Mode    Curr-MCS        TrainUp TrainDown       // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
166         0x0b, 0x00, 0, 0, 0,    // 0x0a, 0x00,  0,  0,  0,      // Initial used item after association
167         0x00, 0x21, 0, 30, 101,
168         0x01, 0x21, 1, 20, 50,
169         0x02, 0x21, 2, 20, 50,
170         0x03, 0x21, 3, 15, 50,
171         0x04, 0x21, 4, 15, 30,
172         0x05, 0x20, 11, 15, 30, // Required by System-Alan @ 20080812
173         0x06, 0x20, 12, 15, 30, // 0x05, 0x20, 12, 15, 30,
174         0x07, 0x20, 13, 8, 20,  // 0x06, 0x20, 13,  8, 20,
175         0x08, 0x20, 14, 8, 20,  // 0x07, 0x20, 14,  8, 20,
176         0x09, 0x20, 15, 8, 25,  // 0x08, 0x20, 15,  8, 25,
177         0x0a, 0x22, 15, 8, 25,  // 0x09, 0x22, 15,  8, 25,
178 };
179
180 UCHAR RateSwitchTable11N2SForABand[] = {
181 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
182         0x0b, 0x09, 0, 0, 0,    // Initial used item after association
183         0x00, 0x21, 0, 30, 101,
184         0x01, 0x21, 1, 20, 50,
185         0x02, 0x21, 2, 20, 50,
186         0x03, 0x21, 3, 15, 50,
187         0x04, 0x21, 4, 15, 30,
188         0x05, 0x21, 5, 15, 30,
189         0x06, 0x20, 12, 15, 30,
190         0x07, 0x20, 13, 8, 20,
191         0x08, 0x20, 14, 8, 20,
192         0x09, 0x20, 15, 8, 25,
193         0x0a, 0x22, 15, 8, 25,
194 };
195
196 UCHAR RateSwitchTable11N3SForABand[] = {        // 3*3
197 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
198         0x0b, 0x09, 0, 0, 0,    // Initial used item after association
199         0x00, 0x21, 0, 30, 101,
200         0x01, 0x21, 1, 20, 50,
201         0x02, 0x21, 2, 20, 50,
202         0x03, 0x21, 3, 15, 50,
203         0x04, 0x21, 4, 15, 30,
204         0x05, 0x21, 5, 15, 30,
205         0x06, 0x20, 12, 15, 30,
206         0x07, 0x20, 13, 8, 20,
207         0x08, 0x20, 14, 8, 20,
208         0x09, 0x20, 15, 8, 25,
209         0x0a, 0x22, 15, 8, 25,
210 };
211
212 UCHAR RateSwitchTable11BGN1S[] = {
213 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
214         0x0c, 0x0a, 0, 0, 0,    // Initial used item after association
215         0x00, 0x00, 0, 40, 101,
216         0x01, 0x00, 1, 40, 50,
217         0x02, 0x00, 2, 25, 45,
218         0x03, 0x21, 0, 20, 35,
219         0x04, 0x21, 1, 20, 35,
220         0x05, 0x21, 2, 20, 35,
221         0x06, 0x21, 3, 15, 35,
222         0x07, 0x21, 4, 15, 30,
223         0x08, 0x21, 5, 10, 25,
224         0x09, 0x21, 6, 8, 14,
225         0x0a, 0x21, 7, 8, 14,
226         0x0b, 0x23, 7, 8, 14,
227 };
228
229 UCHAR RateSwitchTable11BGN2S[] = {
230 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
231         0x0e, 0x0c, 0, 0, 0,    // Initial used item after association
232         0x00, 0x00, 0, 40, 101,
233         0x01, 0x00, 1, 40, 50,
234         0x02, 0x00, 2, 25, 45,
235         0x03, 0x21, 0, 20, 35,
236         0x04, 0x21, 1, 20, 35,
237         0x05, 0x21, 2, 20, 35,
238         0x06, 0x21, 3, 15, 35,
239         0x07, 0x21, 4, 15, 30,
240         0x08, 0x20, 11, 15, 30,
241         0x09, 0x20, 12, 15, 30,
242         0x0a, 0x20, 13, 8, 20,
243         0x0b, 0x20, 14, 8, 20,
244         0x0c, 0x20, 15, 8, 25,
245         0x0d, 0x22, 15, 8, 15,
246 };
247
248 UCHAR RateSwitchTable11BGN3S[] = {      // 3*3
249 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
250         0x0a, 0x00, 0, 0, 0,    // Initial used item after association
251         0x00, 0x21, 0, 30, 101, //50
252         0x01, 0x21, 1, 20, 50,
253         0x02, 0x21, 2, 20, 50,
254         0x03, 0x21, 3, 20, 50,
255         0x04, 0x21, 4, 15, 50,
256         0x05, 0x20, 20, 15, 30,
257         0x06, 0x20, 21, 8, 20,
258         0x07, 0x20, 22, 8, 20,
259         0x08, 0x20, 23, 8, 25,
260         0x09, 0x22, 23, 8, 25,
261 };
262
263 UCHAR RateSwitchTable11BGN2SForABand[] = {
264 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
265         0x0b, 0x09, 0, 0, 0,    // Initial used item after association
266         0x00, 0x21, 0, 30, 101, //50
267         0x01, 0x21, 1, 20, 50,
268         0x02, 0x21, 2, 20, 50,
269         0x03, 0x21, 3, 15, 50,
270         0x04, 0x21, 4, 15, 30,
271         0x05, 0x21, 5, 15, 30,
272         0x06, 0x20, 12, 15, 30,
273         0x07, 0x20, 13, 8, 20,
274         0x08, 0x20, 14, 8, 20,
275         0x09, 0x20, 15, 8, 25,
276         0x0a, 0x22, 15, 8, 25,
277 };
278
279 UCHAR RateSwitchTable11BGN3SForABand[] = {      // 3*3
280 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
281         0x0c, 0x09, 0, 0, 0,    // Initial used item after association
282         0x00, 0x21, 0, 30, 101, //50
283         0x01, 0x21, 1, 20, 50,
284         0x02, 0x21, 2, 20, 50,
285         0x03, 0x21, 3, 15, 50,
286         0x04, 0x21, 4, 15, 30,
287         0x05, 0x21, 5, 15, 30,
288         0x06, 0x21, 12, 15, 30,
289         0x07, 0x20, 20, 15, 30,
290         0x08, 0x20, 21, 8, 20,
291         0x09, 0x20, 22, 8, 20,
292         0x0a, 0x20, 23, 8, 25,
293         0x0b, 0x22, 23, 8, 25,
294 };
295
296 extern UCHAR 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 ULONG 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 */ ,
305             0xffffffff /* 54 */
306 };
307
308 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
309 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
310
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 };
317
318 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
319 USHORT RateIdTo500Kbps[] =
320     { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
321
322 UCHAR SsidIe = IE_SSID;
323 UCHAR SupRateIe = IE_SUPP_RATES;
324 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
325 UCHAR HtCapIe = IE_HT_CAP;
326 UCHAR AddHtInfoIe = IE_ADD_HT;
327 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
328 UCHAR ErpIe = IE_ERP;
329 UCHAR DsIe = IE_DS_PARM;
330 UCHAR TimIe = IE_TIM;
331 UCHAR WpaIe = IE_WPA;
332 UCHAR Wpa2Ie = IE_WPA2;
333 UCHAR IbssIe = IE_IBSS_PARM;
334
335 extern UCHAR WPA_OUI[];
336
337 UCHAR SES_OUI[] = { 0x00, 0x90, 0x4c };
338
339 UCHAR ZeroSsid[32] =
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
344 };
345
346 /*
347         ==========================================================================
348         Description:
349                 initialize the MLME task and its data structure (queue, spinlock,
350                 timer, state machines).
351
352         IRQL = PASSIVE_LEVEL
353
354         Return:
355                 always return NDIS_STATUS_SUCCESS
356
357         ==========================================================================
358 */
359 NDIS_STATUS MlmeInit(IN PRTMP_ADAPTER pAd)
360 {
361         NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
362
363         DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
364
365         do {
366                 Status = MlmeQueueInit(&pAd->Mlme.Queue);
367                 if (Status != NDIS_STATUS_SUCCESS)
368                         break;
369
370                 pAd->Mlme.bRunning = FALSE;
371                 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
372
373                 {
374                         BssTableInit(&pAd->ScanTab);
375
376                         // init STA state machines
377                         AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine,
378                                               pAd->Mlme.AssocFunc);
379                         AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine,
380                                              pAd->Mlme.AuthFunc);
381                         AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine,
382                                                 pAd->Mlme.AuthRspFunc);
383                         SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine,
384                                              pAd->Mlme.SyncFunc);
385
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);
389                 }
390
391                 WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine,
392                                     pAd->Mlme.WpaFunc);
393
394                 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine,
395                                        pAd->Mlme.ActFunc);
396
397                 // Init mlme periodic timer
398                 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer,
399                               GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
400
401                 // Set mlme periodic timer
402                 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
403
404                 // software-based RX Antenna diversity
405                 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer,
406                               GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd,
407                               FALSE);
408
409                 {
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,
414                                               GET_TIMER_FUNCTION
415                                               (PsPollWakeExec), pAd, FALSE);
416                                 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer,
417                                               GET_TIMER_FUNCTION(RadioOnExec),
418                                               pAd, FALSE);
419                         }
420 #endif // RTMP_PCI_SUPPORT //
421
422                         RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer,
423                                       GET_TIMER_FUNCTION(LinkDownExec), pAd,
424                                       FALSE);
425
426 #ifdef RTMP_MAC_USB
427                         RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer,
428                                       GET_TIMER_FUNCTION
429                                       (RtmpUsbStaAsicForceWakeupTimeout), pAd,
430                                       FALSE);
431                         pAd->Mlme.AutoWakeupTimerRunning = FALSE;
432 #endif // RTMP_MAC_USB //
433                 }
434
435         } while (FALSE);
436
437         DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
438
439         return Status;
440 }
441
442 /*
443         ==========================================================================
444         Description:
445                 main loop of the MLME
446         Pre:
447                 Mlme has to be initialized, and there are something inside the queue
448         Note:
449                 This function is invoked from MPSetInformation and MPReceive;
450                 This task guarantee only one MlmeHandler will run.
451
452         IRQL = DISPATCH_LEVEL
453
454         ==========================================================================
455  */
456 VOID MlmeHandler(IN PRTMP_ADAPTER pAd)
457 {
458         MLME_QUEUE_ELEM *Elem = NULL;
459
460         // Only accept MLME and Frame from peer side, no other (control/data) frame should
461         // get into this state machine
462
463         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
464         if (pAd->Mlme.bRunning) {
465                 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
466                 return;
467         } else {
468                 pAd->Mlme.bRunning = TRUE;
469         }
470         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
471
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));
479                         break;
480                 }
481                 //From message type, determine which state machine I should drive
482                 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
483 #ifdef RTMP_MAC_USB
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;
489                                 Elem->MsgLen = 0;
490                                 continue;
491                         }
492 #endif // RTMP_MAC_USB //
493
494                         // if dequeue success
495                         switch (Elem->Machine) {
496                                 // STA state machines
497                         case ASSOC_STATE_MACHINE:
498                                 StateMachinePerformAction(pAd,
499                                                           &pAd->Mlme.
500                                                           AssocMachine, Elem);
501                                 break;
502                         case AUTH_STATE_MACHINE:
503                                 StateMachinePerformAction(pAd,
504                                                           &pAd->Mlme.
505                                                           AuthMachine, Elem);
506                                 break;
507                         case AUTH_RSP_STATE_MACHINE:
508                                 StateMachinePerformAction(pAd,
509                                                           &pAd->Mlme.
510                                                           AuthRspMachine, Elem);
511                                 break;
512                         case SYNC_STATE_MACHINE:
513                                 StateMachinePerformAction(pAd,
514                                                           &pAd->Mlme.
515                                                           SyncMachine, Elem);
516                                 break;
517                         case MLME_CNTL_STATE_MACHINE:
518                                 MlmeCntlMachinePerformAction(pAd,
519                                                              &pAd->Mlme.
520                                                              CntlMachine, Elem);
521                                 break;
522                         case WPA_PSK_STATE_MACHINE:
523                                 StateMachinePerformAction(pAd,
524                                                           &pAd->Mlme.
525                                                           WpaPskMachine, Elem);
526                                 break;
527
528                         case ACTION_STATE_MACHINE:
529                                 StateMachinePerformAction(pAd,
530                                                           &pAd->Mlme.ActMachine,
531                                                           Elem);
532                                 break;
533
534                         case WPA_STATE_MACHINE:
535                                 StateMachinePerformAction(pAd,
536                                                           &pAd->Mlme.WpaMachine,
537                                                           Elem);
538                                 break;
539
540                         default:
541                                 DBGPRINT(RT_DEBUG_TRACE,
542                                          ("ERROR: Illegal machine %ld in MlmeHandler()\n",
543                                           Elem->Machine));
544                                 break;
545                         }       // end of switch
546
547                         // free MLME element
548                         Elem->Occupied = FALSE;
549                         Elem->MsgLen = 0;
550
551                 } else {
552                         DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
553                 }
554         }
555
556         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
557         pAd->Mlme.bRunning = FALSE;
558         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
559 }
560
561 /*
562         ==========================================================================
563         Description:
564                 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
565         Parameters:
566                 Adapter - NIC Adapter pointer
567         Post:
568                 The MLME task will no longer work properly
569
570         IRQL = PASSIVE_LEVEL
571
572         ==========================================================================
573  */
574 VOID MlmeHalt(IN PRTMP_ADAPTER pAd)
575 {
576         BOOLEAN Cancelled;
577
578         DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
579
580         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
581                 // disable BEACON generation and other BEACON related hardware timers
582                 AsicDisableSync(pAd);
583         }
584
585         {
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);
593
594 #ifdef RTMP_MAC_PCI
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);
599                 }
600 #endif // RTMP_MAC_PCI //
601
602                 RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
603
604 #ifdef RTMP_MAC_USB
605                 RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
606 #endif // RTMP_MAC_USB //
607         }
608
609         RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
610         RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
611
612         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
613                 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
614
615                 // Set LED
616                 RTMPSetLED(pAd, LED_HALT);
617                 RTMPSetSignalLED(pAd, -100);    // Force signal strength Led to be turned off, firmware is not done it.
618 #ifdef RTMP_MAC_USB
619                 {
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);
627                 }
628 #endif // RTMP_MAC_USB //
629
630                 if (pChipOps->AsicHaltAction)
631                         pChipOps->AsicHaltAction(pAd);
632         }
633
634         RTMPusecDelay(5000);    //  5 msec to gurantee Ant Diversity timer canceled
635
636         MlmeQueueDestroy(&pAd->Mlme.Queue);
637         NdisFreeSpinLock(&pAd->Mlme.TaskLock);
638
639         DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
640 }
641
642 VOID MlmeResetRalinkCounters(IN PRTMP_ADAPTER pAd)
643 {
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;
657
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;
671
672         return;
673 }
674
675 /*
676         ==========================================================================
677         Description:
678                 This routine is executed periodically to -
679                 1. Decide if it's a right time to turn on PwrMgmt bit of all
680                    outgoiing frames
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.
686
687         IRQL = DISPATCH_LEVEL
688
689         ==========================================================================
690  */
691 #define ADHOC_BEACON_LOST_TIME          (8*OS_HZ)       // 8 sec
692 VOID MlmePeriodicExec(IN PVOID SystemSpecific1,
693                       IN PVOID FunctionContext,
694                       IN PVOID SystemSpecific2, IN PVOID SystemSpecific3)
695 {
696         ULONG TxTotalCnt;
697         PRTMP_ADAPTER pAd = (RTMP_ADAPTER *) FunctionContext;
698
699 #ifdef RTMP_MAC_PCI
700         {
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) */
708                     ) {
709                         UINT32 data = 0;
710
711                         // Read GPIO pin2 as Hardware controlled radio state
712 #ifndef RT3090
713                         RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
714 #endif // RT3090 //
715 //KH(PCIE PS):Added based on Jane<--
716 #ifdef RT3090
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))
720                             &&
721                             (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
722                             && (pAd->StaCfg.PSControl.field.EnablePSinIdle ==
723                                 TRUE)) {
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);
728                         } else
729                                 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
730 #endif // RT3090 //
731 //KH(PCIE PS):Added based on Jane-->
732
733                         if (data & 0x04) {
734                                 pAd->StaCfg.bHwRadio = TRUE;
735                         } else {
736                                 pAd->StaCfg.bHwRadio = FALSE;
737                         }
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) {
743                                         MlmeRadioOn(pAd);
744                                         // Update extra information
745                                         pAd->ExtraInfo = EXTRA_INFO_CLEAR;
746                                 } else {
747                                         MlmeRadioOff(pAd);
748                                         // Update extra information
749                                         pAd->ExtraInfo = HW_RADIO_OFF;
750                                 }
751                         }
752                 }
753         }
754 #endif // RTMP_MAC_PCI //
755
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))))
762                 return;
763
764         RTMP_MLME_PRE_SANITY_CHECK(pAd);
765
766         {
767                 // Do nothing if monitor mode is on
768                 if (MONITOR_ON(pAd))
769                         return;
770
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))
776                         {
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;
783                         }
784                 }
785         }
786
787         pAd->bUpdateBcnCntDone = FALSE;
788
789 //      RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
790         pAd->Mlme.PeriodicRound++;
791
792 #ifdef RTMP_MAC_USB
793         // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
794         NICUpdateFifoStaCounters(pAd);
795 #endif // RTMP_MAC_USB //
796
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)) */ )
801         {
802                 // perform dynamic tx rate switching based on past TX history
803                 {
804                         if ((OPSTATUS_TEST_FLAG
805                              (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
806                             )
807                             && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
808                                 MlmeDynamicTxRateSwitching(pAd);
809                 }
810         }
811         // Normal 1 second Mlme PeriodicExec.
812         if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) {
813                 pAd->Mlme.OneSecPeriodicRound++;
814
815                 //ORIBATimerTimeout(pAd);
816
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);
825
826                         } else {
827                                 pAd->IndicateMediaState =
828                                     NdisMediaStateDisconnected;
829                                 RTMP_IndicateMediaState(pAd);
830                         }
831                 }
832
833                 NdisGetSystemUpTime(&pAd->Mlme.Now32);
834
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);
838
839 #ifdef RTMP_MAC_USB
840                 RTUSBWatchDog(pAd);
841 #endif // RTMP_MAC_USB //
842
843                 // Need statistics after read counter. So put after NICUpdateRawCounters
844                 ORIBATimerTimeout(pAd);
845
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);
851                 //      else
852                 //              pAd->RalinkCounters.MgmtRingFullCount = 0;
853
854                 // The time period for checking antenna is according to traffic
855                 {
856                         if (pAd->Mlme.bEnableAutoAntennaCheck) {
857                                 TxTotalCnt =
858                                     pAd->RalinkCounters.OneSecTxNoRetryOkCount +
859                                     pAd->RalinkCounters.OneSecTxRetryOkCount +
860                                     pAd->RalinkCounters.OneSecTxFailCount;
861
862                                 // dynamic adjust antenna evaluation period according to the traffic
863                                 if (TxTotalCnt > 50) {
864                                         if (pAd->Mlme.OneSecPeriodicRound %
865                                             10 == 0) {
866                                                 AsicEvaluateRxAnt(pAd);
867                                         }
868                                 } else {
869                                         if (pAd->Mlme.OneSecPeriodicRound % 3 ==
870                                             0) {
871                                                 AsicEvaluateRxAnt(pAd);
872                                         }
873                                 }
874                         }
875                 }
876
877                 STAMlmePeriodicExec(pAd);
878
879                 MlmeResetRalinkCounters(pAd);
880
881                 {
882 #ifdef RTMP_MAC_PCI
883                         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
884                             && (pAd->bPCIclkOff == FALSE))
885 #endif // RTMP_MAC_PCI //
886                         {
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.
893
894                                 UINT32 MacReg = 0;
895
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);
901                                         RTMPusecDelay(1);
902                                         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
903
904                                         DBGPRINT(RT_DEBUG_WARN,
905                                                  ("Warning, MAC specific condition occurs \n"));
906                                 }
907                         }
908                 }
909
910                 RTMP_MLME_HANDLER(pAd);
911         }
912
913         pAd->bUpdateBcnCntDone = FALSE;
914 }
915
916 /*
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         ==========================================================================
923  */
924 BOOLEAN MlmeValidateSSID(IN PUCHAR pSsid, IN UCHAR SsidLen)
925 {
926         int index;
927
928         if (SsidLen > MAX_LEN_OF_SSID)
929                 return (FALSE);
930
931         // Check each character value
932         for (index = 0; index < SsidLen; index++) {
933                 if (pSsid[index] < 0x20)
934                         return (FALSE);
935         }
936
937         // All checked
938         return (TRUE);
939 }
940
941 VOID MlmeSelectTxRateTable(IN PRTMP_ADAPTER pAd,
942                            IN PMAC_TABLE_ENTRY pEntry,
943                            IN PUCHAR * ppTable,
944                            IN PUCHAR pTableSize, IN PUCHAR pInitTxRateIdx)
945 {
946         do {
947                 // decide the rate table for tuning
948                 if (pAd->CommonCfg.TxRateTableSize > 0) {
949                         *ppTable = RateSwitchTable;
950                         *pTableSize = RateSwitchTable[0];
951                         *pInitTxRateIdx = RateSwitchTable[1];
952
953                         break;
954                 }
955
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];
961
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];
966                                         *pInitTxRateIdx =
967                                             RateSwitchTable11N2S[1];
968                                 } else {
969                                         *ppTable = RateSwitchTable11N2SForABand;
970                                         *pTableSize =
971                                             RateSwitchTable11N2SForABand[0];
972                                         *pInitTxRateIdx =
973                                             RateSwitchTable11N2SForABand[1];
974                                 }
975
976                         } else if ((pEntry->RateLen == 4)
977                                    && (pEntry->HTCapability.MCSSet[0] == 0)
978                                    && (pEntry->HTCapability.MCSSet[1] == 0)
979                             ) {
980                                 *ppTable = RateSwitchTable11B;
981                                 *pTableSize = RateSwitchTable11B[0];
982                                 *pInitTxRateIdx = RateSwitchTable11B[1];
983
984                         } else if (pAd->LatchRfRegs.Channel <= 14) {
985                                 *ppTable = RateSwitchTable11BG;
986                                 *pTableSize = RateSwitchTable11BG[0];
987                                 *pInitTxRateIdx = RateSwitchTable11BG[1];
988
989                         } else {
990                                 *ppTable = RateSwitchTable11G;
991                                 *pTableSize = RateSwitchTable11G[0];
992                                 *pInitTxRateIdx = RateSwitchTable11G[1];
993
994                         }
995                         break;
996                 }
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];
1003
1004                         break;
1005                 }
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];
1013
1014                         } else {
1015                                 *ppTable = RateSwitchTable11BGN2SForABand;
1016                                 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1017                                 *pInitTxRateIdx =
1018                                     RateSwitchTable11BGN2SForABand[1];
1019
1020                         }
1021                         break;
1022                 }
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];
1028
1029                         break;
1030                 }
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];
1037                         } else {
1038                                 *ppTable = RateSwitchTable11N2SForABand;
1039                                 *pTableSize = RateSwitchTable11N2SForABand[0];
1040                                 *pInitTxRateIdx =
1041                                     RateSwitchTable11N2SForABand[1];
1042                         }
1043
1044                         break;
1045                 }
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) */
1050                     ) {         // B only AP
1051                         *ppTable = RateSwitchTable11B;
1052                         *pTableSize = RateSwitchTable11B[0];
1053                         *pInitTxRateIdx = RateSwitchTable11B[1];
1054
1055                         break;
1056                 }
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];
1065
1066                         break;
1067                 }
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)
1072                     ) {         // G only AP
1073                         *ppTable = RateSwitchTable11G;
1074                         *pTableSize = RateSwitchTable11G[0];
1075                         *pInitTxRateIdx = RateSwitchTable11G[1];
1076
1077                         break;
1078                 }
1079
1080                 {
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 >
1089                                                RATE_11)) {
1090                                         *ppTable = RateSwitchTable11G;
1091                                         *pTableSize = RateSwitchTable11G[0];
1092                                         *pInitTxRateIdx = RateSwitchTable11G[1];
1093
1094                                 } else {
1095                                         *ppTable = RateSwitchTable11BG;
1096                                         *pTableSize = RateSwitchTable11BG[0];
1097                                         *pInitTxRateIdx =
1098                                             RateSwitchTable11BG[1];
1099                                 }
1100                                 break;
1101                         }
1102                         if (pAd->LatchRfRegs.Channel <= 14) {
1103                                 if (pAd->CommonCfg.TxStream == 1) {
1104                                         *ppTable = RateSwitchTable11N1S;
1105                                         *pTableSize = RateSwitchTable11N1S[0];
1106                                         *pInitTxRateIdx =
1107                                             RateSwitchTable11N1S[1];
1108                                         DBGPRINT_RAW(RT_DEBUG_ERROR,
1109                                                      ("DRS: unkown mode,default use 11N 1S AP \n"));
1110                                 } else {
1111                                         *ppTable = RateSwitchTable11N2S;
1112                                         *pTableSize = RateSwitchTable11N2S[0];
1113                                         *pInitTxRateIdx =
1114                                             RateSwitchTable11N2S[1];
1115                                         DBGPRINT_RAW(RT_DEBUG_ERROR,
1116                                                      ("DRS: unkown mode,default use 11N 2S AP \n"));
1117                                 }
1118                         } else {
1119                                 if (pAd->CommonCfg.TxStream == 1) {
1120                                         *ppTable = RateSwitchTable11N1S;
1121                                         *pTableSize = RateSwitchTable11N1S[0];
1122                                         *pInitTxRateIdx =
1123                                             RateSwitchTable11N1S[1];
1124                                         DBGPRINT_RAW(RT_DEBUG_ERROR,
1125                                                      ("DRS: unkown mode,default use 11N 1S AP \n"));
1126                                 } else {
1127                                         *ppTable = RateSwitchTable11N2SForABand;
1128                                         *pTableSize =
1129                                             RateSwitchTable11N2SForABand[0];
1130                                         *pInitTxRateIdx =
1131                                             RateSwitchTable11N2SForABand[1];
1132                                         DBGPRINT_RAW(RT_DEBUG_ERROR,
1133                                                      ("DRS: unkown mode,default use 11N 2S AP \n"));
1134                                 }
1135                         }
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.
1142                                       MCSSet[1]));
1143                 }
1144         } while (FALSE);
1145 }
1146
1147 VOID STAMlmePeriodicExec(PRTMP_ADAPTER pAd)
1148 {
1149         ULONG TxTotalCnt;
1150         int i;
1151
1152         /*
1153            We return here in ATE mode, because the statistics
1154            that ATE need are not collected via this routine.
1155          */
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) {
1159 #ifdef RT3070
1160                 if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201)))
1161 #endif // RT3070 //
1162                 {
1163                         if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0)
1164                             && (pAd->StaCfg.RssiSample.AvgRssi0 >
1165                                 (pAd->BbpRssiToDbmDelta - 35))) {
1166                                 RT30xxWriteRFRegister(pAd, RF_R27, 0x20);
1167                         } else {
1168                                 RT30xxWriteRFRegister(pAd, RF_R27, 0x23);
1169                         }
1170                 }
1171         }
1172 #endif
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 ==
1183                                     TRUE) {
1184                                         DBGPRINT(RT_DEBUG_TRACE,
1185                                                  ("%s\n", __func__));
1186                                         RT28xxPciAsicRadioOff(pAd,
1187                                                               GUI_IDLE_POWER_SAVE,
1188                                                               0);
1189                                 } else {
1190                                         AsicSendCommandToMcu(pAd, 0x30,
1191                                                              PowerSafeCID, 0xff,
1192                                                              0x2);
1193                                         // Wait command success
1194                                         AsicCheckCommanOk(pAd, PowerSafeCID);
1195                                         RTMP_SET_FLAG(pAd,
1196                                                       fRTMP_ADAPTER_IDLE_RADIO_OFF);
1197                                         DBGPRINT(RT_DEBUG_TRACE,
1198                                                  ("PSM - rt30xx Issue Sleep command)\n"));
1199                                 }
1200                         } else if (pAd->Mlme.OneSecPeriodicRound > 180) {
1201                                 if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1202                                     TRUE) {
1203                                         DBGPRINT(RT_DEBUG_TRACE,
1204                                                  ("%s\n", __func__));
1205                                         RT28xxPciAsicRadioOff(pAd,
1206                                                               GUI_IDLE_POWER_SAVE,
1207                                                               0);
1208                                 } else {
1209                                         AsicSendCommandToMcu(pAd, 0x30,
1210                                                              PowerSafeCID, 0xff,
1211                                                              0x02);
1212                                         // Wait command success
1213                                         AsicCheckCommanOk(pAd, PowerSafeCID);
1214                                         RTMP_SET_FLAG(pAd,
1215                                                       fRTMP_ADAPTER_IDLE_RADIO_OFF);
1216                                         DBGPRINT(RT_DEBUG_TRACE,
1217                                                  ("PSM -  rt28xx Issue Sleep command)\n"));
1218                                 }
1219                         }
1220                 } else {
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]));
1230                 }
1231         }
1232 #endif // PCIE_PS_SUPPORT //
1233
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 +
1239                                     (60 * OS_HZ)))
1240                         pAd->StaCfg.bBlockAssoc = FALSE;
1241         }
1242
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].
1248                                               Addr, BSS0, 0);
1249                 }
1250                 pAd->PreMediaState = pAd->IndicateMediaState;
1251         }
1252
1253         if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) {
1254         } else {
1255                 AsicStaBbpTuning(pAd);
1256         }
1257
1258         TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1259             pAd->RalinkCounters.OneSecTxRetryOkCount +
1260             pAd->RalinkCounters.OneSecTxFailCount;
1261
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);
1265         }
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);
1270
1271         if (INFRA_ON(pAd)) {
1272
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);
1277
1278                 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1279
1280                 if ((RTMP_TIME_AFTER
1281                      (pAd->Mlme.Now32,
1282                       pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ)))
1283                     &&
1284                     (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1285                     &&
1286                     (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) <
1287                       600))) {
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))));
1292                 }
1293                 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1294                 //    (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1295                 {
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,
1302                                                           TRUE);
1303                         } else {
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,
1308                                                                   pAd->
1309                                                                   CommonCfg.
1310                                                                   TxRate, TRUE);
1311                                         else
1312                                                 RTMPSendNullFrame(pAd,
1313                                                                   pAd->
1314                                                                   CommonCfg.
1315                                                                   TxRate,
1316                                                                   FALSE);
1317                                 }
1318                         }
1319                 }
1320
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));
1325
1326                         // Lost AP, send disconnect & link down event
1327                         LinkDown(pAd, FALSE);
1328
1329                         RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL,
1330                                                 0);
1331
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);
1340                 }
1341
1342                 if (pAd->StaCfg.bAutoRoaming) {
1343                         BOOLEAN rv = FALSE;
1344                         CHAR dBmToRoam = pAd->StaCfg.dBmToRoam;
1345                         CHAR MaxRssi = RTMPMaxRssi(pAd,
1346                                                    pAd->StaCfg.RssiSample.
1347                                                    LastRssi0,
1348                                                    pAd->StaCfg.RssiSample.
1349                                                    LastRssi1,
1350                                                    pAd->StaCfg.RssiSample.
1351                                                    LastRssi2);
1352
1353                         // Scanning, ignore Roaming
1354                         if (!RTMP_TEST_FLAG
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,
1360                                           (CHAR) dBmToRoam));
1361
1362                                 // Add auto seamless roaming
1363                                 if (rv == FALSE)
1364                                         rv = MlmeCheckForFastRoaming(pAd);
1365
1366                                 if (rv == FALSE) {
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 =
1373                                                     pAd->Mlme.Now32;
1374                                                 MlmeAutoScan(pAd);
1375                                         }
1376                                 }
1377                         }
1378                 }
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
1382                 // join later.
1383                 if (RTMP_TIME_AFTER
1384                     (pAd->Mlme.Now32,
1385                      pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)
1386                     && OPSTATUS_TEST_FLAG(pAd,
1387                                           fOP_STATUS_MEDIA_STATE_CONNECTED)) {
1388                         MLME_START_REQ_STRUCT StartReq;
1389
1390                         DBGPRINT(RT_DEBUG_TRACE,
1391                                  ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1392                         LinkDown(pAd, FALSE);
1393
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(MLME_START_REQ_STRUCT), &StartReq);
1399                         pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1400                 }
1401
1402                 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1403                         MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1404
1405                         if (pEntry->ValidAsCLI == FALSE)
1406                                 continue;
1407
1408                         if (RTMP_TIME_AFTER
1409                             (pAd->Mlme.Now32,
1410                              pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1411                                 MacTableDeleteEntry(pAd, pEntry->Aid,
1412                                                     pEntry->Addr);
1413                 }
1414         } else                  // no INFRA nor ADHOC connection
1415         {
1416
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;
1421                 else
1422                         pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1423
1424                 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1425                     && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1426                     &&
1427                     (MlmeValidateSSID
1428                      (pAd->MlmeAux.AutoReconnectSsid,
1429                       pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1430                         if ((pAd->ScanTab.BssNr == 0)
1431                             && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) {
1432                                 MLME_SCAN_REQ_STRUCT ScanReq;
1433
1434                                 if (RTMP_TIME_AFTER
1435                                     (pAd->Mlme.Now32,
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",
1439                                                   pAd->MlmeAux.
1440                                                   AutoReconnectSsid));
1441                                         ScanParmFill(pAd, &ScanReq,
1442                                                      (PSTRING) pAd->MlmeAux.
1443                                                      AutoReconnectSsid,
1444                                                      pAd->MlmeAux.
1445                                                      AutoReconnectSsidLen,
1446                                                      BSS_ANY, SCAN_ACTIVE);
1447                                         MlmeEnqueue(pAd, SYNC_STATE_MACHINE,
1448                                                     MT2_MLME_SCAN_REQ,
1449                                                     sizeof
1450                                                     (MLME_SCAN_REQ_STRUCT),
1451                                                     &ScanReq);
1452                                         pAd->Mlme.CntlMachine.CurrState =
1453                                             CNTL_WAIT_OID_LIST_SCAN;
1454                                         // Reset Missed scan number
1455                                         pAd->StaCfg.LastScanTime =
1456                                             pAd->Mlme.Now32;
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) {
1461                                         MlmeAutoScan(pAd);
1462                                         pAd->StaCfg.LastScanTime =
1463                                             pAd->Mlme.Now32;
1464                                 } else {
1465                                         MlmeAutoReconnectLastSSID(pAd);
1466                                 }
1467                         }
1468                 }
1469         }
1470
1471 SKIP_AUTO_SCAN_CONN:
1472
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,
1477                                   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);
1484         }
1485
1486         return;
1487 }
1488
1489 // Link down report
1490 VOID LinkDownExec(IN PVOID SystemSpecific1,
1491                   IN PVOID FunctionContext,
1492                   IN PVOID SystemSpecific2, IN PVOID SystemSpecific3)
1493 {
1494         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext;
1495
1496         if (pAd != NULL) {
1497                 MLME_DISASSOC_REQ_STRUCT DisassocReq;
1498
1499                 if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
1500                     (INFRA_ON(pAd))) {
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(MLME_DISASSOC_REQ_STRUCT),
1509                                     &DisassocReq);
1510                         pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1511
1512                         pAd->IndicateMediaState = NdisMediaStateDisconnected;
1513                         RTMP_IndicateMediaState(pAd);
1514                         pAd->ExtraInfo = GENERAL_LINK_DOWN;
1515                 }
1516         }
1517 }
1518
1519 // IRQL = DISPATCH_LEVEL
1520 VOID MlmeAutoScan(IN PRTMP_ADAPTER pAd)
1521 {
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"));
1525                 MlmeEnqueue(pAd,
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);
1531         }
1532 }
1533
1534 // IRQL = DISPATCH_LEVEL
1535 VOID MlmeAutoReconnectLastSSID(IN PRTMP_ADAPTER pAd)
1536 {
1537         if (pAd->StaCfg.bAutoConnectByBssid) {
1538                 DBGPRINT(RT_DEBUG_TRACE,
1539                          ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n",
1540                           pAd->MlmeAux.Bssid[0], pAd->MlmeAux.Bssid[1],
1541                           pAd->MlmeAux.Bssid[2], pAd->MlmeAux.Bssid[3],
1542                           pAd->MlmeAux.Bssid[4], pAd->MlmeAux.Bssid[5]));
1543
1544                 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1545                 MlmeEnqueue(pAd,
1546                             MLME_CNTL_STATE_MACHINE,
1547                             OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid);
1548
1549                 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1550
1551                 RTMP_MLME_HANDLER(pAd);
1552         }
1553         // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1554         else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1555                  (MlmeValidateSSID
1556                   (pAd->MlmeAux.AutoReconnectSsid,
1557                    pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1558                 NDIS_802_11_SSID OidSsid;
1559                 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1560                 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid,
1561                                pAd->MlmeAux.AutoReconnectSsidLen);
1562
1563                 DBGPRINT(RT_DEBUG_TRACE,
1564                          ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
1565                           pAd->MlmeAux.AutoReconnectSsid,
1566                           pAd->MlmeAux.AutoReconnectSsidLen));
1567                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID,
1568                             sizeof(NDIS_802_11_SSID), &OidSsid);
1569                 RTMP_MLME_HANDLER(pAd);
1570         }
1571 }
1572
1573 /*
1574         ==========================================================================
1575         Description:
1576                 This routine checks if there're other APs out there capable for
1577                 roaming. Caller should call this routine only when Link up in INFRA mode
1578                 and channel quality is below CQI_GOOD_THRESHOLD.
1579
1580         IRQL = DISPATCH_LEVEL
1581
1582         Output:
1583         ==========================================================================
1584  */
1585 VOID MlmeCheckForRoaming(IN PRTMP_ADAPTER pAd, IN ULONG Now32)
1586 {
1587         USHORT i;
1588         BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1589         BSS_ENTRY *pBss;
1590
1591         DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1592         // put all roaming candidates into RoamTab, and sort in RSSI order
1593         BssTableInit(pRoamTab);
1594         for (i = 0; i < pAd->ScanTab.BssNr; i++) {
1595                 pBss = &pAd->ScanTab.BssEntry[i];
1596
1597                 if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) <
1598                     Now32)
1599                         continue;       // AP disappear
1600                 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1601                         continue;       // RSSI too weak. forget it.
1602                 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1603                         continue;       // skip current AP
1604                 if (pBss->Rssi <
1605                     (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1606                         continue;       // only AP with stronger RSSI is eligible for roaming
1607
1608                 // AP passing all above rules is put into roaming candidate table
1609                 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
1610                                sizeof(BSS_ENTRY));
1611                 pRoamTab->BssNr += 1;
1612         }
1613
1614         if (pRoamTab->BssNr > 0) {
1615                 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1616                 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1617                         pAd->RalinkCounters.PoorCQIRoamingCount++;
1618                         DBGPRINT(RT_DEBUG_TRACE,
1619                                  ("MMCHK - Roaming attempt #%ld\n",
1620                                   pAd->RalinkCounters.PoorCQIRoamingCount));
1621                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1622                                     MT2_MLME_ROAMING_REQ, 0, NULL);
1623                         RTMP_MLME_HANDLER(pAd);
1624                 }
1625         }
1626         DBGPRINT(RT_DEBUG_TRACE,
1627                  ("<== MlmeCheckForRoaming(# of candidate= %d)\n",
1628                   pRoamTab->BssNr));
1629 }
1630
1631 /*
1632         ==========================================================================
1633         Description:
1634                 This routine checks if there're other APs out there capable for
1635                 roaming. Caller should call this routine only when link up in INFRA mode
1636                 and channel quality is below CQI_GOOD_THRESHOLD.
1637
1638         IRQL = DISPATCH_LEVEL
1639
1640         Output:
1641         ==========================================================================
1642  */
1643 BOOLEAN MlmeCheckForFastRoaming(IN PRTMP_ADAPTER pAd)
1644 {
1645         USHORT i;
1646         BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1647         BSS_ENTRY *pBss;
1648
1649         DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1650         // put all roaming candidates into RoamTab, and sort in RSSI order
1651         BssTableInit(pRoamTab);
1652         for (i = 0; i < pAd->ScanTab.BssNr; i++) {
1653                 pBss = &pAd->ScanTab.BssEntry[i];
1654
1655                 if ((pBss->Rssi <= -50)
1656                     && (pBss->Channel == pAd->CommonCfg.Channel))
1657                         continue;       // RSSI too weak. forget it.
1658                 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1659                         continue;       // skip current AP
1660                 if (!SSID_EQUAL
1661                     (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid,
1662                      pAd->CommonCfg.SsidLen))
1663                         continue;       // skip different SSID
1664                 if (pBss->Rssi <
1665                     (RTMPMaxRssi
1666                      (pAd, pAd->StaCfg.RssiSample.LastRssi0,
1667                       pAd->StaCfg.RssiSample.LastRssi1,
1668                       pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1669                         continue;       // skip AP without better RSSI
1670
1671                 DBGPRINT(RT_DEBUG_TRACE,
1672                          ("LastRssi0 = %d, pBss->Rssi = %d\n",
1673                           RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0,
1674                                       pAd->StaCfg.RssiSample.LastRssi1,
1675                                       pAd->StaCfg.RssiSample.LastRssi2),
1676                           pBss->Rssi));
1677                 // AP passing all above rules is put into roaming candidate table
1678                 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
1679                                sizeof(BSS_ENTRY));
1680                 pRoamTab->BssNr += 1;
1681         }
1682
1683         DBGPRINT(RT_DEBUG_TRACE,
1684                  ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1685         if (pRoamTab->BssNr > 0) {
1686                 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1687                 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1688                         pAd->RalinkCounters.PoorCQIRoamingCount++;
1689                         DBGPRINT(RT_DEBUG_TRACE,
1690                                  ("MMCHK - Roaming attempt #%ld\n",
1691                                   pAd->RalinkCounters.PoorCQIRoamingCount));
1692                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1693                                     MT2_MLME_ROAMING_REQ, 0, NULL);
1694                         RTMP_MLME_HANDLER(pAd);
1695                         return TRUE;
1696                 }
1697         }
1698
1699         return FALSE;
1700 }
1701
1702 VOID MlmeSetTxRate(IN PRTMP_ADAPTER pAd,
1703                    IN PMAC_TABLE_ENTRY pEntry, IN PRTMP_TX_RATE_SWITCH pTxRate)
1704 {
1705         UCHAR MaxMode = MODE_OFDM;
1706
1707         MaxMode = MODE_HTGREENFIELD;
1708
1709         if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC)
1710             && (pAd->Antenna.field.TxPath == 2))
1711                 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1712         else
1713                 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1714
1715         if (pTxRate->CurrMCS < MCS_AUTO)
1716                 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1717
1718         if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1719                 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1720
1721         if (ADHOC_ON(pAd)) {
1722                 // If peer adhoc is b-only mode, we can't send 11g rate.
1723                 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1724                 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1725
1726                 //
1727                 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1728                 //
1729                 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1730                 pEntry->HTPhyMode.field.ShortGI =
1731                     pAd->StaCfg.HTPhyMode.field.ShortGI;
1732                 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1733
1734                 // Patch speed error in status page
1735                 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1736         } else {
1737                 if (pTxRate->Mode <= MaxMode)
1738                         pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1739
1740                 if (pTxRate->ShortGI
1741                     && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1742                         pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1743                 else
1744                         pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1745
1746                 // Reexam each bandwidth's SGI support.
1747                 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) {
1748                         if ((pEntry->HTPhyMode.field.BW == BW_20)
1749                             &&
1750                             (!CLIENT_STATUS_TEST_FLAG
1751                              (pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1752                                 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1753                         if ((pEntry->HTPhyMode.field.BW == BW_40)
1754                             &&
1755                             (!CLIENT_STATUS_TEST_FLAG
1756                              (pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1757                                 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1758                 }
1759                 // Turn RTS/CTS rate to 6Mbps.
1760                 if ((pEntry->HTPhyMode.field.MCS == 0)
1761                     && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) {
1762                         pEntry->HTPhyMode.field.MCS =
1763                             pAd->StaCfg.HTPhyMode.field.MCS;
1764                         if (pAd->MacTab.fAnyBASession) {
1765                                 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1766                                                   ALLN_SETPROTECT, TRUE,
1767                                                   (BOOLEAN) pAd->MlmeAux.
1768                                                   AddHtInfo.AddHtInfo2.
1769                                                   NonGfPresent);
1770                         } else {
1771                                 AsicUpdateProtect(pAd,
1772                                                   pAd->MlmeAux.AddHtInfo.
1773                                                   AddHtInfo2.OperaionMode,
1774                                                   ALLN_SETPROTECT, TRUE,
1775                                                   (BOOLEAN) pAd->MlmeAux.
1776                                                   AddHtInfo.AddHtInfo2.
1777                                                   NonGfPresent);
1778                         }
1779                 } else if ((pEntry->HTPhyMode.field.MCS == 8)
1780                            && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) {
1781                         pEntry->HTPhyMode.field.MCS =
1782                             pAd->StaCfg.HTPhyMode.field.MCS;
1783                         if (pAd->MacTab.fAnyBASession) {
1784                                 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1785                                                   ALLN_SETPROTECT, TRUE,
1786                                                   (BOOLEAN) pAd->MlmeAux.
1787                                                   AddHtInfo.AddHtInfo2.
1788                                                   NonGfPresent);
1789                         } else {
1790                                 AsicUpdateProtect(pAd,
1791                                                   pAd->MlmeAux.AddHtInfo.
1792                                                   AddHtInfo2.OperaionMode,
1793                                                   ALLN_SETPROTECT, TRUE,
1794                                                   (BOOLEAN) pAd->MlmeAux.
1795                                                   AddHtInfo.AddHtInfo2.
1796                                                   NonGfPresent);
1797                         }
1798                 } else if ((pEntry->HTPhyMode.field.MCS != 0)
1799                            && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) {
1800                         AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1801                                           TRUE,
1802                                           (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1803                                           AddHtInfo2.NonGfPresent);
1804
1805                 } else if ((pEntry->HTPhyMode.field.MCS != 8)
1806                            && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) {
1807                         AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1808                                           TRUE,
1809                                           (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1810                                           AddHtInfo2.NonGfPresent);
1811                 }
1812
1813                 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1814                 pEntry->HTPhyMode.field.ShortGI =
1815                     pAd->StaCfg.HTPhyMode.field.ShortGI;
1816                 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1817                 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1818                 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD)
1819                     && pAd->WIFItestbed.bGreenField)
1820                         pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1821         }
1822
1823         pAd->LastTxRate = (USHORT) (pEntry->HTPhyMode.word);
1824 }
1825
1826 /*
1827         ==========================================================================
1828         Description:
1829                 This routine calculates the acumulated TxPER of eaxh TxRate. And
1830                 according to the calculation result, change CommonCfg.TxRate which
1831                 is the stable TX Rate we expect the Radio situation could sustained.
1832
1833                 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1834         Output:
1835                 CommonCfg.TxRate -
1836
1837         IRQL = DISPATCH_LEVEL
1838
1839         NOTE:
1840                 call this routine every second
1841         ==========================================================================
1842  */
1843 VOID MlmeDynamicTxRateSwitching(IN PRTMP_ADAPTER pAd)
1844 {
1845         UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1846         ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1847         ULONG TxErrorRatio = 0;
1848         BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
1849         PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1850         PUCHAR pTable;
1851         UCHAR TableSize = 0;
1852         UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1853         CHAR Rssi, RssiOffset = 0;
1854         TX_STA_CNT1_STRUC StaTx1;
1855         TX_STA_CNT0_STRUC TxStaCnt0;
1856         ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1857         MAC_TABLE_ENTRY *pEntry;
1858         RSSI_SAMPLE *pRssi = &pAd->StaCfg.RssiSample;
1859
1860         //
1861         // walk through MAC table, see if need to change AP's TX rate toward each entry
1862         //
1863         for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1864                 pEntry = &pAd->MacTab.Content[i];
1865
1866                 // check if this entry need to switch rate automatically
1867                 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1868                         continue;
1869
1870                 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) {
1871                         Rssi = RTMPMaxRssi(pAd,
1872                                            pRssi->AvgRssi0,
1873                                            pRssi->AvgRssi1, pRssi->AvgRssi2);
1874
1875                         // Update statistic counter
1876                         RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1877                         RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1878                         pAd->bUpdateBcnCntDone = TRUE;
1879                         TxRetransmit = StaTx1.field.TxRetransmit;
1880                         TxSuccess = StaTx1.field.TxSuccess;
1881                         TxFailCount = TxStaCnt0.field.TxFailCount;
1882                         TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1883
1884                         pAd->RalinkCounters.OneSecTxRetryOkCount +=
1885                             StaTx1.field.TxRetransmit;
1886                         pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
1887                             StaTx1.field.TxSuccess;
1888                         pAd->RalinkCounters.OneSecTxFailCount +=
1889                             TxStaCnt0.field.TxFailCount;
1890                         pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
1891                             StaTx1.field.TxSuccess;
1892                         pAd->WlanCounters.RetryCount.u.LowPart +=
1893                             StaTx1.field.TxRetransmit;
1894                         pAd->WlanCounters.FailedCount.u.LowPart +=
1895                             TxStaCnt0.field.TxFailCount;
1896
1897                         // if no traffic in the past 1-sec period, don't change TX rate,
1898                         // but clear all bad history. because the bad history may affect the next
1899                         // Chariot throughput test
1900                         AccuTxTotalCnt =
1901                             pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1902                             pAd->RalinkCounters.OneSecTxRetryOkCount +
1903                             pAd->RalinkCounters.OneSecTxFailCount;
1904
1905                         if (TxTotalCnt)
1906                                 TxErrorRatio =
1907                                     ((TxRetransmit +
1908                                       TxFailCount) * 100) / TxTotalCnt;
1909                 } else {
1910                         if (INFRA_ON(pAd) && (i == 1))
1911                                 Rssi = RTMPMaxRssi(pAd,
1912                                                    pRssi->AvgRssi0,
1913                                                    pRssi->AvgRssi1,
1914                                                    pRssi->AvgRssi2);
1915                         else
1916                                 Rssi = RTMPMaxRssi(pAd,
1917                                                    pEntry->RssiSample.AvgRssi0,
1918                                                    pEntry->RssiSample.AvgRssi1,
1919                                                    pEntry->RssiSample.AvgRssi2);
1920
1921                         TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1922                             pEntry->OneSecTxRetryOkCount +
1923                             pEntry->OneSecTxFailCount;
1924
1925                         if (TxTotalCnt)
1926                                 TxErrorRatio =
1927                                     ((pEntry->OneSecTxRetryOkCount +
1928                                       pEntry->OneSecTxFailCount) * 100) /
1929                                     TxTotalCnt;
1930                 }
1931
1932                 if (TxTotalCnt) {
1933                         /*
1934                            Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1935                            We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1936                          */
1937                         if (TxErrorRatio == 100) {
1938                                 TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp;
1939                                 ULONG Index;
1940                                 ULONG MACValue;
1941
1942                                 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1943                                 TxRtyCfgtmp.word = TxRtyCfg.word;
1944                                 TxRtyCfg.field.LongRtyLimit = 0x0;
1945                                 TxRtyCfg.field.ShortRtyLimit = 0x0;
1946                                 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1947
1948                                 RTMPusecDelay(1);
1949
1950                                 Index = 0;
1951                                 MACValue = 0;
1952                                 do {
1953                                         RTMP_IO_READ32(pAd, TXRXQ_PCNT,
1954                                                        &MACValue);
1955                                         if ((MACValue & 0xffffff) == 0)
1956                                                 break;
1957                                         Index++;
1958                                         RTMPusecDelay(1000);
1959                                 } while ((Index < 330)
1960                                          &&
1961                                          (!RTMP_TEST_FLAG
1962                                           (pAd,
1963                                            fRTMP_ADAPTER_HALT_IN_PROGRESS)));
1964
1965                                 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1966                                 TxRtyCfg.field.LongRtyLimit =
1967                                     TxRtyCfgtmp.field.LongRtyLimit;
1968                                 TxRtyCfg.field.ShortRtyLimit =
1969                                     TxRtyCfgtmp.field.ShortRtyLimit;
1970                                 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1971                         }
1972                 }
1973
1974                 CurrRateIdx = pEntry->CurrTxRateIndex;
1975
1976                 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
1977                                       &InitTxRateIdx);
1978
1979                 if (CurrRateIdx >= TableSize) {
1980                         CurrRateIdx = TableSize - 1;
1981                 }
1982                 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1983                 // So need to sync here.
1984                 pCurrTxRate =
1985                     (PRTMP_TX_RATE_SWITCH) & pTable[(CurrRateIdx + 1) * 5];
1986                 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1987                     //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1988                     ) {
1989
1990                         // Need to sync Real Tx rate and our record.
1991                         // Then return for next DRS.
1992                         pCurrTxRate =
1993                             (PRTMP_TX_RATE_SWITCH) & pTable[(InitTxRateIdx + 1)
1994                                                             * 5];
1995                         pEntry->CurrTxRateIndex = InitTxRateIdx;
1996                         MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1997
1998                         // reset all OneSecTx counters
1999                         RESET_ONE_SEC_TX_CNT(pEntry);
2000                         continue;
2001                 }
2002                 // decide the next upgrade rate and downgrade rate, if any
2003                 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
2004                         UpRateIdx = CurrRateIdx + 1;
2005                         DownRateIdx = CurrRateIdx - 1;
2006                 } else if (CurrRateIdx == 0) {
2007                         UpRateIdx = CurrRateIdx + 1;
2008                         DownRateIdx = CurrRateIdx;
2009                 } else if (CurrRateIdx == (TableSize - 1)) {
2010                         UpRateIdx = CurrRateIdx;
2011                         DownRateIdx = CurrRateIdx - 1;
2012                 }
2013
2014                 pCurrTxRate =
2015                     (PRTMP_TX_RATE_SWITCH) & pTable[(CurrRateIdx + 1) * 5];
2016
2017                 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2018                         TrainUp =
2019                             (pCurrTxRate->TrainUp +
2020                              (pCurrTxRate->TrainUp >> 1));
2021                         TrainDown =
2022                             (pCurrTxRate->TrainDown +
2023                              (pCurrTxRate->TrainDown >> 1));
2024                 } else {
2025                         TrainUp = pCurrTxRate->TrainUp;
2026                         TrainDown = pCurrTxRate->TrainDown;
2027                 }
2028
2029                 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2030
2031                 //
2032                 // Keep the last time TxRateChangeAction status.
2033                 //
2034                 pEntry->LastTimeTxRateChangeAction =
2035                     pEntry->LastSecTxRateChangeAction;
2036
2037                 //
2038                 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2039                 //         (criteria copied from RT2500 for Netopia case)
2040                 //
2041                 if (TxTotalCnt <= 15) {
2042                         CHAR idx = 0;
2043                         UCHAR TxRateIdx;
2044                         UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 =
2045                             0, MCS5 = 0, MCS6 = 0, MCS7 = 0;
2046                         UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2047                         UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0;       // 3*3
2048
2049                         // check the existence and index of each needed MCS
2050                         while (idx < pTable[0]) {
2051                                 pCurrTxRate =
2052                                     (PRTMP_TX_RATE_SWITCH) & pTable[(idx + 1) *
2053                                                                     5];
2054
2055                                 if (pCurrTxRate->CurrMCS == MCS_0) {
2056                                         MCS0 = idx;
2057                                 } else if (pCurrTxRate->CurrMCS == MCS_1) {
2058                                         MCS1 = idx;
2059                                 } else if (pCurrTxRate->CurrMCS == MCS_2) {
2060                                         MCS2 = idx;
2061                                 } else if (pCurrTxRate->CurrMCS == MCS_3) {
2062                                         MCS3 = idx;
2063                                 } else if (pCurrTxRate->CurrMCS == MCS_4) {
2064                                         MCS4 = idx;
2065                                 } else if (pCurrTxRate->CurrMCS == MCS_5) {
2066                                         MCS5 = idx;
2067                                 } else if (pCurrTxRate->CurrMCS == MCS_6) {
2068                                         MCS6 = idx;
2069                                 }
2070                                 //else if (pCurrTxRate->CurrMCS == MCS_7)
2071                                 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800))   // prevent the highest MCS using short GI when 1T and low throughput
2072                                 {
2073                                         MCS7 = idx;
2074                                 } else if (pCurrTxRate->CurrMCS == MCS_12) {
2075                                         MCS12 = idx;
2076                                 } else if (pCurrTxRate->CurrMCS == MCS_13) {
2077                                         MCS13 = idx;
2078                                 } else if (pCurrTxRate->CurrMCS == MCS_14) {
2079                                         MCS14 = idx;
2080                                 }
2081                                 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/)    //we hope to use ShortGI as initial rate
2082                                 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                                 {
2084                                         MCS15 = idx;
2085                                 } else if (pCurrTxRate->CurrMCS == MCS_20)      // 3*3
2086                                 {
2087                                         MCS20 = idx;
2088                                 } else if (pCurrTxRate->CurrMCS == MCS_21) {
2089                                         MCS21 = idx;
2090                                 } else if (pCurrTxRate->CurrMCS == MCS_22) {
2091                                         MCS22 = idx;
2092                                 } else if (pCurrTxRate->CurrMCS == MCS_23) {
2093                                         MCS23 = idx;
2094                                 }
2095                                 idx++;
2096                         }
2097
2098                         if (pAd->LatchRfRegs.Channel <= 14) {
2099                                 if (pAd->NicConfig2.field.ExternalLNAForG) {
2100                                         RssiOffset = 2;
2101                                 } else {
2102                                         RssiOffset = 5;
2103                                 }
2104                         } else {
2105                                 if (pAd->NicConfig2.field.ExternalLNAForA) {
2106                                         RssiOffset = 5;
2107                                 } else {
2108                                         RssiOffset = 8;
2109                                 }
2110                         }
2111
2112                         /*if (MCS15) */
2113                         if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) {    // N mode with 3 stream // 3*3
2114                                 if (MCS23 && (Rssi >= -70))
2115                                         TxRateIdx = MCS23;
2116                                 else if (MCS22 && (Rssi >= -72))
2117                                         TxRateIdx = MCS22;
2118                                 else if (MCS21 && (Rssi >= -76))
2119                                         TxRateIdx = MCS21;
2120                                 else if (MCS20 && (Rssi >= -78))
2121                                         TxRateIdx = MCS20;
2122                                 else if (MCS4 && (Rssi >= -82))
2123                                         TxRateIdx = MCS4;
2124                                 else if (MCS3 && (Rssi >= -84))
2125                                         TxRateIdx = MCS3;
2126                                 else if (MCS2 && (Rssi >= -86))
2127                                         TxRateIdx = MCS2;
2128                                 else if (MCS1 && (Rssi >= -88))
2129                                         TxRateIdx = MCS1;
2130                                 else
2131                                         TxRateIdx = MCS0;
2132                         }
2133 //              else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2134                         else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand))      // 3*3
2135                         {       // N mode with 2 stream
2136                                 if (MCS15 && (Rssi >= (-70 + RssiOffset)))
2137                                         TxRateIdx = MCS15;
2138                                 else if (MCS14 && (Rssi >= (-72 + RssiOffset)))
2139                                         TxRateIdx = MCS14;
2140                                 else if (MCS13 && (Rssi >= (-76 + RssiOffset)))
2141                                         TxRateIdx = MCS13;
2142                                 else if (MCS12 && (Rssi >= (-78 + RssiOffset)))
2143                                         TxRateIdx = MCS12;
2144                                 else if (MCS4 && (Rssi >= (-82 + RssiOffset)))
2145                                         TxRateIdx = MCS4;
2146                                 else if (MCS3 && (Rssi >= (-84 + RssiOffset)))
2147                                         TxRateIdx = MCS3;
2148                                 else if (MCS2 && (Rssi >= (-86 + RssiOffset)))
2149                                         TxRateIdx = MCS2;
2150                                 else if (MCS1 && (Rssi >= (-88 + RssiOffset)))
2151                                         TxRateIdx = MCS1;
2152                                 else
2153                                         TxRateIdx = MCS0;
2154                         } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) {    // N mode with 1 stream
2155                                 if (MCS7 && (Rssi > (-72 + RssiOffset)))
2156                                         TxRateIdx = MCS7;
2157                                 else if (MCS6 && (Rssi > (-74 + RssiOffset)))
2158                                         TxRateIdx = MCS6;
2159                                 else if (MCS5 && (Rssi > (-77 + RssiOffset)))
2160                                         TxRateIdx = MCS5;
2161                                 else if (MCS4 && (Rssi > (-79 + RssiOffset)))
2162                                         TxRateIdx = MCS4;
2163                                 else if (MCS3 && (Rssi > (-81 + RssiOffset)))
2164                                         TxRateIdx = MCS3;
2165                                 else if (MCS2 && (Rssi > (-83 + RssiOffset)))
2166                                         TxRateIdx = MCS2;
2167                                 else if (MCS1 && (Rssi > (-86 + RssiOffset)))
2168                                         TxRateIdx = MCS1;
2169                                 else
2170                                         TxRateIdx = MCS0;
2171                         } else {        // Legacy mode
2172                                 if (MCS7 && (Rssi > -70))
2173                                         TxRateIdx = MCS7;
2174                                 else if (MCS6 && (Rssi > -74))
2175                                         TxRateIdx = MCS6;
2176                                 else if (MCS5 && (Rssi > -78))
2177                                         TxRateIdx = MCS5;
2178                                 else if (MCS4 && (Rssi > -82))
2179                                         TxRateIdx = MCS4;
2180                                 else if (MCS4 == 0)     // for B-only mode
2181                                         TxRateIdx = MCS3;
2182                                 else if (MCS3 && (Rssi > -85))
2183                                         TxRateIdx = MCS3;
2184                                 else if (MCS2 && (Rssi > -87))
2185                                         TxRateIdx = MCS2;
2186                                 else if (MCS1 && (Rssi > -90))
2187                                         TxRateIdx = MCS1;
2188                                 else
2189                                         TxRateIdx = MCS0;
2190                         }
2191
2192                         //              if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2193                         {
2194                                 pEntry->CurrTxRateIndex = TxRateIdx;
2195                                 pNextTxRate =
2196                                     (PRTMP_TX_RATE_SWITCH) &
2197                                     pTable[(pEntry->CurrTxRateIndex + 1) * 5];
2198                                 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2199                         }
2200
2201                         NdisZeroMemory(pEntry->TxQuality,
2202                                        sizeof(USHORT) *
2203                                        MAX_STEP_OF_TX_RATE_SWITCH);
2204                         NdisZeroMemory(pEntry->PER,
2205                                        sizeof(UCHAR) *
2206                                        MAX_STEP_OF_TX_RATE_SWITCH);
2207                         pEntry->fLastSecAccordingRSSI = TRUE;
2208                         // reset all OneSecTx counters
2209                         RESET_ONE_SEC_TX_CNT(pEntry);
2210
2211                         continue;
2212                 }
2213
2214                 if (pEntry->fLastSecAccordingRSSI == TRUE) {
2215                         pEntry->fLastSecAccordingRSSI = FALSE;
2216                         pEntry->LastSecTxRateChangeAction = 0;
2217                         // reset all OneSecTx counters
2218                         RESET_ONE_SEC_TX_CNT(pEntry);
2219
2220                         continue;
2221                 }
2222
2223                 do {
2224                         BOOLEAN bTrainUpDown = FALSE;
2225
2226                         pEntry->CurrTxRateStableTime++;
2227
2228                         // downgrade TX quality if PER >= Rate-Down threshold
2229                         if (TxErrorRatio >= TrainDown) {
2230                                 bTrainUpDown = TRUE;
2231                                 pEntry->TxQuality[CurrRateIdx] =
2232                                     DRS_TX_QUALITY_WORST_BOUND;
2233                         }
2234                         // upgrade TX quality if PER <= Rate-Up threshold
2235                         else if (TxErrorRatio <= TrainUp) {
2236                                 bTrainUpDown = TRUE;
2237                                 bUpgradeQuality = TRUE;
2238                                 if (pEntry->TxQuality[CurrRateIdx])
2239                                         pEntry->TxQuality[CurrRateIdx]--;       // quality very good in CurrRate
2240
2241                                 if (pEntry->TxRateUpPenalty)
2242                                         pEntry->TxRateUpPenalty--;
2243                                 else if (pEntry->TxQuality[UpRateIdx])
2244                                         pEntry->TxQuality[UpRateIdx]--; // may improve next UP rate's quality
2245                         }
2246
2247                         pEntry->PER[CurrRateIdx] = (UCHAR) TxErrorRatio;
2248
2249                         if (bTrainUpDown) {
2250                                 // perform DRS - consider TxRate Down first, then rate up.
2251                                 if ((CurrRateIdx != DownRateIdx)
2252                                     && (pEntry->TxQuality[CurrRateIdx] >=
2253                                         DRS_TX_QUALITY_WORST_BOUND)) {
2254                                         pEntry->CurrTxRateIndex = DownRateIdx;
2255                                 } else if ((CurrRateIdx != UpRateIdx)
2256                                            && (pEntry->TxQuality[UpRateIdx] <=
2257                                                0)) {
2258                                         pEntry->CurrTxRateIndex = UpRateIdx;
2259                                 }
2260                         }
2261                 } while (FALSE);
2262
2263                 // if rate-up happen, clear all bad history of all TX rates
2264                 if (pEntry->CurrTxRateIndex > CurrRateIdx) {
2265                         pEntry->CurrTxRateStableTime = 0;
2266                         pEntry->TxRateUpPenalty = 0;
2267                         pEntry->LastSecTxRateChangeAction = 1;  // rate UP
2268                         NdisZeroMemory(pEntry->TxQuality,
2269                                        sizeof(USHORT) *
2270                                        MAX_STEP_OF_TX_RATE_SWITCH);
2271                         NdisZeroMemory(pEntry->PER,
2272                                        sizeof(UCHAR) *
2273                                        MAX_STEP_OF_TX_RATE_SWITCH);
2274
2275                         //
2276                         // For TxRate fast train up
2277                         //
2278                         if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2279                                 RTMPSetTimer(&pAd->StaCfg.
2280                                              StaQuickResponeForRateUpTimer,
2281                                              100);
2282
2283                                 pAd->StaCfg.
2284                                     StaQuickResponeForRateUpTimerRunning = TRUE;
2285                         }
2286                         bTxRateChanged = TRUE;
2287                 }
2288                 // if rate-down happen, only clear DownRate's bad history
2289                 else if (pEntry->CurrTxRateIndex < CurrRateIdx) {
2290                         pEntry->CurrTxRateStableTime = 0;
2291                         pEntry->TxRateUpPenalty = 0;    // no penalty
2292                         pEntry->LastSecTxRateChangeAction = 2;  // rate DOWN
2293                         pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2294                         pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2295
2296                         //
2297                         // For TxRate fast train down
2298                         //
2299                         if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2300                                 RTMPSetTimer(&pAd->StaCfg.
2301                                              StaQuickResponeForRateUpTimer,
2302                                              100);
2303
2304                                 pAd->StaCfg.
2305                                     StaQuickResponeForRateUpTimerRunning = TRUE;
2306                         }
2307                         bTxRateChanged = TRUE;
2308                 } else {
2309                         pEntry->LastSecTxRateChangeAction = 0;  // rate no change
2310                         bTxRateChanged = FALSE;
2311                 }
2312
2313                 pEntry->LastTxOkCount = TxSuccess;
2314                 {
2315                         UCHAR tmpTxRate;
2316
2317                         // to fix tcp ack issue
2318                         if (!bTxRateChanged
2319                             && (pAd->RalinkCounters.OneSecReceivedByteCount >
2320                                 (pAd->RalinkCounters.
2321                                  OneSecTransmittedByteCount * 5))) {
2322                                 tmpTxRate = DownRateIdx;
2323                                 DBGPRINT_RAW(RT_DEBUG_TRACE,
2324                                              ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2325                                               pAd->RalinkCounters.
2326                                               OneSecReceivedByteCount,
2327                                               pAd->RalinkCounters.
2328                                               OneSecTransmittedByteCount,
2329                                               pEntry->CurrTxRateIndex,
2330                                               tmpTxRate));
2331                         } else {
2332                                 tmpTxRate = pEntry->CurrTxRateIndex;
2333                         }
2334
2335                         pNextTxRate =
2336                             (PRTMP_TX_RATE_SWITCH) & pTable[(tmpTxRate + 1) *
2337                                                             5];
2338                 }
2339                 if (bTxRateChanged && pNextTxRate) {
2340                         MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2341                 }
2342                 // reset all OneSecTx counters
2343                 RESET_ONE_SEC_TX_CNT(pEntry);
2344         }
2345 }
2346
2347 /*
2348         ========================================================================
2349         Routine Description:
2350                 Station side, Auto TxRate faster train up timer call back function.
2351
2352         Arguments:
2353                 SystemSpecific1                 - Not used.
2354                 FunctionContext                 - Pointer to our Adapter context.
2355                 SystemSpecific2                 - Not used.
2356                 SystemSpecific3                 - Not used.
2357
2358         Return Value:
2359                 None
2360
2361         ========================================================================
2362 */
2363 VOID StaQuickResponeForRateUpExec(IN PVOID SystemSpecific1,
2364                                   IN PVOID FunctionContext,
2365                                   IN PVOID SystemSpecific2,
2366                                   IN PVOID SystemSpecific3)
2367 {
2368         PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) FunctionContext;
2369         UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2370         ULONG TxTotalCnt;
2371         ULONG TxErrorRatio = 0;
2372         BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2373         PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2374         PUCHAR pTable;
2375         UCHAR TableSize = 0;
2376         UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2377         TX_STA_CNT1_STRUC StaTx1;
2378         TX_STA_CNT0_STRUC TxStaCnt0;
2379         CHAR Rssi, ratio;
2380         ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2381         MAC_TABLE_ENTRY *pEntry;
2382         ULONG i;
2383
2384         pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2385
2386         //
2387         // walk through MAC table, see if need to change AP's TX rate toward each entry
2388         //
2389         for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
2390                 pEntry = &pAd->MacTab.Content[i];
2391
2392                 // check if this entry need to switch rate automatically
2393                 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2394                         continue;
2395
2396                 if (INFRA_ON(pAd) && (i == 1))
2397                         Rssi = RTMPMaxRssi(pAd,
2398                                            pAd->StaCfg.RssiSample.AvgRssi0,
2399                                            pAd->StaCfg.RssiSample.AvgRssi1,
2400                                            pAd->StaCfg.RssiSample.AvgRssi2);
2401                 else
2402                         Rssi = RTMPMaxRssi(pAd,
2403                                            pEntry->RssiSample.AvgRssi0,
2404                                            pEntry->RssiSample.AvgRssi1,
2405                                            pEntry->RssiSample.AvgRssi2);
2406
2407                 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2408
2409                 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
2410                                       &InitTxRateIdx);
2411
2412                 // decide the next upgrade rate and downgrade rate, if any
2413                 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
2414                         UpRateIdx = CurrRateIdx + 1;
2415                         DownRateIdx = CurrRateIdx - 1;
2416                 } else if (CurrRateIdx == 0) {
2417                         UpRateIdx = CurrRateIdx + 1;
2418                         DownRateIdx = CurrRateIdx;
2419                 } else if (CurrRateIdx == (TableSize - 1)) {
2420                         UpRateIdx = CurrRateIdx;
2421                         DownRateIdx = CurrRateIdx - 1;
2422                 }
2423
2424                 pCurrTxRate =
2425                     (PRTMP_TX_RATE_SWITCH) & pTable[(CurrRateIdx + 1) * 5];
2426
2427                 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2428                         TrainUp =
2429                             (pCurrTxRate->TrainUp +
2430                              (pCurrTxRate->TrainUp >> 1));
2431                         TrainDown =
2432                             (pCurrTxRate->TrainDown +
2433                              (pCurrTxRate->TrainDown >> 1));
2434                 } else {
2435                         TrainUp = pCurrTxRate->TrainUp;
2436                         TrainDown = pCurrTxRate->TrainDown;
2437                 }
2438
2439                 if (pAd->MacTab.Size == 1) {
2440                         // Update statistic counter
2441                         RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2442                         RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2443
2444                         TxRetransmit = StaTx1.field.TxRetransmit;
2445                         TxSuccess = StaTx1.field.TxSuccess;
2446                         TxFailCount = TxStaCnt0.field.TxFailCount;
2447                         TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2448
2449                         pAd->RalinkCounters.OneSecTxRetryOkCount +=
2450                             StaTx1.field.TxRetransmit;
2451                         pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
2452                             StaTx1.field.TxSuccess;
2453                         pAd->RalinkCounters.OneSecTxFailCount +=
2454                             TxStaCnt0.field.TxFailCount;
2455                         pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
2456                             StaTx1.field.TxSuccess;
2457                         pAd->WlanCounters.RetryCount.u.LowPart +=
2458                             StaTx1.field.TxRetransmit;
2459                         pAd->WlanCounters.FailedCount.u.LowPart +=
2460                             TxStaCnt0.field.TxFailCount;
2461
2462                         if (TxTotalCnt)
2463                                 TxErrorRatio =
2464                                     ((TxRetransmit +
2465                                       TxFailCount) * 100) / TxTotalCnt;
2466                 } else {
2467                         TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2468                             pEntry->OneSecTxRetryOkCount +
2469                             pEntry->OneSecTxFailCount;
2470
2471                         if (TxTotalCnt)
2472                                 TxErrorRatio =
2473                                     ((pEntry->OneSecTxRetryOkCount +
2474                                       pEntry->OneSecTxFailCount) * 100) /
2475                                     TxTotalCnt;
2476                 }
2477
2478                 //
2479                 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2480                 //         (criteria copied from RT2500 for Netopia case)
2481                 //
2482                 if (TxTotalCnt <= 12) {
2483                         NdisZeroMemory(pAd->DrsCounters.TxQuality,
2484                                        sizeof(USHORT) *
2485                                        MAX_STEP_OF_TX_RATE_SWITCH);
2486                         NdisZeroMemory(pAd->DrsCounters.PER,
2487                                        sizeof(UCHAR) *
2488                                        MAX_STEP_OF_TX_RATE_SWITCH);
2489
2490                         if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2491                             && (CurrRateIdx != DownRateIdx)) {
2492                                 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2493                                 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2494                                     DRS_TX_QUALITY_WORST_BOUND;
2495                         } else
2496                             if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2497                                  2) && (CurrRateIdx != UpRateIdx)) {
2498                                 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2499                         }
2500
2501                         DBGPRINT_RAW(RT_DEBUG_TRACE,
2502                                      ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2503                         return;
2504                 }
2505
2506                 do {
2507                         ULONG OneSecTxNoRetryOKRationCount;
2508
2509                         if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2510                                 ratio = 5;
2511                         else
2512                                 ratio = 4;
2513
2514                         // downgrade TX quality if PER >= Rate-Down threshold
2515                         if (TxErrorRatio >= TrainDown) {
2516                                 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2517                                     DRS_TX_QUALITY_WORST_BOUND;
2518                         }
2519
2520                         pAd->DrsCounters.PER[CurrRateIdx] =
2521                             (UCHAR) TxErrorRatio;
2522
2523                         OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2524
2525                         // perform DRS - consider TxRate Down first, then rate up.
2526                         if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2527                             && (CurrRateIdx != DownRateIdx)) {
2528                                 if ((pAd->DrsCounters.LastTxOkCount + 2) >=
2529                                     OneSecTxNoRetryOKRationCount) {
2530                                         pAd->CommonCfg.TxRateIndex =
2531                                             DownRateIdx;
2532                                         pAd->DrsCounters.
2533                                             TxQuality[CurrRateIdx] =
2534                                             DRS_TX_QUALITY_WORST_BOUND;
2535
2536                                 }
2537
2538                         } else
2539                             if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2540                                  2) && (CurrRateIdx != UpRateIdx)) {
2541                                 if ((TxErrorRatio >= 50)
2542                                     || (TxErrorRatio >= TrainDown)) {
2543
2544                                 } else if ((pAd->DrsCounters.LastTxOkCount + 2)
2545                                            >= OneSecTxNoRetryOKRationCount) {
2546                                         pAd->CommonCfg.TxRateIndex = UpRateIdx;
2547                                 }
2548                         }
2549                 } while (FALSE);
2550
2551                 // if rate-up happen, clear all bad history of all TX rates
2552                 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) {
2553                         pAd->DrsCounters.TxRateUpPenalty = 0;
2554                         NdisZeroMemory(pAd->DrsCounters.TxQuality,
2555                                        sizeof(USHORT) *
2556                                        MAX_STEP_OF_TX_RATE_SWITCH);
2557                         NdisZeroMemory(pAd->DrsCounters.PER,
2558                                        sizeof(UCHAR) *
2559                                        MAX_STEP_OF_TX_RATE_SWITCH);
2560                         bTxRateChanged = TRUE;
2561                 }
2562                 // if rate-down happen, only clear DownRate's bad history
2563                 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) {
2564                         DBGPRINT_RAW(RT_DEBUG_TRACE,
2565                                      ("QuickDRS: --TX rate from %d to %d \n",
2566                                       CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2567
2568                         pAd->DrsCounters.TxRateUpPenalty = 0;   // no penalty
2569                         pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] =
2570                             0;
2571                         pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2572                         bTxRateChanged = TRUE;
2573                 } else {
2574                         bTxRateChanged = FALSE;
2575                 }
2576
2577                 pNextTxRate =
2578                     (PRTMP_TX_RATE_SWITCH) &
2579                     pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5];
2580                 if (bTxRateChanged && pNextTxRate) {
2581                         MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2582                 }
2583         }
2584 }
2585
2586 /*
2587         ==========================================================================
2588         Description:
2589                 This routine is executed periodically inside MlmePeriodicExec() after
2590                 association with an AP.
2591                 It checks if StaCfg.Psm is consistent with user policy (recorded in
2592                 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2593                 there're some conditions to consider:
2594                 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2595                    the time when Mibss==TRUE
2596                 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2597                    if outgoing traffic available in TxRing or MgmtRing.
2598         Output:
2599                 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2600
2601         IRQL = DISPATCH_LEVEL
2602
2603         ==========================================================================
2604  */
2605 VOID MlmeCheckPsmChange(IN PRTMP_ADAPTER pAd, IN ULONG Now32)
2606 {
2607         ULONG PowerMode;
2608
2609         // condition -
2610         // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2611         // 2. user wants either MAX_PSP or FAST_PSP
2612         // 3. but current psm is not in PWR_SAVE
2613         // 4. CNTL state machine is not doing SCANning
2614         // 5. no TX SUCCESS event for the past 1-sec period
2615         PowerMode = pAd->StaCfg.WindowsPowerMode;
2616
2617         if (INFRA_ON(pAd) &&
2618             (PowerMode != Ndis802_11PowerModeCAM) &&
2619             (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2620 //              (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2621             (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
2622             RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2623             /*&&
2624                (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2625                (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2626             ) {
2627                 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2628                 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2629                 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
2630                 if (!
2631                     (pAd->CommonCfg.bAPSDCapable
2632                      && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
2633                         RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2634                 } else {
2635                         RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2636                 }
2637         }
2638 }
2639
2640 // IRQL = PASSIVE_LEVEL
2641 // IRQL = DISPATCH_LEVEL
2642 VOID MlmeSetPsmBit(IN PRTMP_ADAPTER pAd, IN USHORT psm)
2643 {
2644         AUTO_RSP_CFG_STRUC csr4;
2645
2646         pAd->StaCfg.Psm = psm;
2647         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2648         csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0;
2649         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2650
2651         DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2652 }
2653
2654 /*
2655         ==========================================================================
2656         Description:
2657                 This routine calculates TxPER, RxPER of the past N-sec period. And
2658                 according to the calculation result, ChannelQuality is calculated here
2659                 to decide if current AP is still doing the job.
2660
2661                 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2662         Output:
2663                 StaCfg.ChannelQuality - 0..100
2664
2665         IRQL = DISPATCH_LEVEL
2666
2667         NOTE: This routine decide channle quality based on RX CRC error ratio.
2668                 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2669                 is performed right before this routine, so that this routine can decide
2670                 channel quality based on the most up-to-date information
2671         ==========================================================================
2672  */
2673 VOID MlmeCalculateChannelQuality(IN PRTMP_ADAPTER pAd,
2674                                  IN PMAC_TABLE_ENTRY pMacEntry, IN ULONG Now32)
2675 {
2676         ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
2677         ULONG RxCnt, RxPER;
2678         UCHAR NorRssi;
2679         CHAR MaxRssi;
2680         RSSI_SAMPLE *pRssiSample = NULL;
2681         UINT32 OneSecTxNoRetryOkCount = 0;
2682         UINT32 OneSecTxRetryOkCount = 0;
2683         UINT32 OneSecTxFailCount = 0;
2684         UINT32 OneSecRxOkCnt = 0;
2685         UINT32 OneSecRxFcsErrCnt = 0;
2686         ULONG ChannelQuality = 0;       // 0..100, Channel Quality Indication for Roaming
2687         ULONG BeaconLostTime = pAd->StaCfg.BeaconLostTime;
2688
2689         if (pAd->OpMode == OPMODE_STA) {
2690                 pRssiSample = &pAd->StaCfg.RssiSample;
2691                 OneSecTxNoRetryOkCount =
2692                     pAd->RalinkCounters.OneSecTxNoRetryOkCount;
2693                 OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2694                 OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2695                 OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2696                 OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
2697         }
2698
2699         MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
2700                               pRssiSample->LastRssi1, pRssiSample->LastRssi2);
2701
2702         //
2703         // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
2704         //
2705         TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2706         TxCnt = TxOkCnt + OneSecTxFailCount;
2707         if (TxCnt < 5) {
2708                 TxPER = 0;
2709                 TxPRR = 0;
2710         } else {
2711                 TxPER = (OneSecTxFailCount * 100) / TxCnt;
2712                 TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2713         }
2714
2715         //
2716         // calculate RX PER - don't take RxPER into consideration if too few sample
2717         //
2718         RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2719         if (RxCnt < 5)
2720                 RxPER = 0;
2721         else
2722                 RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
2723
2724         //
2725         // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
2726         //
2727         if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) &&     // no heavy traffic
2728             ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) {
2729                 DBGPRINT(RT_DEBUG_TRACE,
2730                          ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2731                           BeaconLostTime, TxOkCnt));
2732                 ChannelQuality = 0;
2733         } else {
2734                 // Normalize Rssi
2735                 if (MaxRssi > -40)
2736                         NorRssi = 100;
2737                 else if (MaxRssi < -90)
2738                         NorRssi = 0;
2739                 else
2740                         NorRssi = (MaxRssi + 90) * 2;
2741
2742                 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER        (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
2743                 ChannelQuality = (RSSI_WEIGHTING * NorRssi +
2744                                   TX_WEIGHTING * (100 - TxPRR) +
2745                                   RX_WEIGHTING * (100 - RxPER)) / 100;
2746         }
2747
2748         if (pAd->OpMode == OPMODE_STA)
2749                 pAd->Mlme.ChannelQuality =
2750                     (ChannelQuality > 100) ? 100 : ChannelQuality;
2751
2752 }
2753
2754 // IRQL = DISPATCH_LEVEL
2755 VOID MlmeSetTxPreamble(IN PRTMP_ADAPTER pAd, IN USHORT TxPreamble)
2756 {
2757         AUTO_RSP_CFG_STRUC csr4;
2758
2759         //
2760         // Always use Long preamble before verifiation short preamble functionality works well.
2761         // Todo: remove the following line if short preamble functionality works
2762         //
2763         //TxPreamble = Rt802_11PreambleLong;
2764
2765         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2766         if (TxPreamble == Rt802_11PreambleLong) {
2767                 DBGPRINT(RT_DEBUG_TRACE,
2768                          ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2769                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2770                 csr4.field.AutoResponderPreamble = 0;
2771         } else {
2772                 // NOTE: 1Mbps should always use long preamble
2773                 DBGPRINT(RT_DEBUG_TRACE,
2774                          ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2775                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2776                 csr4.field.AutoResponderPreamble = 1;
2777         }
2778
2779         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2780 }
2781
2782 /*
2783     ==========================================================================
2784     Description:
2785         Update basic rate bitmap
2786     ==========================================================================
2787  */
2788
2789 VOID UpdateBasicRateBitmap(IN PRTMP_ADAPTER pAdapter)
2790 {
2791         INT i, j;
2792         /* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
2793         UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2794         UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2795         UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2796         ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2797
2798         /* if A mode, always use fix BasicRateBitMap */
2799         //if (pAdapter->CommonCfg.Channel == PHY_11A)
2800         if (pAdapter->CommonCfg.Channel > 14)
2801                 pAdapter->CommonCfg.BasicRateBitmap = 0x150;    /* 6, 12, 24M */
2802         /* End of if */
2803
2804         if (pAdapter->CommonCfg.BasicRateBitmap > 4095) {
2805                 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2806                 return;
2807         }
2808         /* End of if */
2809         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2810                 sup_p[i] &= 0x7f;
2811                 ext_p[i] &= 0x7f;
2812         }                       /* End of for */
2813
2814         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2815                 if (bitmap & (1 << i)) {
2816                         for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2817                                 if (sup_p[j] == rate[i])
2818                                         sup_p[j] |= 0x80;
2819                                 /* End of if */
2820                         }       /* End of for */
2821
2822                         for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2823                                 if (ext_p[j] == rate[i])
2824                                         ext_p[j] |= 0x80;
2825                                 /* End of if */
2826                         }       /* End of for */
2827                 }               /* End of if */
2828         }                       /* End of for */
2829 }                               /* End of UpdateBasicRateBitmap */
2830
2831 // IRQL = PASSIVE_LEVEL
2832 // IRQL = DISPATCH_LEVEL
2833 // bLinkUp is to identify the inital link speed.
2834 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2835 VOID MlmeUpdateTxRates(IN PRTMP_ADAPTER pAd, IN BOOLEAN bLinkUp, IN UCHAR apidx)
2836 {
2837         int i, num;
2838         UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2839         UCHAR MinSupport = RATE_54;
2840         ULONG BasicRateBitmap = 0;
2841         UCHAR CurrBasicRate = RATE_1;
2842         UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2843         PHTTRANSMIT_SETTING pHtPhy = NULL;
2844         PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2845         PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2846         BOOLEAN *auto_rate_cur_p;
2847         UCHAR HtMcs = MCS_AUTO;
2848
2849         // find max desired rate
2850         UpdateBasicRateBitmap(pAd);
2851
2852         num = 0;
2853         auto_rate_cur_p = NULL;
2854         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2855                 switch (pAd->CommonCfg.DesireRate[i] & 0x7f) {
2856                 case 2:
2857                         Rate = RATE_1;
2858                         num++;
2859                         break;
2860                 case 4:
2861                         Rate = RATE_2;
2862                         num++;
2863                         break;
2864                 case 11:
2865                         Rate = RATE_5_5;
2866                         num++;
2867                         break;
2868                 case 22:
2869                         Rate = RATE_11;
2870                         num++;
2871                         break;
2872                 case 12:
2873                         Rate = RATE_6;
2874                         num++;
2875                         break;
2876                 case 18:
2877                         Rate = RATE_9;
2878                         num++;
2879                         break;
2880                 case 24:
2881                         Rate = RATE_12;
2882                         num++;
2883                         break;
2884                 case 36:
2885                         Rate = RATE_18;
2886                         num++;
2887                         break;
2888                 case 48:
2889                         Rate = RATE_24;
2890                         num++;
2891                         break;
2892                 case 72:
2893                         Rate = RATE_36;
2894                         num++;
2895                         break;
2896                 case 96:
2897                         Rate = RATE_48;
2898                         num++;
2899                         break;
2900                 case 108:
2901                         Rate = RATE_54;
2902                         num++;
2903                         break;
2904                         //default: Rate = RATE_1;   break;
2905                 }
2906                 if (MaxDesire < Rate)
2907                         MaxDesire = Rate;
2908         }
2909
2910 //===========================================================================
2911 //===========================================================================
2912         {
2913                 pHtPhy = &pAd->StaCfg.HTPhyMode;
2914                 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2915                 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2916
2917                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2918                 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2919
2920                 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2921                     (pAd->CommonCfg.PhyMode == PHY_11B) &&
2922                     (MaxDesire > RATE_11)) {
2923                         MaxDesire = RATE_11;
2924                 }
2925         }
2926
2927         pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2928         pMinHtPhy->word = 0;
2929         pMaxHtPhy->word = 0;
2930         pHtPhy->word = 0;
2931
2932         // Auto rate switching is enabled only if more than one DESIRED RATES are
2933         // specified; otherwise disabled
2934         if (num <= 1) {
2935                 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2936                 //pAd->CommonCfg.bAutoTxRateSwitch      = FALSE;
2937                 *auto_rate_cur_p = FALSE;
2938         } else {
2939                 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2940                 //pAd->CommonCfg.bAutoTxRateSwitch      = TRUE;
2941                 *auto_rate_cur_p = TRUE;
2942         }
2943
2944         if (HtMcs != MCS_AUTO) {
2945                 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2946                 //pAd->CommonCfg.bAutoTxRateSwitch      = FALSE;
2947                 *auto_rate_cur_p = FALSE;
2948         } else {
2949                 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2950                 //pAd->CommonCfg.bAutoTxRateSwitch      = TRUE;
2951                 *auto_rate_cur_p = TRUE;
2952         }
2953
2954         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
2955                 pSupRate = &pAd->StaActive.SupRate[0];
2956                 pExtRate = &pAd->StaActive.ExtRate[0];
2957                 SupRateLen = pAd->StaActive.SupRateLen;
2958                 ExtRateLen = pAd->StaActive.ExtRateLen;
2959         } else {
2960                 pSupRate = &pAd->CommonCfg.SupRate[0];
2961                 pExtRate = &pAd->CommonCfg.ExtRate[0];
2962                 SupRateLen = pAd->CommonCfg.SupRateLen;
2963                 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2964         }
2965
2966         // find max supported rate
2967         for (i = 0; i < SupRateLen; i++) {
2968                 switch (pSupRate[i] & 0x7f) {
2969                 case 2:
2970                         Rate = RATE_1;
2971                         if (pSupRate[i] & 0x80)
2972                                 BasicRateBitmap |= 0x0001;
2973                         break;
2974                 case 4:
2975                         Rate = RATE_2;
2976                         if (pSupRate[i] & 0x80)
2977                                 BasicRateBitmap |= 0x0002;
2978                         break;
2979                 case 11:
2980                         Rate = RATE_5_5;
2981                         if (pSupRate[i] & 0x80)
2982                                 BasicRateBitmap |= 0x0004;
2983                         break;
2984                 case 22:
2985                         Rate = RATE_11;
2986                         if (pSupRate[i] & 0x80)
2987                                 BasicRateBitmap |= 0x0008;
2988                         break;
2989                 case 12:
2990                         Rate = RATE_6;  /*if (pSupRate[i] & 0x80) */
2991                         BasicRateBitmap |= 0x0010;
2992                         break;
2993                 case 18:
2994                         Rate = RATE_9;
2995                         if (pSupRate[i] & 0x80)
2996                                 BasicRateBitmap |= 0x0020;
2997                         break;
2998                 case 24:
2999                         Rate = RATE_12; /*if (pSupRate[i] & 0x80) */
3000                         BasicRateBitmap |= 0x0040;
3001                         break;
3002                 case 36:
3003                         Rate = RATE_18;
3004                         if (pSupRate[i] & 0x80)
3005                                 BasicRateBitmap |= 0x0080;
3006                         break;
3007                 case 48:
3008                         Rate = RATE_24; /*if (pSupRate[i] & 0x80) */
3009                         BasicRateBitmap |= 0x0100;
3010                         break;
3011                 case 72:
3012                         Rate = RATE_36;
3013                         if (pSupRate[i] & 0x80)
3014                                 BasicRateBitmap |= 0x0200;
3015                         break;
3016                 case 96:
3017                         Rate = RATE_48;
3018                         if (pSupRate[i] & 0x80)
3019                                 BasicRateBitmap |= 0x0400;
3020                         break;
3021                 case 108:
3022                         Rate = RATE_54;
3023                         if (pSupRate[i] & 0x80)
3024                                 BasicRateBitmap |= 0x0800;
3025                         break;
3026                 default:
3027                         Rate = RATE_1;
3028                         break;
3029                 }
3030                 if (MaxSupport < Rate)
3031                         MaxSupport = Rate;
3032
3033                 if (MinSupport > Rate)
3034                         MinSupport = Rate;
3035         }
3036
3037         for (i = 0; i < ExtRateLen; i++) {
3038                 switch (pExtRate[i] & 0x7f) {
3039                 case 2:
3040                         Rate = RATE_1;
3041                         if (pExtRate[i] & 0x80)
3042                                 BasicRateBitmap |= 0x0001;
3043                         break;
3044                 case 4:
3045                         Rate = RATE_2;
3046                         if (pExtRate[i] & 0x80)
3047                                 BasicRateBitmap |= 0x0002;
3048                         break;
3049                 case 11:
3050                         Rate = RATE_5_5;
3051                         if (pExtRate[i] & 0x80)
3052                                 BasicRateBitmap |= 0x0004;
3053                         break;
3054                 case 22:
3055                         Rate = RATE_11;
3056                         if (pExtRate[i] & 0x80)
3057                                 BasicRateBitmap |= 0x0008;
3058                         break;
3059                 case 12:
3060                         Rate = RATE_6;  /*if (pExtRate[i] & 0x80) */
3061                         BasicRateBitmap |= 0x0010;
3062                         break;
3063                 case 18:
3064                         Rate = RATE_9;
3065                         if (pExtRate[i] & 0x80)
3066                                 BasicRateBitmap |= 0x0020;
3067                         break;
3068                 case 24:
3069                         Rate = RATE_12; /*if (pExtRate[i] & 0x80) */
3070                         BasicRateBitmap |= 0x0040;
3071                         break;
3072                 case 36:
3073                         Rate = RATE_18;
3074                         if (pExtRate[i] & 0x80)
3075                                 BasicRateBitmap |= 0x0080;
3076                         break;
3077                 case 48:
3078                         Rate = RATE_24; /*if (pExtRate[i] & 0x80) */
3079                         BasicRateBitmap |= 0x0100;
3080                         break;
3081                 case 72:
3082                         Rate = RATE_36;
3083                         if (pExtRate[i] & 0x80)
3084                                 BasicRateBitmap |= 0x0200;
3085                         break;
3086                 case 96:
3087                         Rate = RATE_48;
3088                         if (pExtRate[i] & 0x80)
3089                                 BasicRateBitmap |= 0x0400;
3090                         break;
3091                 case 108:
3092                         Rate = RATE_54;
3093                         if (pExtRate[i] & 0x80)
3094                                 BasicRateBitmap |= 0x0800;
3095                         break;
3096                 default:
3097                         Rate = RATE_1;
3098                         break;
3099                 }
3100                 if (MaxSupport < Rate)
3101                         MaxSupport = Rate;
3102
3103                 if (MinSupport > Rate)
3104                         MinSupport = Rate;
3105         }
3106
3107         RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3108
3109         // bug fix
3110         // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
3111
3112         // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3113         // the DURATION field of outgoing uniicast DATA/MGMT frame
3114         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
3115                 if (BasicRateBitmap & (0x01 << i))
3116                         CurrBasicRate = (UCHAR) i;
3117                 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3118         }
3119
3120         DBGPRINT(RT_DEBUG_TRACE,
3121                  ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3122                   RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3123         // max tx rate = min {max desire rate, max supported rate}
3124         if (MaxSupport < MaxDesire)
3125                 pAd->CommonCfg.MaxTxRate = MaxSupport;
3126         else
3127                 pAd->CommonCfg.MaxTxRate = MaxDesire;
3128
3129         pAd->CommonCfg.MinTxRate = MinSupport;
3130         // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
3131         // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
3132         // on average RSSI
3133         //       1. RSSI >= -70db, start at 54 Mbps (short distance)
3134         //       2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
3135         //       3. -75 > RSSI, start at 11 Mbps (long distance)
3136         //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
3137         //      OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
3138         if (*auto_rate_cur_p) {
3139                 short dbm = 0;
3140
3141                 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3142
3143                 if (bLinkUp == TRUE)
3144                         pAd->CommonCfg.TxRate = RATE_24;
3145                 else
3146                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3147
3148                 if (dbm < -75)
3149                         pAd->CommonCfg.TxRate = RATE_11;
3150                 else if (dbm < -70)
3151                         pAd->CommonCfg.TxRate = RATE_24;
3152
3153                 // should never exceed MaxTxRate (consider 11B-only mode)
3154                 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3155                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3156
3157                 pAd->CommonCfg.TxRateIndex = 0;
3158         } else {
3159                 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3160                 pHtPhy->field.MCS =
3161                     (pAd->CommonCfg.MaxTxRate >
3162                      3) ? (pAd->CommonCfg.MaxTxRate -
3163                            4) : pAd->CommonCfg.MaxTxRate;
3164                 pHtPhy->field.MODE =
3165                     (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3166
3167                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC =
3168                     pHtPhy->field.STBC;
3169                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI =
3170                     pHtPhy->field.ShortGI;
3171                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS =
3172                     pHtPhy->field.MCS;
3173                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE =
3174                     pHtPhy->field.MODE;
3175         }
3176
3177         if (pAd->CommonCfg.TxRate <= RATE_11) {
3178                 pMaxHtPhy->field.MODE = MODE_CCK;
3179                 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3180                 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3181         } else {
3182                 pMaxHtPhy->field.MODE = MODE_OFDM;
3183                 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3184                 if (pAd->CommonCfg.MinTxRate >= RATE_6
3185                     && (pAd->CommonCfg.MinTxRate <= RATE_54)) {
3186                         pMinHtPhy->field.MCS =
3187                             OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
3188                 } else {
3189                         pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3190                 }
3191         }
3192
3193         pHtPhy->word = (pMaxHtPhy->word);
3194         if (bLinkUp && (pAd->OpMode == OPMODE_STA)) {
3195                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3196                 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word =
3197                     pMaxHtPhy->word;
3198                 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word =
3199                     pMinHtPhy->word;
3200         } else {
3201                 switch (pAd->CommonCfg.PhyMode) {
3202                 case PHY_11BG_MIXED:
3203                 case PHY_11B:
3204                 case PHY_11BGN_MIXED:
3205                         pAd->CommonCfg.MlmeRate = RATE_1;
3206                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3207                         pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3208
3209 //#ifdef        WIFI_TEST
3210                         pAd->CommonCfg.RtsRate = RATE_11;
3211 //#else
3212 //                              pAd->CommonCfg.RtsRate = RATE_1;
3213 //#endif
3214                         break;
3215                 case PHY_11G:
3216                 case PHY_11A:
3217                 case PHY_11AGN_MIXED:
3218                 case PHY_11GN_MIXED:
3219                 case PHY_11N_2_4G:
3220                 case PHY_11AN_MIXED:
3221                 case PHY_11N_5G:
3222                         pAd->CommonCfg.MlmeRate = RATE_6;
3223                         pAd->CommonCfg.RtsRate = RATE_6;
3224                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3225                         pAd->CommonCfg.MlmeTransmit.field.MCS =
3226                             OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3227                         break;
3228                 case PHY_11ABG_MIXED:
3229                 case PHY_11ABGN_MIXED:
3230                         if (pAd->CommonCfg.Channel <= 14) {
3231                                 pAd->CommonCfg.MlmeRate = RATE_1;
3232                                 pAd->CommonCfg.RtsRate = RATE_1;
3233                                 pAd->CommonCfg.MlmeTransmit.field.MODE =
3234                                     MODE_CCK;
3235                                 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3236                         } else {
3237                                 pAd->CommonCfg.MlmeRate = RATE_6;
3238                                 pAd->CommonCfg.RtsRate = RATE_6;
3239                                 pAd->CommonCfg.MlmeTransmit.field.MODE =
3240                                     MODE_OFDM;
3241                                 pAd->CommonCfg.MlmeTransmit.field.MCS =
3242                                     OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3243                         }
3244                         break;
3245                 default:        // error
3246                         pAd->CommonCfg.MlmeRate = RATE_6;
3247                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3248                         pAd->CommonCfg.MlmeTransmit.field.MCS =
3249                             OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3250                         pAd->CommonCfg.RtsRate = RATE_1;
3251                         break;
3252                 }
3253                 //
3254                 // Keep Basic Mlme Rate.
3255                 //
3256                 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word =
3257                     pAd->CommonCfg.MlmeTransmit.word;
3258                 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3259                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3260                             OfdmRateToRxwiMCS[RATE_24];
3261                 else
3262                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3263                             RATE_1;
3264                 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3265         }
3266
3267         DBGPRINT(RT_DEBUG_TRACE,
3268                  (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3269                   RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
3270                   RateIdToMbps[pAd->CommonCfg.MaxTxRate],
3271                   RateIdToMbps[pAd->CommonCfg.MinTxRate],
3272                   /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3273                   *auto_rate_cur_p));
3274         DBGPRINT(RT_DEBUG_TRACE,
3275                  (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3276                   RateIdToMbps[pAd->CommonCfg.TxRate],
3277                   RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3278         DBGPRINT(RT_DEBUG_TRACE,
3279                  ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3280                   pAd->CommonCfg.MlmeTransmit.word,
3281                   pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
3282                   pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
3283                   pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word));
3284 }
3285
3286 /*
3287         ==========================================================================
3288         Description:
3289                 This function update HT Rate setting.
3290                 Input Wcid value is valid for 2 case :
3291                 1. it's used for Station in infra mode that copy AP rate to Mactable.
3292                 2. OR Station   in adhoc mode to copy peer's HT rate to Mactable.
3293
3294  IRQL = DISPATCH_LEVEL
3295
3296         ==========================================================================
3297  */
3298 VOID MlmeUpdateHtTxRates(IN PRTMP_ADAPTER pAd, IN UCHAR apidx)
3299 {
3300         UCHAR StbcMcs;          //j, StbcMcs, bitmask;
3301         CHAR i;                 // 3*3
3302         RT_HT_CAPABILITY *pRtHtCap = NULL;
3303         RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3304         ULONG BasicMCS;
3305         UCHAR j, bitmask;
3306         PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3307         PHTTRANSMIT_SETTING pHtPhy = NULL;
3308         PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3309         PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3310         BOOLEAN *auto_rate_cur_p;
3311
3312         DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n"));
3313
3314         auto_rate_cur_p = NULL;
3315
3316         {
3317                 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3318                 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3319                 pHtPhy = &pAd->StaCfg.HTPhyMode;
3320                 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3321                 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3322
3323                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3324         }
3325
3326         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
3327                 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3328                         return;
3329
3330                 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3331                 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3332                 StbcMcs = (UCHAR) pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3333                 BasicMCS =
3334                     pAd->MlmeAux.AddHtInfo.MCSSet[0] +
3335                     (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3336                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3337                     && (pAd->Antenna.field.TxPath == 2))
3338                         pMaxHtPhy->field.STBC = STBC_USE;
3339                 else
3340                         pMaxHtPhy->field.STBC = STBC_NONE;
3341         } else {
3342                 if (pDesireHtPhy->bHtEnable == FALSE)
3343                         return;
3344
3345                 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3346                 StbcMcs = (UCHAR) pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3347                 BasicMCS =
3348                     pAd->CommonCfg.AddHTInfo.MCSSet[0] +
3349                     (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3350                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3351                     && (pAd->Antenna.field.TxPath == 2))
3352                         pMaxHtPhy->field.STBC = STBC_USE;
3353                 else
3354                         pMaxHtPhy->field.STBC = STBC_NONE;
3355         }
3356
3357         // Decide MAX ht rate.
3358         if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3359                 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3360         else
3361                 pMaxHtPhy->field.MODE = MODE_HTMIX;
3362
3363         if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth)
3364             && (pRtHtCap->ChannelWidth))
3365                 pMaxHtPhy->field.BW = BW_40;
3366         else
3367                 pMaxHtPhy->field.BW = BW_20;
3368
3369         if (pMaxHtPhy->field.BW == BW_20)
3370                 pMaxHtPhy->field.ShortGI =
3371                     (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->
3372                      ShortGIfor20);
3373         else
3374                 pMaxHtPhy->field.ShortGI =
3375                     (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->
3376                      ShortGIfor40);
3377
3378         if (pDesireHtPhy->MCSSet[4] != 0) {
3379                 pMaxHtPhy->field.MCS = 32;
3380         }
3381
3382         for (i = 23; i >= 0; i--)       // 3*3
3383         {
3384                 j = i / 8;
3385                 bitmask = (1 << (i - (j * 8)));
3386
3387                 if ((pActiveHtPhy->MCSSet[j] & bitmask)
3388                     && (pDesireHtPhy->MCSSet[j] & bitmask)) {
3389                         pMaxHtPhy->field.MCS = i;
3390                         break;
3391                 }
3392
3393                 if (i == 0)
3394                         break;
3395         }
3396
3397         // Copy MIN ht rate.  rt2860???
3398         pMinHtPhy->field.BW = BW_20;
3399         pMinHtPhy->field.MCS = 0;
3400         pMinHtPhy->field.STBC = 0;
3401         pMinHtPhy->field.ShortGI = 0;
3402         //If STA assigns fixed rate. update to fixed here.
3403         if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) {
3404                 if (pDesireHtPhy->MCSSet[4] != 0) {
3405                         pMaxHtPhy->field.MCS = 32;
3406                         pMinHtPhy->field.MCS = 32;
3407                         DBGPRINT(RT_DEBUG_TRACE,
3408                                  ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3409                                   pMinHtPhy->field.MCS));
3410                 }
3411
3412                 for (i = 23; (CHAR) i >= 0; i--)        // 3*3
3413                 {
3414                         j = i / 8;
3415                         bitmask = (1 << (i - (j * 8)));
3416                         if ((pDesireHtPhy->MCSSet[j] & bitmask)
3417                             && (pActiveHtPhy->MCSSet[j] & bitmask)) {
3418                                 pMaxHtPhy->field.MCS = i;
3419                                 pMinHtPhy->field.MCS = i;
3420                                 break;
3421                         }
3422                         if (i == 0)
3423                                 break;
3424                 }
3425         }
3426
3427         // Decide ht rate
3428         pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3429         pHtPhy->field.BW = pMaxHtPhy->field.BW;
3430         pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3431         pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3432         pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3433
3434         // use default now. rt2860
3435         if (pDesireHtPhy->MCSSet[0] != 0xff)
3436                 *auto_rate_cur_p = FALSE;
3437         else
3438                 *auto_rate_cur_p = TRUE;
3439
3440         DBGPRINT(RT_DEBUG_TRACE,
3441                  (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n",
3442                   pAd->CommonCfg.DesiredHtPhy.AmsduSize));
3443         DBGPRINT(RT_DEBUG_TRACE,
3444                  ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n",
3445                   pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW,
3446                   pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3447         DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n"));
3448 }
3449
3450 VOID BATableInit(IN PRTMP_ADAPTER pAd, IN BA_TABLE * Tab)
3451 {
3452         int i;
3453
3454         Tab->numAsOriginator = 0;
3455         Tab->numAsRecipient = 0;
3456         Tab->numDoneOriginator = 0;
3457         NdisAllocateSpinLock(&pAd->BATabLock);
3458         for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
3459                 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3460                 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3461         }
3462         for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
3463                 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3464         }
3465 }
3466
3467 // IRQL = DISPATCH_LEVEL
3468 VOID MlmeRadioOff(IN PRTMP_ADAPTER pAd)
3469 {
3470         RTMP_MLME_RADIO_OFF(pAd);
3471 }
3472
3473 // IRQL = DISPATCH_LEVEL
3474 VOID MlmeRadioOn(IN PRTMP_ADAPTER pAd)
3475 {
3476         RTMP_MLME_RADIO_ON(pAd);
3477 }
3478
3479 // ===========================================================================================
3480 // bss_table.c
3481 // ===========================================================================================
3482
3483 /*! \brief initialize BSS table
3484  *      \param p_tab pointer to the table
3485  *      \return none
3486  *      \pre
3487  *      \post
3488
3489  IRQL = PASSIVE_LEVEL
3490  IRQL = DISPATCH_LEVEL
3491
3492  */
3493 VOID BssTableInit(IN BSS_TABLE * Tab)
3494 {
3495         int i;
3496
3497         Tab->BssNr = 0;
3498         Tab->BssOverlapNr = 0;
3499         for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) {
3500                 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3501                 Tab->BssEntry[i].Rssi = -127;   // initial the rssi as a minimum value
3502         }
3503 }
3504
3505 /*! \brief search the BSS table by SSID
3506  *      \param p_tab pointer to the bss table
3507  *      \param ssid SSID string
3508  *      \return index of the table, BSS_NOT_FOUND if not in the table
3509  *      \pre
3510  *      \post
3511  *      \note search by sequential search
3512
3513  IRQL = DISPATCH_LEVEL
3514
3515  */
3516 ULONG BssTableSearch(IN BSS_TABLE * Tab, IN PUCHAR pBssid, IN UCHAR Channel)
3517 {
3518         UCHAR i;
3519
3520         for (i = 0; i < Tab->BssNr; i++) {
3521                 //
3522                 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3523                 // We should distinguish this case.
3524                 //
3525                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3526                      ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3527                     MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) {
3528                         return i;
3529                 }
3530         }
3531         return (ULONG) BSS_NOT_FOUND;
3532 }
3533
3534 ULONG BssSsidTableSearch(IN BSS_TABLE * Tab,
3535                          IN PUCHAR pBssid,
3536                          IN PUCHAR pSsid, IN UCHAR SsidLen, IN UCHAR Channel)
3537 {
3538         UCHAR i;
3539
3540         for (i = 0; i < Tab->BssNr; i++) {
3541                 //
3542                 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3543                 // We should distinguish this case.
3544                 //
3545                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3546                      ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3547                     MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3548                     SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3549                                Tab->BssEntry[i].SsidLen)) {
3550                         return i;
3551                 }
3552         }
3553         return (ULONG) BSS_NOT_FOUND;
3554 }
3555
3556 ULONG BssTableSearchWithSSID(IN BSS_TABLE * Tab,
3557                              IN PUCHAR Bssid,
3558                              IN PUCHAR pSsid,
3559                              IN UCHAR SsidLen, IN UCHAR Channel)
3560 {
3561         UCHAR i;
3562
3563         for (i = 0; i < Tab->BssNr; i++) {
3564                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3565                      ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3566                     MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3567                     (SSID_EQUAL
3568                      (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3569                       Tab->BssEntry[i].SsidLen)
3570                      || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen))
3571                      ||
3572                      (NdisEqualMemory
3573                       (Tab->BssEntry[i].Ssid, ZeroSsid,
3574                        Tab->BssEntry[i].SsidLen)))) {
3575                         return i;
3576                 }
3577         }
3578         return (ULONG) BSS_NOT_FOUND;
3579 }
3580
3581 ULONG BssSsidTableSearchBySSID(IN BSS_TABLE * Tab,
3582                                IN PUCHAR pSsid, IN UCHAR SsidLen)
3583 {
3584         UCHAR i;
3585
3586         for (i = 0; i < Tab->BssNr; i++) {
3587                 if (SSID_EQUAL
3588                     (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3589                      Tab->BssEntry[i].SsidLen)) {
3590                         return i;
3591                 }
3592         }
3593         return (ULONG) BSS_NOT_FOUND;
3594 }
3595
3596 // IRQL = DISPATCH_LEVEL
3597 VOID BssTableDeleteEntry(IN OUT BSS_TABLE * Tab,
3598                          IN PUCHAR pBssid, IN UCHAR Channel)
3599 {
3600         UCHAR i, j;
3601
3602         for (i = 0; i < Tab->BssNr; i++) {
3603                 if ((Tab->BssEntry[i].Channel == Channel) &&
3604                     (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) {
3605                         for (j = i; j < Tab->BssNr - 1; j++) {
3606                                 NdisMoveMemory(&(Tab->BssEntry[j]),
3607                                                &(Tab->BssEntry[j + 1]),
3608                                                sizeof(BSS_ENTRY));
3609                         }
3610                         NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]),
3611                                        sizeof(BSS_ENTRY));
3612                         Tab->BssNr -= 1;
3613                         return;
3614                 }
3615         }
3616 }
3617
3618 /*
3619         ========================================================================
3620         Routine Description:
3621                 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3622
3623         Arguments:
3624         // IRQL = DISPATCH_LEVEL
3625         ========================================================================
3626 */
3627 VOID BATableDeleteORIEntry(IN OUT PRTMP_ADAPTER pAd,
3628                            IN BA_ORI_ENTRY * pBAORIEntry)
3629 {
3630
3631         if (pBAORIEntry->ORI_BA_Status != Originator_NONE) {
3632                 NdisAcquireSpinLock(&pAd->BATabLock);
3633                 if (pBAORIEntry->ORI_BA_Status == Originator_Done) {
3634                         pAd->BATable.numAsOriginator -= 1;
3635                         DBGPRINT(RT_DEBUG_TRACE,
3636                                  ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3637                                   pAd->BATable.numAsRecipient));
3638                         // Erase Bitmap flag.
3639                 }
3640                 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID)));      // If STA mode,  erase flag here
3641                 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;    // If STA mode,  erase flag here
3642                 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3643                 pBAORIEntry->Token = 1;
3644                 // Not clear Sequence here.
3645                 NdisReleaseSpinLock(&pAd->BATabLock);
3646         }
3647 }
3648
3649 /*! \brief
3650  *      \param
3651  *      \return
3652  *      \pre
3653  *      \post
3654
3655  IRQL = DISPATCH_LEVEL
3656
3657  */
3658 VOID BssEntrySet(IN PRTMP_ADAPTER pAd, OUT BSS_ENTRY * pBss, IN PUCHAR pBssid, IN CHAR Ssid[], IN UCHAR SsidLen, IN UCHAR BssType, IN USHORT BeaconPeriod, IN PCF_PARM pCfParm, IN USHORT AtimWin, IN USHORT CapabilityInfo, IN UCHAR SupRate[], IN UCHAR SupRateLen, IN UCHAR ExtRate[], IN UCHAR ExtRateLen, IN HT_CAPABILITY_IE * pHtCapability, IN ADD_HT_INFO_IE * pAddHtInfo,     // AP might use this additional ht info IE
3659                  IN UCHAR HtCapabilityLen,
3660                  IN UCHAR AddHtInfoLen,
3661                  IN UCHAR NewExtChanOffset,
3662                  IN UCHAR Channel,
3663                  IN CHAR Rssi,
3664                  IN LARGE_INTEGER TimeStamp,
3665                  IN UCHAR CkipFlag,
3666                  IN PEDCA_PARM pEdcaParm,
3667                  IN PQOS_CAPABILITY_PARM pQosCapability,
3668                  IN PQBSS_LOAD_PARM pQbssLoad,
3669                  IN USHORT LengthVIE, IN PNDIS_802_11_VARIABLE_IEs pVIE)
3670 {
3671         COPY_MAC_ADDR(pBss->Bssid, pBssid);
3672         // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3673         pBss->Hidden = 1;
3674         if (SsidLen > 0) {
3675                 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3676                 // Or send beacon /probe response with SSID len matching real SSID length,
3677                 // but SSID is all zero. such as "00-00-00-00" with length 4.
3678                 // We have to prevent this case overwrite correct table
3679                 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) {
3680                         NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3681                         NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3682                         pBss->SsidLen = SsidLen;
3683                         pBss->Hidden = 0;
3684                 }
3685         } else
3686                 pBss->SsidLen = 0;
3687         pBss->BssType = BssType;
3688         pBss->BeaconPeriod = BeaconPeriod;
3689         if (BssType == BSS_INFRA) {
3690                 if (pCfParm->bValid) {
3691                         pBss->CfpCount = pCfParm->CfpCount;
3692                         pBss->CfpPeriod = pCfParm->CfpPeriod;
3693                         pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3694                         pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3695                 }
3696         } else {
3697                 pBss->AtimWin = AtimWin;
3698         }
3699
3700         pBss->CapabilityInfo = CapabilityInfo;
3701         // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3702         // Combine with AuthMode, they will decide the connection methods.
3703         pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3704         ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3705         if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3706                 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3707         else
3708                 NdisMoveMemory(pBss->SupRate, SupRate,
3709                                MAX_LEN_OF_SUPPORTED_RATES);
3710         pBss->SupRateLen = SupRateLen;
3711         ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3712         NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3713         pBss->NewExtChanOffset = NewExtChanOffset;
3714         pBss->ExtRateLen = ExtRateLen;
3715         pBss->Channel = Channel;
3716         pBss->CentralChannel = Channel;
3717         pBss->Rssi = Rssi;
3718         // Update CkipFlag. if not exists, the value is 0x0
3719         pBss->CkipFlag = CkipFlag;
3720
3721         // New for microsoft Fixed IEs
3722         NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3723         pBss->FixIEs.BeaconInterval = BeaconPeriod;
3724         pBss->FixIEs.Capabilities = CapabilityInfo;
3725
3726         // New for microsoft Variable IEs
3727         if (LengthVIE != 0) {
3728                 pBss->VarIELen = LengthVIE;
3729                 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3730         } else {
3731                 pBss->VarIELen = 0;
3732         }
3733
3734         pBss->AddHtInfoLen = 0;
3735         pBss->HtCapabilityLen = 0;
3736         if (HtCapabilityLen > 0) {
3737                 pBss->HtCapabilityLen = HtCapabilityLen;
3738                 NdisMoveMemory(&pBss->HtCapability, pHtCapability,
3739                                HtCapabilityLen);
3740                 if (AddHtInfoLen > 0) {
3741                         pBss->AddHtInfoLen = AddHtInfoLen;
3742                         NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo,
3743                                        AddHtInfoLen);
3744
3745                         if ((pAddHtInfo->ControlChan > 2)
3746                             && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
3747                                 EXTCHA_BELOW)
3748                             && (pHtCapability->HtCapInfo.ChannelWidth ==
3749                                 BW_40)) {
3750                                 pBss->CentralChannel =
3751                                     pAddHtInfo->ControlChan - 2;
3752                         } else
3753                             if ((pAddHtInfo->AddHtInfo.ExtChanOffset ==
3754                                  EXTCHA_ABOVE)
3755                                 && (pHtCapability->HtCapInfo.ChannelWidth ==
3756                                     BW_40)) {
3757                                 pBss->CentralChannel =
3758                                     pAddHtInfo->ControlChan + 2;
3759                         }
3760                 }
3761         }
3762
3763         BssCipherParse(pBss);
3764
3765         // new for QOS
3766         if (pEdcaParm)
3767                 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3768         else
3769                 pBss->EdcaParm.bValid = FALSE;
3770         if (pQosCapability)
3771                 NdisMoveMemory(&pBss->QosCapability, pQosCapability,
3772                                sizeof(QOS_CAPABILITY_PARM));
3773         else
3774                 pBss->QosCapability.bValid = FALSE;
3775         if (pQbssLoad)
3776                 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad,
3777                                sizeof(QBSS_LOAD_PARM));
3778         else
3779                 pBss->QbssLoad.bValid = FALSE;
3780
3781         {
3782                 PEID_STRUCT pEid;
3783                 USHORT Length = 0;
3784
3785                 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3786                 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3787                 pEid = (PEID_STRUCT) pVIE;
3788                 while ((Length + 2 + (USHORT) pEid->Len) <= LengthVIE) {
3789                         switch (pEid->Eid) {
3790                         case IE_WPA:
3791                                 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) {
3792                                         if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3793                                                 pBss->WpaIE.IELen = 0;
3794                                                 break;
3795                                         }
3796                                         pBss->WpaIE.IELen = pEid->Len + 2;
3797                                         NdisMoveMemory(pBss->WpaIE.IE, pEid,
3798                                                        pBss->WpaIE.IELen);
3799                                 }
3800                                 break;
3801                         case IE_RSN:
3802                                 if (NdisEqualMemory
3803                                     (pEid->Octet + 2, RSN_OUI, 3)) {
3804                                         if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3805                                                 pBss->RsnIE.IELen = 0;
3806                                                 break;
3807                                         }
3808                                         pBss->RsnIE.IELen = pEid->Len + 2;
3809                                         NdisMoveMemory(pBss->RsnIE.IE, pEid,
3810                                                        pBss->RsnIE.IELen);
3811                                 }
3812                                 break;
3813                         }
3814                         Length = Length + 2 + (USHORT) pEid->Len;       // Eid[1] + Len[1]+ content[Len]
3815                         pEid = (PEID_STRUCT) ((UCHAR *) pEid + 2 + pEid->Len);
3816                 }
3817         }
3818 }
3819
3820 /*!
3821  *      \brief insert an entry into the bss table
3822  *      \param p_tab The BSS table
3823  *      \param Bssid BSSID
3824  *      \param ssid SSID
3825  *      \param ssid_len Length of SSID
3826  *      \param bss_type
3827  *      \param beacon_period
3828  *      \param timestamp
3829  *      \param p_cf
3830  *      \param atim_win
3831  *      \param cap
3832  *      \param rates
3833  *      \param rates_len
3834  *      \param channel_idx
3835  *      \return none
3836  *      \pre
3837  *      \post
3838  *      \note If SSID is identical, the old entry will be replaced by the new one
3839
3840  IRQL = DISPATCH_LEVEL
3841
3842  */
3843 ULONG BssTableSetEntry(IN PRTMP_ADAPTER pAd, OUT BSS_TABLE * Tab, IN PUCHAR pBssid, IN CHAR Ssid[], IN UCHAR SsidLen, IN UCHAR BssType, IN USHORT BeaconPeriod, IN CF_PARM * CfParm, IN USHORT AtimWin, IN USHORT CapabilityInfo, IN UCHAR SupRate[], IN UCHAR SupRateLen, IN UCHAR ExtRate[], IN UCHAR ExtRateLen, IN HT_CAPABILITY_IE * pHtCapability, IN ADD_HT_INFO_IE * pAddHtInfo,        // AP might use this additional ht info IE
3844                        IN UCHAR HtCapabilityLen,
3845                        IN UCHAR AddHtInfoLen,
3846                        IN UCHAR NewExtChanOffset,
3847                        IN UCHAR ChannelNo,
3848                        IN CHAR Rssi,
3849                        IN LARGE_INTEGER TimeStamp,
3850                        IN UCHAR CkipFlag,
3851                        IN PEDCA_PARM pEdcaParm,
3852                        IN PQOS_CAPABILITY_PARM pQosCapability,
3853                        IN PQBSS_LOAD_PARM pQbssLoad,
3854                        IN USHORT LengthVIE, IN PNDIS_802_11_VARIABLE_IEs pVIE)
3855 {
3856         ULONG Idx;
3857
3858         Idx =
3859             BssTableSearchWithSSID(Tab, pBssid, (UCHAR *) Ssid, SsidLen,
3860                                    ChannelNo);
3861         if (Idx == BSS_NOT_FOUND) {
3862                 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) {
3863                         //
3864                         // It may happen when BSS Table was full.
3865                         // The desired AP will not be added into BSS Table
3866                         // In this case, if we found the desired AP then overwrite BSS Table.
3867                         //
3868                         if (!OPSTATUS_TEST_FLAG
3869                             (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
3870                                 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid)
3871                                     || SSID_EQUAL(pAd->MlmeAux.Ssid,
3872                                                   pAd->MlmeAux.SsidLen, Ssid,
3873                                                   SsidLen)) {
3874                                         Idx = Tab->BssOverlapNr;
3875                                         BssEntrySet(pAd, &Tab->BssEntry[Idx],
3876                                                     pBssid, Ssid, SsidLen,
3877                                                     BssType, BeaconPeriod,
3878                                                     CfParm, AtimWin,
3879                                                     CapabilityInfo, SupRate,
3880                                                     SupRateLen, ExtRate,
3881                                                     ExtRateLen, pHtCapability,
3882                                                     pAddHtInfo, HtCapabilityLen,
3883                                                     AddHtInfoLen,
3884                                                     NewExtChanOffset, ChannelNo,
3885                                                     Rssi, TimeStamp, CkipFlag,
3886                                                     pEdcaParm, pQosCapability,
3887                                                     pQbssLoad, LengthVIE, pVIE);
3888                                         Tab->BssOverlapNr =
3889                                             (Tab->BssOverlapNr++) %
3890                                             MAX_LEN_OF_BSS_TABLE;
3891                                 }
3892                                 return Idx;
3893                         } else {
3894                                 return BSS_NOT_FOUND;
3895                         }
3896                 }
3897                 Idx = Tab->BssNr;
3898                 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen,
3899                             BssType, BeaconPeriod, CfParm, AtimWin,
3900                             CapabilityInfo, SupRate, SupRateLen, ExtRate,
3901                             ExtRateLen, pHtCapability, pAddHtInfo,
3902                             HtCapabilityLen, AddHtInfoLen, NewExtChanOffset,
3903                             ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm,
3904                             pQosCapability, pQbssLoad, LengthVIE, pVIE);
3905                 Tab->BssNr++;
3906         } else {
3907                 /* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
3908                 if ((SSID_EQUAL
3909                      (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid,
3910                       Tab->BssEntry[Idx].SsidLen))
3911                     ||
3912                     (NdisEqualMemory
3913                      (Tab->BssEntry[Idx].Ssid, ZeroSsid,
3914                       Tab->BssEntry[Idx].SsidLen))) {
3915                         BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid,
3916                                     SsidLen, BssType, BeaconPeriod, CfParm,
3917                                     AtimWin, CapabilityInfo, SupRate,
3918                                     SupRateLen, ExtRate, ExtRateLen,
3919                                     pHtCapability, pAddHtInfo, HtCapabilityLen,
3920                                     AddHtInfoLen, NewExtChanOffset, ChannelNo,
3921                                     Rssi, TimeStamp, CkipFlag, pEdcaParm,
3922                                     pQosCapability, pQbssLoad, LengthVIE, pVIE);
3923                 }
3924         }
3925
3926         return Idx;
3927 }
3928
3929 // IRQL = DISPATCH_LEVEL
3930 VOID BssTableSsidSort(IN PRTMP_ADAPTER pAd,
3931                       OUT BSS_TABLE * OutTab, IN CHAR Ssid[], IN UCHAR SsidLen)
3932 {
3933         INT i;
3934         BssTableInit(OutTab);
3935
3936         for (i = 0; i < pAd->ScanTab.BssNr; i++) {
3937                 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3938                 BOOLEAN bIsHiddenApIncluded = FALSE;
3939
3940                 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3941                      (pAd->MlmeAux.Channel > 14) &&
3942                      RadarChannelCheck(pAd, pInBss->Channel))
3943                     ) {
3944                         if (pInBss->Hidden)
3945                                 bIsHiddenApIncluded = TRUE;
3946                 }
3947
3948                 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3949                     (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen)
3950                      || bIsHiddenApIncluded)) {
3951                         BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3952
3953                         // 2.4G/5G N only mode
3954                         if ((pInBss->HtCapabilityLen == 0) &&
3955                             ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
3956                              || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
3957                                 DBGPRINT(RT_DEBUG_TRACE,
3958                                          ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3959                                 continue;
3960                         }
3961                         // New for WPA2
3962                         // Check the Authmode first
3963                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
3964                                 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3965                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
3966                                     && (pAd->StaCfg.AuthMode !=
3967                                         pInBss->AuthModeAux))
3968                                         // None matched
3969                                         continue;
3970
3971                                 // Check cipher suite, AP must have more secured cipher than station setting
3972                                 if ((pAd->StaCfg.AuthMode ==
3973                                      Ndis802_11AuthModeWPA)
3974                                     || (pAd->StaCfg.AuthMode ==
3975                                         Ndis802_11AuthModeWPAPSK)) {
3976                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
3977                                         if (pInBss->WPA.bMixMode == FALSE)
3978                                                 if (pAd->StaCfg.WepStatus !=
3979                                                     pInBss->WPA.GroupCipher)
3980                                                         continue;
3981
3982                                         // check group cipher
3983                                         if ((pAd->StaCfg.WepStatus <
3984                                              pInBss->WPA.GroupCipher)
3985                                             && (pInBss->WPA.GroupCipher !=
3986                                                 Ndis802_11GroupWEP40Enabled)
3987                                             && (pInBss->WPA.GroupCipher !=
3988                                                 Ndis802_11GroupWEP104Enabled))
3989                                                 continue;
3990
3991                                         // check pairwise cipher, skip if none matched
3992                                         // If profile set to AES, let it pass without question.
3993                                         // If profile set to TKIP, we must find one mateched
3994                                         if ((pAd->StaCfg.WepStatus ==
3995                                              Ndis802_11Encryption2Enabled)
3996                                             && (pAd->StaCfg.WepStatus !=
3997                                                 pInBss->WPA.PairCipher)
3998                                             && (pAd->StaCfg.WepStatus !=
3999                                                 pInBss->WPA.PairCipherAux))
4000                                                 continue;
4001                                 } else
4002                                     if ((pAd->StaCfg.AuthMode ==
4003                                          Ndis802_11AuthModeWPA2)
4004                                         || (pAd->StaCfg.AuthMode ==
4005                                             Ndis802_11AuthModeWPA2PSK)) {
4006                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
4007                                         if (pInBss->WPA2.bMixMode == FALSE)
4008                                                 if (pAd->StaCfg.WepStatus !=
4009                                                     pInBss->WPA2.GroupCipher)
4010                                                         continue;
4011
4012                                         // check group cipher
4013                                         if ((pAd->StaCfg.WepStatus <
4014                                              pInBss->WPA.GroupCipher)
4015                                             && (pInBss->WPA2.GroupCipher !=
4016                                                 Ndis802_11GroupWEP40Enabled)
4017                                             && (pInBss->WPA2.GroupCipher !=
4018                                                 Ndis802_11GroupWEP104Enabled))
4019                                                 continue;
4020
4021                                         // check pairwise cipher, skip if none matched
4022                                         // If profile set to AES, let it pass without question.
4023                                         // If profile set to TKIP, we must find one mateched
4024                                         if ((pAd->StaCfg.WepStatus ==
4025                                              Ndis802_11Encryption2Enabled)
4026                                             && (pAd->StaCfg.WepStatus !=
4027                                                 pInBss->WPA2.PairCipher)
4028                                             && (pAd->StaCfg.WepStatus !=
4029                                                 pInBss->WPA2.PairCipherAux))
4030                                                 continue;
4031                                 }
4032                         }
4033                         // Bss Type matched, SSID matched.
4034                         // We will check wepstatus for qualification Bss
4035                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) {
4036                                 DBGPRINT(RT_DEBUG_TRACE,
4037                                          ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4038                                           pAd->StaCfg.WepStatus,
4039                                           pInBss->WepStatus));
4040                                 //
4041                                 // For the SESv2 case, we will not qualify WepStatus.
4042                                 //
4043                                 if (!pInBss->bSES)
4044                                         continue;
4045                         }
4046                         // Since the AP is using hidden SSID, and we are trying to connect to ANY
4047                         // It definitely will fail. So, skip it.
4048                         // CCX also require not even try to connect it!!
4049                         if (SsidLen == 0)
4050                                 continue;
4051
4052                         // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4053                         // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4054                         if ((pInBss->CentralChannel != pInBss->Channel) &&
4055                             (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4056                              BW_40)) {
4057                                 if (RTMPCheckChannel
4058                                     (pAd, pInBss->CentralChannel,
4059                                      pInBss->Channel) == FALSE) {
4060                                         pAd->CommonCfg.RegTransmitSetting.field.
4061                                             BW = BW_20;
4062                                         SetCommonHT(pAd);
4063                                         pAd->CommonCfg.RegTransmitSetting.field.
4064                                             BW = BW_40;
4065                                 } else {
4066                                         if (pAd->CommonCfg.DesiredHtPhy.
4067                                             ChannelWidth == BAND_WIDTH_20) {
4068                                                 SetCommonHT(pAd);
4069                                         }
4070                                 }
4071                         }
4072                         // copy matching BSS from InTab to OutTab
4073                         NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4074
4075                         OutTab->BssNr++;
4076                 } else if ((pInBss->BssType == pAd->StaCfg.BssType)
4077                            && (SsidLen == 0)) {
4078                         BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4079
4080                         // 2.4G/5G N only mode
4081                         if ((pInBss->HtCapabilityLen == 0) &&
4082                             ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
4083                              || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
4084                                 DBGPRINT(RT_DEBUG_TRACE,
4085                                          ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4086                                 continue;
4087                         }
4088                         // New for WPA2
4089                         // Check the Authmode first
4090                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
4091                                 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4092                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
4093                                     && (pAd->StaCfg.AuthMode !=
4094                                         pInBss->AuthModeAux))
4095                                         // None matched
4096                                         continue;
4097
4098                                 // Check cipher suite, AP must have more secured cipher than station setting
4099                                 if ((pAd->StaCfg.AuthMode ==
4100                                      Ndis802_11AuthModeWPA)
4101                                     || (pAd->StaCfg.AuthMode ==
4102                                         Ndis802_11AuthModeWPAPSK)) {
4103                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
4104                                         if (pInBss->WPA.bMixMode == FALSE)
4105                                                 if (pAd->StaCfg.WepStatus !=
4106                                                     pInBss->WPA.GroupCipher)
4107                                                         continue;
4108
4109                                         // check group cipher
4110                                         if (pAd->StaCfg.WepStatus <
4111                                             pInBss->WPA.GroupCipher)
4112                                                 continue;
4113
4114                                         // check pairwise cipher, skip if none matched
4115                                         // If profile set to AES, let it pass without question.
4116                                         // If profile set to TKIP, we must find one mateched
4117                                         if ((pAd->StaCfg.WepStatus ==
4118                                              Ndis802_11Encryption2Enabled)
4119                                             && (pAd->StaCfg.WepStatus !=
4120                                                 pInBss->WPA.PairCipher)
4121                                             && (pAd->StaCfg.WepStatus !=
4122                                                 pInBss->WPA.PairCipherAux))
4123                                                 continue;
4124                                 } else
4125                                     if ((pAd->StaCfg.AuthMode ==
4126                                          Ndis802_11AuthModeWPA2)
4127                                         || (pAd->StaCfg.AuthMode ==
4128                                             Ndis802_11AuthModeWPA2PSK)) {
4129                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
4130                                         if (pInBss->WPA2.bMixMode == FALSE)
4131                                                 if (pAd->StaCfg.WepStatus !=
4132                                                     pInBss->WPA2.GroupCipher)
4133                                                         continue;
4134
4135                                         // check group cipher
4136                                         if (pAd->StaCfg.WepStatus <
4137                                             pInBss->WPA2.GroupCipher)
4138                                                 continue;
4139
4140                                         // check pairwise cipher, skip if none matched
4141                                         // If profile set to AES, let it pass without question.
4142                                         // If profile set to TKIP, we must find one mateched
4143                                         if ((pAd->StaCfg.WepStatus ==
4144                                              Ndis802_11Encryption2Enabled)
4145                                             && (pAd->StaCfg.WepStatus !=
4146                                                 pInBss->WPA2.PairCipher)
4147                                             && (pAd->StaCfg.WepStatus !=
4148                                                 pInBss->WPA2.PairCipherAux))
4149                                                 continue;
4150                                 }
4151                         }
4152                         // Bss Type matched, SSID matched.
4153                         // We will check wepstatus for qualification Bss
4154                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4155                                 continue;
4156
4157                         // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4158                         // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4159                         if ((pInBss->CentralChannel != pInBss->Channel) &&
4160                             (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4161                              BW_40)) {
4162                                 if (RTMPCheckChannel
4163                                     (pAd, pInBss->CentralChannel,
4164                                      pInBss->Channel) == FALSE) {
4165                                         pAd->CommonCfg.RegTransmitSetting.field.
4166                                             BW = BW_20;
4167                                         SetCommonHT(pAd);
4168                                         pAd->CommonCfg.RegTransmitSetting.field.
4169                                             BW = BW_40;
4170                                 }
4171                         }
4172                         // copy matching BSS from InTab to OutTab
4173                         NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4174
4175                         OutTab->BssNr++;
4176                 }
4177
4178                 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4179                         break;
4180         }
4181
4182         BssTableSortByRssi(OutTab);
4183 }
4184
4185 // IRQL = DISPATCH_LEVEL
4186 VOID BssTableSortByRssi(IN OUT BSS_TABLE * OutTab)
4187 {
4188         INT i, j;
4189         BSS_ENTRY TmpBss;
4190
4191         for (i = 0; i < OutTab->BssNr - 1; i++) {
4192                 for (j = i + 1; j < OutTab->BssNr; j++) {
4193                         if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) {
4194                                 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j],
4195                                                sizeof(BSS_ENTRY));
4196                                 NdisMoveMemory(&OutTab->BssEntry[j],
4197                                                &OutTab->BssEntry[i],
4198                                                sizeof(BSS_ENTRY));
4199                                 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss,
4200                                                sizeof(BSS_ENTRY));
4201                         }
4202                 }
4203         }
4204 }
4205
4206 VOID BssCipherParse(IN OUT PBSS_ENTRY pBss)
4207 {
4208         PEID_STRUCT pEid;
4209         PUCHAR pTmp;
4210         PRSN_IE_HEADER_STRUCT pRsnHeader;
4211         PCIPHER_SUITE_STRUCT pCipher;
4212         PAKM_SUITE_STRUCT pAKM;
4213         USHORT Count;
4214         INT Length;
4215         NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4216
4217         //
4218         // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4219         //
4220         if (pBss->Privacy) {
4221                 pBss->WepStatus = Ndis802_11WEPEnabled;
4222         } else {
4223                 pBss->WepStatus = Ndis802_11WEPDisabled;
4224         }
4225         // Set default to disable & open authentication before parsing variable IE
4226         pBss->AuthMode = Ndis802_11AuthModeOpen;
4227         pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4228
4229         // Init WPA setting
4230         pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4231         pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4232         pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4233         pBss->WPA.RsnCapability = 0;
4234         pBss->WPA.bMixMode = FALSE;
4235
4236         // Init WPA2 setting
4237         pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4238         pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4239         pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4240         pBss->WPA2.RsnCapability = 0;
4241         pBss->WPA2.bMixMode = FALSE;
4242
4243         Length = (INT) pBss->VarIELen;
4244
4245         while (Length > 0) {
4246                 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4247                 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4248                 pEid = (PEID_STRUCT) pTmp;
4249                 switch (pEid->Eid) {
4250                 case IE_WPA:
4251                         if (NdisEqualMemory(pEid->Octet, SES_OUI, 3)
4252                             && (pEid->Len == 7)) {
4253                                 pBss->bSES = TRUE;
4254                                 break;
4255                         } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) !=
4256                                    1) {
4257                                 // if unsupported vendor specific IE
4258                                 break;
4259                         }
4260                         // Skip OUI, version, and multicast suite
4261                         // This part should be improved in the future when AP supported multiple cipher suite.
4262                         // For now, it's OK since almost all APs have fixed cipher suite supported.
4263                         // pTmp = (PUCHAR) pEid->Octet;
4264                         pTmp += 11;
4265
4266                         // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4267                         //      Value      Meaning
4268                         //      0                       None
4269                         //      1                       WEP-40
4270                         //      2                       Tkip
4271                         //      3                       WRAP
4272                         //      4                       AES
4273                         //      5                       WEP-104
4274                         // Parse group cipher
4275                         switch (*pTmp) {
4276                         case 1:
4277                                 pBss->WPA.GroupCipher =
4278                                     Ndis802_11GroupWEP40Enabled;
4279                                 break;
4280                         case 5:
4281                                 pBss->WPA.GroupCipher =
4282                                     Ndis802_11GroupWEP104Enabled;
4283                                 break;
4284                         case 2:
4285                                 pBss->WPA.GroupCipher =
4286                                     Ndis802_11Encryption2Enabled;
4287                                 break;
4288                         case 4:
4289                                 pBss->WPA.GroupCipher =
4290                                     Ndis802_11Encryption3Enabled;
4291                                 break;
4292                         default:
4293                                 break;
4294                         }
4295                         // number of unicast suite
4296                         pTmp += 1;
4297
4298                         // skip all unicast cipher suites
4299                         //Count = *(PUSHORT) pTmp;
4300                         Count = (pTmp[1] << 8) + pTmp[0];
4301                         pTmp += sizeof(USHORT);
4302
4303                         // Parsing all unicast cipher suite
4304                         while (Count > 0) {
4305                                 // Skip OUI
4306                                 pTmp += 3;
4307                                 TmpCipher = Ndis802_11WEPDisabled;
4308                                 switch (*pTmp) {
4309                                 case 1:
4310                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4311                                         TmpCipher =
4312                                             Ndis802_11Encryption1Enabled;
4313                                         break;
4314                                 case 2:
4315                                         TmpCipher =
4316                                             Ndis802_11Encryption2Enabled;
4317                                         break;
4318                                 case 4:
4319                                         TmpCipher =
4320                                             Ndis802_11Encryption3Enabled;
4321                                         break;
4322                                 default:
4323                                         break;
4324                                 }
4325                                 if (TmpCipher > pBss->WPA.PairCipher) {
4326                                         // Move the lower cipher suite to PairCipherAux
4327                                         pBss->WPA.PairCipherAux =
4328                                             pBss->WPA.PairCipher;
4329                                         pBss->WPA.PairCipher = TmpCipher;
4330                                 } else {
4331                                         pBss->WPA.PairCipherAux = TmpCipher;
4332                                 }
4333                                 pTmp++;
4334                                 Count--;
4335                         }
4336
4337                         // 4. get AKM suite counts
4338                         //Count = *(PUSHORT) pTmp;
4339                         Count = (pTmp[1] << 8) + pTmp[0];
4340                         pTmp += sizeof(USHORT);
4341                         pTmp += 3;
4342
4343                         switch (*pTmp) {
4344                         case 1:
4345                                 // Set AP support WPA-enterprise mode
4346                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4347                                         pBss->AuthMode = Ndis802_11AuthModeWPA;
4348                                 else
4349                                         pBss->AuthModeAux =
4350                                             Ndis802_11AuthModeWPA;
4351                                 break;
4352                         case 2:
4353                                 // Set AP support WPA-PSK mode
4354                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4355                                         pBss->AuthMode =
4356                                             Ndis802_11AuthModeWPAPSK;
4357                                 else
4358                                         pBss->AuthModeAux =
4359                                             Ndis802_11AuthModeWPAPSK;
4360                                 break;
4361                         default:
4362                                 break;
4363                         }
4364                         pTmp += 1;
4365
4366                         // Fixed for WPA-None
4367                         if (pBss->BssType == BSS_ADHOC) {
4368                                 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4369                                 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4370                                 pBss->WepStatus = pBss->WPA.GroupCipher;
4371                                 // Patched bugs for old driver
4372                                 if (pBss->WPA.PairCipherAux ==
4373                                     Ndis802_11WEPDisabled)
4374                                         pBss->WPA.PairCipherAux =
4375                                             pBss->WPA.GroupCipher;
4376                         } else
4377                                 pBss->WepStatus = pBss->WPA.PairCipher;
4378
4379                         // Check the Pair & Group, if different, turn on mixed mode flag
4380                         if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4381                                 pBss->WPA.bMixMode = TRUE;
4382
4383                         break;
4384
4385                 case IE_RSN:
4386                         pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4387
4388                         // 0. Version must be 1
4389                         if (le2cpu16(pRsnHeader->Version) != 1)
4390                                 break;
4391                         pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4392
4393                         // 1. Check group cipher
4394                         pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4395                         if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4396                                 break;
4397
4398                         // Parse group cipher
4399                         switch (pCipher->Type) {
4400                         case 1:
4401                                 pBss->WPA2.GroupCipher =
4402                                     Ndis802_11GroupWEP40Enabled;
4403                                 break;
4404                         case 5:
4405                                 pBss->WPA2.GroupCipher =
4406                                     Ndis802_11GroupWEP104Enabled;
4407                                 break;
4408                         case 2:
4409                                 pBss->WPA2.GroupCipher =
4410                                     Ndis802_11Encryption2Enabled;
4411                                 break;
4412                         case 4:
4413                                 pBss->WPA2.GroupCipher =
4414                                     Ndis802_11Encryption3Enabled;
4415                                 break;
4416                         default:
4417                                 break;
4418                         }
4419                         // set to correct offset for next parsing
4420                         pTmp += sizeof(CIPHER_SUITE_STRUCT);
4421
4422                         // 2. Get pairwise cipher counts
4423                         //Count = *(PUSHORT) pTmp;
4424                         Count = (pTmp[1] << 8) + pTmp[0];
4425                         pTmp += sizeof(USHORT);
4426
4427                         // 3. Get pairwise cipher
4428                         // Parsing all unicast cipher suite
4429                         while (Count > 0) {
4430                                 // Skip OUI
4431                                 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4432                                 TmpCipher = Ndis802_11WEPDisabled;
4433                                 switch (pCipher->Type) {
4434                                 case 1:
4435                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4436                                         TmpCipher =
4437                                             Ndis802_11Encryption1Enabled;
4438                                         break;
4439                                 case 2:
4440                                         TmpCipher =
4441                                             Ndis802_11Encryption2Enabled;
4442                                         break;
4443                                 case 4:
4444                                         TmpCipher =
4445                                             Ndis802_11Encryption3Enabled;
4446                                         break;
4447                                 default:
4448                                         break;
4449                                 }
4450                                 if (TmpCipher > pBss->WPA2.PairCipher) {
4451                                         // Move the lower cipher suite to PairCipherAux
4452                                         pBss->WPA2.PairCipherAux =
4453                                             pBss->WPA2.PairCipher;
4454                                         pBss->WPA2.PairCipher = TmpCipher;
4455                                 } else {
4456                                         pBss->WPA2.PairCipherAux = TmpCipher;
4457                                 }
4458                                 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4459                                 Count--;
4460                         }
4461
4462                         // 4. get AKM suite counts
4463                         //Count = *(PUSHORT) pTmp;
4464                         Count = (pTmp[1] << 8) + pTmp[0];
4465                         pTmp += sizeof(USHORT);
4466
4467                         // 5. Get AKM ciphers
4468                         // Parsing all AKM ciphers
4469                         while (Count > 0) {
4470                                 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4471                                 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4472                                         break;
4473
4474                                 switch (pAKM->Type) {
4475                                 case 1:
4476                                         // Set AP support WPA-enterprise mode
4477                                         if (pBss->AuthMode ==
4478                                             Ndis802_11AuthModeOpen)
4479                                                 pBss->AuthMode =
4480                                                     Ndis802_11AuthModeWPA2;
4481                                         else
4482                                                 pBss->AuthModeAux =
4483                                                     Ndis802_11AuthModeWPA2;
4484                                         break;
4485                                 case 2:
4486                                         // Set AP support WPA-PSK mode
4487                                         if (pBss->AuthMode ==
4488                                             Ndis802_11AuthModeOpen)
4489                                                 pBss->AuthMode =
4490                                                     Ndis802_11AuthModeWPA2PSK;
4491                                         else
4492                                                 pBss->AuthModeAux =
4493                                                     Ndis802_11AuthModeWPA2PSK;
4494                                         break;
4495                                 default:
4496                                         if (pBss->AuthMode ==
4497                                             Ndis802_11AuthModeOpen)
4498                                                 pBss->AuthMode =
4499                                                     Ndis802_11AuthModeMax;
4500                                         else
4501                                                 pBss->AuthModeAux =
4502                                                     Ndis802_11AuthModeMax;
4503                                         break;
4504                                 }
4505                                 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4506                                 Count--;
4507                         }
4508
4509                         // Fixed for WPA-None
4510                         if (pBss->BssType == BSS_ADHOC) {
4511                                 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4512                                 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4513                                 pBss->WPA.PairCipherAux =
4514                                     pBss->WPA2.PairCipherAux;
4515                                 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4516                                 pBss->WepStatus = pBss->WPA.GroupCipher;
4517                                 // Patched bugs for old driver
4518                                 if (pBss->WPA.PairCipherAux ==
4519                                     Ndis802_11WEPDisabled)
4520                                         pBss->WPA.PairCipherAux =
4521                                             pBss->WPA.GroupCipher;
4522                         }
4523                         pBss->WepStatus = pBss->WPA2.PairCipher;
4524
4525                         // 6. Get RSN capability
4526                         //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4527                         pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0];
4528                         pTmp += sizeof(USHORT);
4529
4530                         // Check the Pair & Group, if different, turn on mixed mode flag
4531                         if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4532                                 pBss->WPA2.bMixMode = TRUE;
4533
4534                         break;
4535                 default:
4536                         break;
4537                 }
4538                 Length -= (pEid->Len + 2);
4539         }
4540 }
4541
4542 // ===========================================================================================
4543 // mac_table.c
4544 // ===========================================================================================
4545
4546 /*! \brief generates a random mac address value for IBSS BSSID
4547  *      \param Addr the bssid location
4548  *      \return none
4549  *      \pre
4550  *      \post
4551  */
4552 VOID MacAddrRandomBssid(IN PRTMP_ADAPTER pAd, OUT PUCHAR pAddr)
4553 {
4554         INT i;
4555
4556         for (i = 0; i < MAC_ADDR_LEN; i++) {
4557                 pAddr[i] = RandomByte(pAd);
4558         }
4559
4560         pAddr[0] = (pAddr[0] & 0xfe) | 0x02;    // the first 2 bits must be 01xxxxxxxx
4561 }
4562
4563 /*! \brief init the management mac frame header
4564  *      \param p_hdr mac header
4565  *      \param subtype subtype of the frame
4566  *      \param p_ds destination address, don't care if it is a broadcast address
4567  *      \return none
4568  *      \pre the station has the following information in the pAd->StaCfg
4569  *       - bssid
4570  *       - station address
4571  *      \post
4572  *      \note this function initializes the following field
4573
4574         IRQL = PASSIVE_LEVEL
4575         IRQL = DISPATCH_LEVEL
4576
4577  */
4578 VOID MgtMacHeaderInit(IN PRTMP_ADAPTER pAd,
4579                       IN OUT PHEADER_802_11 pHdr80211,
4580                       IN UCHAR SubType,
4581                       IN UCHAR ToDs, IN PUCHAR pDA, IN PUCHAR pBssid)
4582 {
4583         NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4584
4585         pHdr80211->FC.Type = BTYPE_MGMT;
4586         pHdr80211->FC.SubType = SubType;
4587 //      if (SubType == SUBTYPE_ACK)     // sample, no use, it will conflict with ACTION frame sub type
4588 //              pHdr80211->FC.Type = BTYPE_CNTL;
4589         pHdr80211->FC.ToDs = ToDs;
4590         COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4591         COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4592         COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4593 }
4594
4595 // ===========================================================================================
4596 // mem_mgmt.c
4597 // ===========================================================================================
4598
4599 /*!***************************************************************************
4600  * This routine build an outgoing frame, and fill all information specified
4601  * in argument list to the frame body. The actual frame size is the summation
4602  * of all arguments.
4603  * input params:
4604  *              Buffer - pointer to a pre-allocated memory segment
4605  *              args - a list of <int arg_size, arg> pairs.
4606  *              NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4607  *                                                 function will FAIL!!!
4608  * return:
4609  *              Size of the buffer
4610  * usage:
4611  *              MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4612
4613  IRQL = PASSIVE_LEVEL
4614         IRQL = DISPATCH_LEVEL
4615
4616  ****************************************************************************/
4617 ULONG MakeOutgoingFrame(OUT UCHAR * Buffer, OUT ULONG * FrameLen, ...)
4618 {
4619         UCHAR *p;
4620         int leng;
4621         ULONG TotLeng;
4622         va_list Args;
4623
4624         // calculates the total length
4625         TotLeng = 0;
4626         va_start(Args, FrameLen);
4627         do {
4628                 leng = va_arg(Args, int);
4629                 if (leng == END_OF_ARGS) {
4630                         break;
4631                 }
4632                 p = va_arg(Args, PVOID);
4633                 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4634                 TotLeng = TotLeng + leng;
4635         } while (TRUE);
4636
4637         va_end(Args);           /* clean up */
4638         *FrameLen = TotLeng;
4639         return TotLeng;
4640 }
4641
4642 // ===========================================================================================
4643 // mlme_queue.c
4644 // ===========================================================================================
4645
4646 /*! \brief      Initialize The MLME Queue, used by MLME Functions
4647  *      \param  *Queue     The MLME Queue
4648  *      \return Always     Return NDIS_STATE_SUCCESS in this implementation
4649  *      \pre
4650  *      \post
4651  *      \note   Because this is done only once (at the init stage), no need to be locked
4652
4653  IRQL = PASSIVE_LEVEL
4654
4655  */
4656 NDIS_STATUS MlmeQueueInit(IN MLME_QUEUE * Queue)
4657 {
4658         INT i;
4659
4660         NdisAllocateSpinLock(&Queue->Lock);
4661
4662         Queue->Num = 0;
4663         Queue->Head = 0;
4664         Queue->Tail = 0;
4665
4666         for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) {
4667                 Queue->Entry[i].Occupied = FALSE;
4668                 Queue->Entry[i].MsgLen = 0;
4669                 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4670         }
4671
4672         return NDIS_STATUS_SUCCESS;
4673 }
4674
4675 /*! \brief       Enqueue a message for other threads, if they want to send messages to MLME thread
4676  *      \param  *Queue    The MLME Queue
4677  *      \param   Machine  The State Machine Id
4678  *      \param   MsgType  The Message Type
4679  *      \param   MsgLen   The Message length
4680  *      \param  *Msg      The message pointer
4681  *      \return  TRUE if enqueue is successful, FALSE if the queue is full
4682  *      \pre
4683  *      \post
4684  *      \note    The message has to be initialized
4685
4686         IRQL = PASSIVE_LEVEL
4687         IRQL = DISPATCH_LEVEL
4688
4689  */
4690 BOOLEAN MlmeEnqueue(IN PRTMP_ADAPTER pAd,
4691                     IN ULONG Machine,
4692                     IN ULONG MsgType, IN ULONG MsgLen, IN VOID * Msg)
4693 {
4694         INT Tail;
4695         MLME_QUEUE *Queue = (MLME_QUEUE *) & pAd->Mlme.Queue;
4696
4697         // Do nothing if the driver is starting halt state.
4698         // This might happen when timer already been fired before cancel timer with mlmehalt
4699         if (RTMP_TEST_FLAG
4700             (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4701                 return FALSE;
4702
4703         // First check the size, it MUST not exceed the mlme queue size
4704         if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4705                 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n",
4706                               MsgLen));
4707                 return FALSE;
4708         }
4709
4710         if (MlmeQueueFull(Queue)) {
4711                 return FALSE;
4712         }
4713
4714         NdisAcquireSpinLock(&(Queue->Lock));
4715         Tail = Queue->Tail;
4716         Queue->Tail++;
4717         Queue->Num++;
4718         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
4719                 Queue->Tail = 0;
4720         }
4721
4722         Queue->Entry[Tail].Wcid = RESERVED_WCID;
4723         Queue->Entry[Tail].Occupied = TRUE;
4724         Queue->Entry[Tail].Machine = Machine;
4725         Queue->Entry[Tail].MsgType = MsgType;
4726         Queue->Entry[Tail].MsgLen = MsgLen;
4727
4728         if (Msg != NULL) {
4729                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4730         }
4731
4732         NdisReleaseSpinLock(&(Queue->Lock));
4733         return TRUE;
4734 }
4735
4736 /*! \brief       This function is used when Recv gets a MLME message
4737  *      \param  *Queue                   The MLME Queue
4738  *      \param   TimeStampHigh   The upper 32 bit of timestamp
4739  *      \param   TimeStampLow    The lower 32 bit of timestamp
4740  *      \param   Rssi                    The receiving RSSI strength
4741  *      \param   MsgLen                  The length of the message
4742  *      \param  *Msg                     The message pointer
4743  *      \return  TRUE if everything ok, FALSE otherwise (like Queue Full)
4744  *      \pre
4745  *      \post
4746
4747  IRQL = DISPATCH_LEVEL
4748
4749  */
4750 BOOLEAN MlmeEnqueueForRecv(IN PRTMP_ADAPTER pAd,
4751                            IN ULONG Wcid,
4752                            IN ULONG TimeStampHigh,
4753                            IN ULONG TimeStampLow,
4754                            IN UCHAR Rssi0,
4755                            IN UCHAR Rssi1,
4756                            IN UCHAR Rssi2,
4757                            IN ULONG MsgLen, IN VOID * Msg, IN UCHAR Signal)
4758 {
4759         INT Tail, Machine;
4760         PFRAME_802_11 pFrame = (PFRAME_802_11) Msg;
4761         INT MsgType;
4762         MLME_QUEUE *Queue = (MLME_QUEUE *) & pAd->Mlme.Queue;
4763
4764         // Do nothing if the driver is starting halt state.
4765         // This might happen when timer already been fired before cancel timer with mlmehalt
4766         if (RTMP_TEST_FLAG
4767             (pAd,
4768              fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) {
4769                 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4770                 return FALSE;
4771         }
4772         // First check the size, it MUST not exceed the mlme queue size
4773         if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4774                 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4775                 return FALSE;
4776         }
4777
4778         if (MlmeQueueFull(Queue)) {
4779                 return FALSE;
4780         }
4781
4782         {
4783                 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) {
4784                         DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType));
4785                         return FALSE;
4786                 }
4787         }
4788
4789         // OK, we got all the informations, it is time to put things into queue
4790         NdisAcquireSpinLock(&(Queue->Lock));
4791         Tail = Queue->Tail;
4792         Queue->Tail++;
4793         Queue->Num++;
4794         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
4795                 Queue->Tail = 0;
4796         }
4797         Queue->Entry[Tail].Occupied = TRUE;
4798         Queue->Entry[Tail].Machine = Machine;
4799         Queue->Entry[Tail].MsgType = MsgType;
4800         Queue->Entry[Tail].MsgLen = MsgLen;
4801         Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4802         Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4803         Queue->Entry[Tail].Rssi0 = Rssi0;
4804         Queue->Entry[Tail].Rssi1 = Rssi1;
4805         Queue->Entry[Tail].Rssi2 = Rssi2;
4806         Queue->Entry[Tail].Signal = Signal;
4807         Queue->Entry[Tail].Wcid = (UCHAR) Wcid;
4808
4809         Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4810
4811         if (Msg != NULL) {
4812                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4813         }
4814
4815         NdisReleaseSpinLock(&(Queue->Lock));
4816
4817         RTMP_MLME_HANDLER(pAd);
4818
4819         return TRUE;
4820 }
4821
4822 /*! \brief       Dequeue a message from the MLME Queue
4823  *      \param  *Queue    The MLME Queue
4824  *      \param  *Elem     The message dequeued from MLME Queue
4825  *      \return  TRUE if the Elem contains something, FALSE otherwise
4826  *      \pre
4827  *      \post
4828
4829  IRQL = DISPATCH_LEVEL
4830
4831  */
4832 BOOLEAN MlmeDequeue(IN MLME_QUEUE * Queue, OUT MLME_QUEUE_ELEM ** Elem)
4833 {
4834         NdisAcquireSpinLock(&(Queue->Lock));
4835         *Elem = &(Queue->Entry[Queue->Head]);
4836         Queue->Num--;
4837         Queue->Head++;
4838         if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) {
4839                 Queue->Head = 0;
4840         }
4841         NdisReleaseSpinLock(&(Queue->Lock));
4842         return TRUE;
4843 }
4844
4845 // IRQL = DISPATCH_LEVEL
4846 VOID MlmeRestartStateMachine(IN PRTMP_ADAPTER pAd)
4847 {
4848 #ifdef RTMP_MAC_PCI
4849         MLME_QUEUE_ELEM *Elem = NULL;
4850 #endif // RTMP_MAC_PCI //
4851         BOOLEAN Cancelled;
4852
4853         DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4854
4855 #ifdef RTMP_MAC_PCI
4856         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4857         if (pAd->Mlme.bRunning) {
4858                 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4859                 return;
4860         } else {
4861                 pAd->Mlme.bRunning = TRUE;
4862         }
4863         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4864
4865         // Remove all Mlme queues elements
4866         while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
4867                 //From message type, determine which state machine I should drive
4868                 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
4869                         // free MLME element
4870                         Elem->Occupied = FALSE;
4871                         Elem->MsgLen = 0;
4872
4873                 } else {
4874                         DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4875                 }
4876         }
4877 #endif // RTMP_MAC_PCI //
4878
4879         {
4880                 // Cancel all timer events
4881                 // Be careful to cancel new added timer
4882                 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4883                 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4884                 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4885                 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4886                 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4887                 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4888
4889         }
4890
4891         // Change back to original channel in case of doing scan
4892         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4893         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4894
4895         // Resume MSDU which is turned off durning scan
4896         RTMPResumeMsduTransmission(pAd);
4897
4898         {
4899                 // Set all state machines back IDLE
4900                 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4901                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4902                 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4903                 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4904                 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4905                 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4906         }
4907
4908 #ifdef RTMP_MAC_PCI
4909         // Remove running state
4910         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4911         pAd->Mlme.bRunning = FALSE;
4912         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4913 #endif // RTMP_MAC_PCI //
4914 }
4915
4916 /*! \brief      test if the MLME Queue is empty
4917  *      \param  *Queue    The MLME Queue
4918  *      \return TRUE if the Queue is empty, FALSE otherwise
4919  *      \pre
4920  *      \post
4921
4922  IRQL = DISPATCH_LEVEL
4923
4924  */
4925 BOOLEAN MlmeQueueEmpty(IN MLME_QUEUE * Queue)
4926 {
4927         BOOLEAN Ans;
4928
4929         NdisAcquireSpinLock(&(Queue->Lock));
4930         Ans = (Queue->Num == 0);
4931         NdisReleaseSpinLock(&(Queue->Lock));
4932
4933         return Ans;
4934 }
4935
4936 /*! \brief       test if the MLME Queue is full
4937  *      \param   *Queue          The MLME Queue
4938  *      \return  TRUE if the Queue is empty, FALSE otherwise
4939  *      \pre
4940  *      \post
4941
4942  IRQL = PASSIVE_LEVEL
4943  IRQL = DISPATCH_LEVEL
4944
4945  */
4946 BOOLEAN MlmeQueueFull(IN MLME_QUEUE * Queue)
4947 {
4948         BOOLEAN Ans;
4949
4950         NdisAcquireSpinLock(&(Queue->Lock));
4951         Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE
4952                || Queue->Entry[Queue->Tail].Occupied);
4953         NdisReleaseSpinLock(&(Queue->Lock));
4954
4955         return Ans;
4956 }
4957
4958 /*! \brief       The destructor of MLME Queue
4959  *      \param
4960  *      \return
4961  *      \pre
4962  *      \post
4963  *      \note   Clear Mlme Queue, Set Queue->Num to Zero.
4964
4965  IRQL = PASSIVE_LEVEL
4966
4967  */
4968 VOID MlmeQueueDestroy(IN MLME_QUEUE * pQueue)
4969 {
4970         NdisAcquireSpinLock(&(pQueue->Lock));
4971         pQueue->Num = 0;
4972         pQueue->Head = 0;
4973         pQueue->Tail = 0;
4974         NdisReleaseSpinLock(&(pQueue->Lock));
4975         NdisFreeSpinLock(&(pQueue->Lock));
4976 }
4977
4978 /*! \brief       To substitute the message type if the message is coming from external
4979  *      \param  pFrame             The frame received
4980  *      \param  *Machine           The state machine
4981  *      \param  *MsgType           the message type for the state machine
4982  *      \return TRUE if the substitution is successful, FALSE otherwise
4983  *      \pre
4984  *      \post
4985
4986  IRQL = DISPATCH_LEVEL
4987
4988  */
4989 BOOLEAN MsgTypeSubst(IN PRTMP_ADAPTER pAd,
4990                      IN PFRAME_802_11 pFrame,
4991                      OUT INT * Machine, OUT INT * MsgType)
4992 {
4993         USHORT Seq, Alg;
4994         UCHAR EAPType;
4995         PUCHAR pData;
4996
4997         // Pointer to start of data frames including SNAP header
4998         pData = (PUCHAR) pFrame + LENGTH_802_11;
4999
5000         // The only data type will pass to this function is EAPOL frame
5001         if (pFrame->Hdr.FC.Type == BTYPE_DATA) {
5002                 {
5003                         *Machine = WPA_STATE_MACHINE;
5004                         EAPType =
5005                             *((UCHAR *) pFrame + LENGTH_802_11 +
5006                               LENGTH_802_1_H + 1);
5007                         return (WpaMsgTypeSubst(EAPType, (INT *) MsgType));
5008                 }
5009         }
5010
5011         switch (pFrame->Hdr.FC.SubType) {
5012         case SUBTYPE_ASSOC_REQ:
5013                 *Machine = ASSOC_STATE_MACHINE;
5014                 *MsgType = MT2_PEER_ASSOC_REQ;
5015                 break;
5016         case SUBTYPE_ASSOC_RSP:
5017                 *Machine = ASSOC_STATE_MACHINE;
5018                 *MsgType = MT2_PEER_ASSOC_RSP;
5019                 break;
5020         case SUBTYPE_REASSOC_REQ:
5021                 *Machine = ASSOC_STATE_MACHINE;
5022                 *MsgType = MT2_PEER_REASSOC_REQ;
5023                 break;
5024         case SUBTYPE_REASSOC_RSP:
5025                 *Machine = ASSOC_STATE_MACHINE;
5026                 *MsgType = MT2_PEER_REASSOC_RSP;
5027                 break;
5028         case SUBTYPE_PROBE_REQ:
5029                 *Machine = SYNC_STATE_MACHINE;
5030                 *MsgType = MT2_PEER_PROBE_REQ;
5031                 break;
5032         case SUBTYPE_PROBE_RSP:
5033                 *Machine = SYNC_STATE_MACHINE;
5034                 *MsgType = MT2_PEER_PROBE_RSP;
5035                 break;
5036         case SUBTYPE_BEACON:
5037                 *Machine = SYNC_STATE_MACHINE;
5038                 *MsgType = MT2_PEER_BEACON;
5039                 break;
5040         case SUBTYPE_ATIM:
5041                 *Machine = SYNC_STATE_MACHINE;
5042                 *MsgType = MT2_PEER_ATIM;
5043                 break;
5044         case SUBTYPE_DISASSOC:
5045                 *Machine = ASSOC_STATE_MACHINE;
5046                 *MsgType = MT2_PEER_DISASSOC_REQ;
5047                 break;
5048         case SUBTYPE_AUTH:
5049                 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5050                 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5051                 NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT));
5052                 if (Seq == 1 || Seq == 3) {
5053                         *Machine = AUTH_RSP_STATE_MACHINE;
5054                         *MsgType = MT2_PEER_AUTH_ODD;
5055                 } else if (Seq == 2 || Seq == 4) {
5056                         if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) {
5057                                 *Machine = AUTH_STATE_MACHINE;
5058                                 *MsgType = MT2_PEER_AUTH_EVEN;
5059                         }
5060                 } else {
5061                         return FALSE;
5062                 }
5063                 break;
5064         case SUBTYPE_DEAUTH:
5065                 *Machine = AUTH_RSP_STATE_MACHINE;
5066                 *MsgType = MT2_PEER_DEAUTH;
5067                 break;
5068         case SUBTYPE_ACTION:
5069                 *Machine = ACTION_STATE_MACHINE;
5070                 //  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5071                 if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) {
5072                         *MsgType = MT2_ACT_INVALID;
5073                 } else {
5074                         *MsgType = (pFrame->Octet[0] & 0x7F);
5075                 }
5076                 break;
5077         default:
5078                 return FALSE;
5079                 break;
5080         }
5081
5082         return TRUE;
5083 }
5084
5085 // ===========================================================================================
5086 // state_machine.c
5087 // ===========================================================================================
5088
5089 /*! \brief Initialize the state machine.
5090  *      \param *S                       pointer to the state machine
5091  *      \param  Trans           State machine transition function
5092  *      \param  StNr            number of states
5093  *      \param  MsgNr           number of messages
5094  *      \param  DefFunc         default function, when there is invalid state/message combination
5095  *      \param  InitState       initial state of the state machine
5096  *      \param  Base            StateMachine base, internal use only
5097  *      \pre p_sm should be a legal pointer
5098  *      \post
5099
5100  IRQL = PASSIVE_LEVEL
5101
5102  */
5103 VOID StateMachineInit(IN STATE_MACHINE * S,
5104                       IN STATE_MACHINE_FUNC Trans[],
5105                       IN ULONG StNr,
5106                       IN ULONG MsgNr,
5107                       IN STATE_MACHINE_FUNC DefFunc,
5108                       IN ULONG InitState, IN ULONG Base)
5109 {
5110         ULONG i, j;
5111
5112         // set number of states and messages
5113         S->NrState = StNr;
5114         S->NrMsg = MsgNr;
5115         S->Base = Base;
5116
5117         S->TransFunc = Trans;
5118
5119         // init all state transition to default function
5120         for (i = 0; i < StNr; i++) {
5121                 for (j = 0; j < MsgNr; j++) {
5122                         S->TransFunc[i * MsgNr + j] = DefFunc;
5123                 }
5124         }
5125
5126         // set the starting state
5127         S->CurrState = InitState;
5128 }
5129
5130 /*! \brief This function fills in the function pointer into the cell in the state machine
5131  *      \param *S       pointer to the state machine
5132  *      \param St       state
5133  *      \param Msg      incoming message
5134  *      \param f        the function to be executed when (state, message) combination occurs at the state machine
5135  *      \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
5136  *      \post
5137
5138  IRQL = PASSIVE_LEVEL
5139
5140  */
5141 VOID StateMachineSetAction(IN STATE_MACHINE * S,
5142                            IN ULONG St,
5143                            IN ULONG Msg, IN STATE_MACHINE_FUNC Func)
5144 {
5145         ULONG MsgIdx;
5146
5147         MsgIdx = Msg - S->Base;
5148
5149         if (St < S->NrState && MsgIdx < S->NrMsg) {
5150                 // boundary checking before setting the action
5151                 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5152         }
5153 }
5154
5155 /*! \brief       This function does the state transition
5156  *      \param   *Adapter the NIC adapter pointer
5157  *      \param   *S       the state machine
5158  *      \param   *Elem    the message to be executed
5159  *      \return   None
5160
5161  IRQL = DISPATCH_LEVEL
5162
5163  */
5164 VOID StateMachinePerformAction(IN PRTMP_ADAPTER pAd,
5165                                IN STATE_MACHINE * S, IN MLME_QUEUE_ELEM * Elem)
5166 {
5167         (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))
5168             (pAd, Elem);
5169 }
5170
5171 /*
5172         ==========================================================================
5173         Description:
5174                 The drop function, when machine executes this, the message is simply
5175                 ignored. This function does nothing, the message is freed in
5176                 StateMachinePerformAction()
5177         ==========================================================================
5178  */
5179 VOID Drop(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
5180 {
5181 }
5182
5183 // ===========================================================================================
5184 // lfsr.c
5185 // ===========================================================================================
5186
5187 /*
5188         ==========================================================================
5189         Description:
5190
5191         IRQL = PASSIVE_LEVEL
5192
5193         ==========================================================================
5194  */
5195 VOID LfsrInit(IN PRTMP_ADAPTER pAd, IN ULONG Seed)
5196 {
5197         if (Seed == 0)
5198                 pAd->Mlme.ShiftReg = 1;
5199         else
5200                 pAd->Mlme.ShiftReg = Seed;
5201 }
5202
5203 /*
5204         ==========================================================================
5205         Description:
5206         ==========================================================================
5207  */
5208 UCHAR RandomByte(IN PRTMP_ADAPTER pAd)
5209 {
5210         ULONG i;
5211         UCHAR R, Result;
5212
5213         R = 0;
5214
5215         if (pAd->Mlme.ShiftReg == 0)
5216                 NdisGetSystemUpTime((ULONG *) & pAd->Mlme.ShiftReg);
5217
5218         for (i = 0; i < 8; i++) {
5219                 if (pAd->Mlme.ShiftReg & 0x00000001) {
5220                         pAd->Mlme.ShiftReg =
5221                             ((pAd->Mlme.
5222                               ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5223                         Result = 1;
5224                 } else {
5225                         pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5226                         Result = 0;
5227                 }
5228                 R = (R << 1) | Result;
5229         }
5230
5231         return R;
5232 }
5233
5234 /*
5235         ========================================================================
5236
5237         Routine Description:
5238                 Verify the support rate for different PHY type
5239
5240         Arguments:
5241                 pAd                             Pointer to our adapter
5242
5243         Return Value:
5244                 None
5245
5246         IRQL = PASSIVE_LEVEL
5247
5248         ========================================================================
5249 */
5250 VOID RTMPCheckRates(IN PRTMP_ADAPTER pAd,
5251                     IN OUT UCHAR SupRate[], IN OUT UCHAR * SupRateLen)
5252 {
5253         UCHAR RateIdx, i, j;
5254         UCHAR NewRate[12], NewRateLen;
5255
5256         NewRateLen = 0;
5257
5258         if (pAd->CommonCfg.PhyMode == PHY_11B)
5259                 RateIdx = 4;
5260         else
5261                 RateIdx = 12;
5262
5263         // Check for support rates exclude basic rate bit
5264         for (i = 0; i < *SupRateLen; i++)
5265                 for (j = 0; j < RateIdx; j++)
5266                         if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5267                                 NewRate[NewRateLen++] = SupRate[i];
5268
5269         *SupRateLen = NewRateLen;
5270         NdisMoveMemory(SupRate, NewRate, NewRateLen);
5271 }
5272
5273 BOOLEAN RTMPCheckChannel(IN PRTMP_ADAPTER pAd,
5274                          IN UCHAR CentralChannel, IN UCHAR Channel)
5275 {
5276         UCHAR k;
5277         UCHAR UpperChannel = 0, LowerChannel = 0;
5278         UCHAR NoEffectChannelinList = 0;
5279
5280         // Find upper and lower channel according to 40MHz current operation.
5281         if (CentralChannel < Channel) {
5282                 UpperChannel = Channel;
5283                 if (CentralChannel > 2)
5284                         LowerChannel = CentralChannel - 2;
5285                 else
5286                         return FALSE;
5287         } else if (CentralChannel > Channel) {
5288                 UpperChannel = CentralChannel + 2;
5289                 LowerChannel = Channel;
5290         }
5291
5292         for (k = 0; k < pAd->ChannelListNum; k++) {
5293                 if (pAd->ChannelList[k].Channel == UpperChannel) {
5294                         NoEffectChannelinList++;
5295                 }
5296                 if (pAd->ChannelList[k].Channel == LowerChannel) {
5297                         NoEffectChannelinList++;
5298                 }
5299         }
5300
5301         DBGPRINT(RT_DEBUG_TRACE,
5302                  ("Total Channel in Channel List = [%d]\n",
5303                   NoEffectChannelinList));
5304         if (NoEffectChannelinList == 2)
5305                 return TRUE;
5306         else
5307                 return FALSE;
5308 }
5309
5310 /*
5311         ========================================================================
5312
5313         Routine Description:
5314                 Verify the support rate for HT phy type
5315
5316         Arguments:
5317                 pAd                             Pointer to our adapter
5318
5319         Return Value:
5320                 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
5321
5322         IRQL = PASSIVE_LEVEL
5323
5324         ========================================================================
5325 */
5326 BOOLEAN RTMPCheckHt(IN PRTMP_ADAPTER pAd,
5327                     IN UCHAR Wcid,
5328                     IN HT_CAPABILITY_IE * pHtCapability,
5329                     IN ADD_HT_INFO_IE * pAddHtInfo)
5330 {
5331         if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5332                 return FALSE;
5333
5334         // If use AMSDU, set flag.
5335         if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
5336                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5337                                        fCLIENT_STATUS_AMSDU_INUSED);
5338         // Save Peer Capability
5339         if (pHtCapability->HtCapInfo.ShortGIfor20)
5340                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5341                                        fCLIENT_STATUS_SGI20_CAPABLE);
5342         if (pHtCapability->HtCapInfo.ShortGIfor40)
5343                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5344                                        fCLIENT_STATUS_SGI40_CAPABLE);
5345         if (pHtCapability->HtCapInfo.TxSTBC)
5346                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5347                                        fCLIENT_STATUS_TxSTBC_CAPABLE);
5348         if (pHtCapability->HtCapInfo.RxSTBC)
5349                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5350                                        fCLIENT_STATUS_RxSTBC_CAPABLE);
5351         if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) {
5352                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5353                                        fCLIENT_STATUS_RDG_CAPABLE);
5354         }
5355
5356         if (Wcid < MAX_LEN_OF_MAC_TABLE) {
5357                 pAd->MacTab.Content[Wcid].MpduDensity =
5358                     pHtCapability->HtCapParm.MpduDensity;
5359         }
5360         // Will check ChannelWidth for MCSSet[4] below
5361         pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
5362         switch (pAd->CommonCfg.RxStream) {
5363         case 1:
5364                 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5365                 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5366                 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5367                 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5368                 break;
5369         case 2:
5370                 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5371                 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5372                 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5373                 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5374                 break;
5375         case 3:
5376                 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5377                 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5378                 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5379                 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5380                 break;
5381         }
5382
5383         pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth =
5384             pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.
5385             ChannelWidth;
5386
5387         DBGPRINT(RT_DEBUG_TRACE,
5388                  ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5389                   pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth,
5390                   pAddHtInfo->AddHtInfo.RecomWidth,
5391                   pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5392                   pAd->NicConfig2.field.BW40MAvailForA,
5393                   pAd->NicConfig2.field.BW40MAvailForG,
5394                   pAd->CommonCfg.PhyMode));
5395
5396         pAd->MlmeAux.HtCapability.HtCapInfo.GF =
5397             pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF;
5398
5399         // Send Assoc Req with my HT capability.
5400         pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =
5401             pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5402         pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =
5403             pAd->CommonCfg.DesiredHtPhy.MimoPs;
5404         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =
5405             (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->
5406                                                           HtCapInfo.
5407                                                           ShortGIfor20);
5408         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =
5409             (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->
5410                                                           HtCapInfo.
5411                                                           ShortGIfor40);
5412         pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =
5413             (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo.
5414                                                     RxSTBC);
5415         pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =
5416             (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo.
5417                                                     TxSTBC);
5418         pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor =
5419             pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5420         pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity =
5421             pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5422         pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC =
5423             pHtCapability->ExtHtCapInfo.PlusHTC;
5424         pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC =
5425             pHtCapability->ExtHtCapInfo.PlusHTC;
5426         if (pAd->CommonCfg.bRdg) {
5427                 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport =
5428                     pHtCapability->ExtHtCapInfo.RDGSupport;
5429                 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5430         }
5431
5432         if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
5433                 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;      // BW20 can't transmit MCS32
5434
5435         COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5436         return TRUE;
5437 }
5438
5439 /*
5440         ========================================================================
5441
5442         Routine Description:
5443                 Verify the support rate for different PHY type
5444
5445         Arguments:
5446                 pAd                             Pointer to our adapter
5447
5448         Return Value:
5449                 None
5450
5451         IRQL = PASSIVE_LEVEL
5452
5453         ========================================================================
5454 */
5455 VOID RTMPUpdateMlmeRate(IN PRTMP_ADAPTER pAd)
5456 {
5457         UCHAR MinimumRate;
5458         UCHAR ProperMlmeRate;   //= RATE_54;
5459         UCHAR i, j, RateIdx = 12;       //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
5460         BOOLEAN bMatch = FALSE;
5461
5462         switch (pAd->CommonCfg.PhyMode) {
5463         case PHY_11B:
5464                 ProperMlmeRate = RATE_11;
5465                 MinimumRate = RATE_1;
5466                 break;
5467         case PHY_11BG_MIXED:
5468         case PHY_11ABGN_MIXED:
5469         case PHY_11BGN_MIXED:
5470                 if ((pAd->MlmeAux.SupRateLen == 4) &&
5471                     (pAd->MlmeAux.ExtRateLen == 0))
5472                         // B only AP
5473                         ProperMlmeRate = RATE_11;
5474                 else
5475                         ProperMlmeRate = RATE_24;
5476
5477                 if (pAd->MlmeAux.Channel <= 14)
5478                         MinimumRate = RATE_1;
5479                 else
5480                         MinimumRate = RATE_6;
5481                 break;
5482         case PHY_11A:
5483         case PHY_11N_2_4G:      // rt2860 need to check mlmerate for 802.11n
5484         case PHY_11GN_MIXED:
5485         case PHY_11AGN_MIXED:
5486         case PHY_11AN_MIXED:
5487         case PHY_11N_5G:
5488                 ProperMlmeRate = RATE_24;
5489                 MinimumRate = RATE_6;
5490                 break;
5491         case PHY_11ABG_MIXED:
5492                 ProperMlmeRate = RATE_24;
5493                 if (pAd->MlmeAux.Channel <= 14)
5494                         MinimumRate = RATE_1;
5495                 else
5496                         MinimumRate = RATE_6;
5497                 break;
5498         default:                // error
5499                 ProperMlmeRate = RATE_1;
5500                 MinimumRate = RATE_1;
5501                 break;
5502         }
5503
5504         for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) {
5505                 for (j = 0; j < RateIdx; j++) {
5506                         if ((pAd->MlmeAux.SupRate[i] & 0x7f) ==
5507                             RateIdTo500Kbps[j]) {
5508                                 if (j == ProperMlmeRate) {
5509                                         bMatch = TRUE;
5510                                         break;
5511                                 }
5512                         }
5513                 }
5514
5515                 if (bMatch)
5516                         break;
5517         }
5518
5519         if (bMatch == FALSE) {
5520                 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) {
5521                         for (j = 0; j < RateIdx; j++) {
5522                                 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) ==
5523                                     RateIdTo500Kbps[j]) {
5524                                         if (j == ProperMlmeRate) {
5525                                                 bMatch = TRUE;
5526                                                 break;
5527                                         }
5528                                 }
5529                         }
5530
5531                         if (bMatch)
5532                                 break;
5533                 }
5534         }
5535
5536         if (bMatch == FALSE) {
5537                 ProperMlmeRate = MinimumRate;
5538         }
5539
5540         pAd->CommonCfg.MlmeRate = MinimumRate;
5541         pAd->CommonCfg.RtsRate = ProperMlmeRate;
5542         if (pAd->CommonCfg.MlmeRate >= RATE_6) {
5543                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
5544                 pAd->CommonCfg.MlmeTransmit.field.MCS =
5545                     OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5546                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5547                     MODE_OFDM;
5548                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5549                     OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5550         } else {
5551                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5552                 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
5553                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5554                     MODE_CCK;
5555                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5556                     pAd->CommonCfg.MlmeRate;
5557         }
5558
5559         DBGPRINT(RT_DEBUG_TRACE,
5560                  ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n",
5561                   pAd->CommonCfg.MlmeTransmit.word));
5562 }
5563
5564 CHAR RTMPMaxRssi(IN PRTMP_ADAPTER pAd,
5565                  IN CHAR Rssi0, IN CHAR Rssi1, IN CHAR Rssi2)
5566 {
5567         CHAR larger = -127;
5568
5569         if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) {
5570                 larger = Rssi0;
5571         }
5572
5573         if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) {
5574                 larger = max(Rssi0, Rssi1);
5575         }
5576
5577         if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) {
5578                 larger = max(larger, Rssi2);
5579         }
5580
5581         if (larger == -127)
5582                 larger = 0;
5583
5584         return larger;
5585 }
5586
5587 /*
5588     ========================================================================
5589     Routine Description:
5590         Periodic evaluate antenna link status
5591
5592     Arguments:
5593         pAd         - Adapter pointer
5594
5595     Return Value:
5596         None
5597
5598     ========================================================================
5599 */
5600 VOID AsicEvaluateRxAnt(IN PRTMP_ADAPTER pAd)
5601 {
5602         UCHAR BBPR3 = 0;
5603
5604         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5605                            fRTMP_ADAPTER_HALT_IN_PROGRESS |
5606                            fRTMP_ADAPTER_RADIO_OFF |
5607                            fRTMP_ADAPTER_NIC_NOT_EXIST |
5608                            fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5609             OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5610 #ifdef RT30xx
5611             || (pAd->EepromAccess)
5612 #endif // RT30xx //
5613 #ifdef RT3090
5614             || (pAd->bPCIclkOff == TRUE)
5615 #endif // RT3090 //
5616             )
5617                 return;
5618
5619         {
5620                 //if (pAd->StaCfg.Psm == PWR_SAVE)
5621                 //      return;
5622
5623                 {
5624
5625                         if (pAd->StaCfg.Psm == PWR_SAVE)
5626                                 return;
5627
5628                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5629                         BBPR3 &= (~0x18);
5630                         if (pAd->Antenna.field.RxPath == 3) {
5631                                 BBPR3 |= (0x10);
5632                         } else if (pAd->Antenna.field.RxPath == 2) {
5633                                 BBPR3 |= (0x8);
5634                         } else if (pAd->Antenna.field.RxPath == 1) {
5635                                 BBPR3 |= (0x0);
5636                         }
5637                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5638 #ifdef RTMP_MAC_PCI
5639                         pAd->StaCfg.BBPR3 = BBPR3;
5640 #endif // RTMP_MAC_PCI //
5641                         if (OPSTATUS_TEST_FLAG
5642                             (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5643                             ) {
5644                                 ULONG TxTotalCnt =
5645                                     pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5646                                     pAd->RalinkCounters.OneSecTxRetryOkCount +
5647                                     pAd->RalinkCounters.OneSecTxFailCount;
5648
5649                                 // dynamic adjust antenna evaluation period according to the traffic
5650                                 if (TxTotalCnt > 50) {
5651                                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5652                                                      20);
5653                                         pAd->Mlme.bLowThroughput = FALSE;
5654                                 } else {
5655                                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5656                                                      300);
5657                                         pAd->Mlme.bLowThroughput = TRUE;
5658                                 }
5659                         }
5660                 }
5661
5662         }
5663
5664 }
5665
5666 /*
5667     ========================================================================
5668     Routine Description:
5669         After evaluation, check antenna link status
5670
5671     Arguments:
5672         pAd         - Adapter pointer
5673
5674     Return Value:
5675         None
5676
5677     ========================================================================
5678 */
5679 VOID AsicRxAntEvalTimeout(IN PVOID SystemSpecific1,
5680                           IN PVOID FunctionContext,
5681                           IN PVOID SystemSpecific2, IN PVOID SystemSpecific3)
5682 {
5683         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext;
5684         UCHAR BBPR3 = 0;
5685         CHAR larger = -127, rssi0, rssi1, rssi2;
5686
5687         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5688                            fRTMP_ADAPTER_HALT_IN_PROGRESS |
5689                            fRTMP_ADAPTER_RADIO_OFF |
5690                            fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5691             OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5692 #ifdef RT30xx
5693             || (pAd->EepromAccess)
5694 #endif // RT30xx //
5695 #ifdef RT3090
5696             || (pAd->bPCIclkOff == TRUE)
5697 #endif // RT3090 //
5698             )
5699                 return;
5700
5701         {
5702                 //if (pAd->StaCfg.Psm == PWR_SAVE)
5703                 //      return;
5704                 {
5705                         if (pAd->StaCfg.Psm == PWR_SAVE)
5706                                 return;
5707
5708                         // if the traffic is low, use average rssi as the criteria
5709                         if (pAd->Mlme.bLowThroughput == TRUE) {
5710                                 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5711                                 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5712                                 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
5713                         } else {
5714                                 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5715                                 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5716                                 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5717                         }
5718
5719                         if (pAd->Antenna.field.RxPath == 3) {
5720                                 larger = max(rssi0, rssi1);
5721
5722                                 if (larger > (rssi2 + 20))
5723                                         pAd->Mlme.RealRxPath = 2;
5724                                 else
5725                                         pAd->Mlme.RealRxPath = 3;
5726                         } else if (pAd->Antenna.field.RxPath == 2) {
5727                                 if (rssi0 > (rssi1 + 20))
5728                                         pAd->Mlme.RealRxPath = 1;
5729                                 else
5730                                         pAd->Mlme.RealRxPath = 2;
5731                         }
5732
5733                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5734                         BBPR3 &= (~0x18);
5735                         if (pAd->Mlme.RealRxPath == 3) {
5736                                 BBPR3 |= (0x10);
5737                         } else if (pAd->Mlme.RealRxPath == 2) {
5738                                 BBPR3 |= (0x8);
5739                         } else if (pAd->Mlme.RealRxPath == 1) {
5740                                 BBPR3 |= (0x0);
5741                         }
5742                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5743 #ifdef RTMP_MAC_PCI
5744                         pAd->StaCfg.BBPR3 = BBPR3;
5745 #endif // RTMP_MAC_PCI //
5746                 }
5747         }
5748
5749 }
5750
5751 VOID APSDPeriodicExec(IN PVOID SystemSpecific1,
5752                       IN PVOID FunctionContext,
5753                       IN PVOID SystemSpecific2, IN PVOID SystemSpecific3)
5754 {
5755         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) FunctionContext;
5756
5757         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5758                 return;
5759
5760         pAd->CommonCfg.TriggerTimerCount++;
5761
5762 // Driver should not send trigger frame, it should be send by application layer
5763 /*
5764         if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5765                 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5766                 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5767         {
5768                 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5769                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5770                 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5771                 pAd->CommonCfg.TriggerTimerCount = 0;
5772                 pAd->CommonCfg.bInServicePeriod = TRUE;
5773         }*/
5774 }
5775
5776 /*
5777     ========================================================================
5778     Routine Description:
5779         Set/reset MAC registers according to bPiggyBack parameter
5780
5781     Arguments:
5782         pAd         - Adapter pointer
5783         bPiggyBack  - Enable / Disable Piggy-Back
5784
5785     Return Value:
5786         None
5787
5788     ========================================================================
5789 */
5790 VOID RTMPSetPiggyBack(IN PRTMP_ADAPTER pAd, IN BOOLEAN bPiggyBack)
5791 {
5792         TX_LINK_CFG_STRUC TxLinkCfg;
5793
5794         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5795
5796         TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5797         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5798 }
5799
5800 /*
5801     ========================================================================
5802     Routine Description:
5803         check if this entry need to switch rate automatically
5804
5805     Arguments:
5806         pAd
5807         pEntry
5808
5809     Return Value:
5810         TURE
5811         FALSE
5812
5813     ========================================================================
5814 */
5815 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(IN PRTMP_ADAPTER pAd,
5816                                            IN PMAC_TABLE_ENTRY pEntry)
5817 {
5818         BOOLEAN result = TRUE;
5819
5820         {
5821                 // only associated STA counts
5822                 if (pEntry && (pEntry->ValidAsCLI)
5823                     && (pEntry->Sst == SST_ASSOC)) {
5824                         result = pAd->StaCfg.bAutoTxRateSwitch;
5825                 } else
5826                         result = FALSE;
5827         }
5828
5829         return result;
5830 }
5831
5832 BOOLEAN RTMPAutoRateSwitchCheck(IN PRTMP_ADAPTER pAd)
5833 {
5834         {
5835                 if (pAd->StaCfg.bAutoTxRateSwitch)
5836                         return TRUE;
5837         }
5838         return FALSE;
5839 }
5840
5841 /*
5842     ========================================================================
5843     Routine Description:
5844         check if this entry need to fix tx legacy rate
5845
5846     Arguments:
5847         pAd
5848         pEntry
5849
5850     Return Value:
5851         TURE
5852         FALSE
5853
5854     ========================================================================
5855 */
5856 UCHAR RTMPStaFixedTxMode(IN PRTMP_ADAPTER pAd, IN PMAC_TABLE_ENTRY pEntry)
5857 {
5858         UCHAR tx_mode = FIXED_TXMODE_HT;
5859
5860         {
5861                 tx_mode =
5862                     (UCHAR) pAd->StaCfg.DesiredTransmitSetting.field.
5863                     FixedTxMode;
5864         }
5865
5866         return tx_mode;
5867 }
5868
5869 /*
5870     ========================================================================
5871     Routine Description:
5872         Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5873
5874     Arguments:
5875         pAd
5876         pEntry
5877
5878     Return Value:
5879         TURE
5880         FALSE
5881
5882     ========================================================================
5883 */
5884 VOID RTMPUpdateLegacyTxSetting(UCHAR fixed_tx_mode, PMAC_TABLE_ENTRY pEntry)
5885 {
5886         HTTRANSMIT_SETTING TransmitSetting;
5887
5888         if (fixed_tx_mode == FIXED_TXMODE_HT)
5889                 return;
5890
5891         TransmitSetting.word = 0;
5892
5893         TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5894         TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5895
5896         if (fixed_tx_mode == FIXED_TXMODE_CCK) {
5897                 TransmitSetting.field.MODE = MODE_CCK;
5898                 // CCK mode allow MCS 0~3
5899                 if (TransmitSetting.field.MCS > MCS_3)
5900                         TransmitSetting.field.MCS = MCS_3;
5901         } else {
5902                 TransmitSetting.field.MODE = MODE_OFDM;
5903                 // OFDM mode allow MCS 0~7
5904                 if (TransmitSetting.field.MCS > MCS_7)
5905                         TransmitSetting.field.MCS = MCS_7;
5906         }
5907
5908         if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) {
5909                 pEntry->HTPhyMode.word = TransmitSetting.word;
5910                 DBGPRINT(RT_DEBUG_TRACE,
5911                          ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5912                           pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE),
5913                           pEntry->HTPhyMode.field.MCS));
5914         }
5915 }
5916
5917 /*
5918         ==========================================================================
5919         Description:
5920                 dynamic tune BBP R66 to find a balance between sensibility and
5921                 noise isolation
5922
5923         IRQL = DISPATCH_LEVEL
5924
5925         ==========================================================================
5926  */
5927 VOID AsicStaBbpTuning(IN PRTMP_ADAPTER pAd)
5928 {
5929         UCHAR OrigR66Value = 0, R66;    //, R66UpperBound = 0x30, R66LowerBound = 0x30;
5930         CHAR Rssi;
5931
5932         // 2860C did not support Fase CCA, therefore can't tune
5933         if (pAd->MACVersion == 0x28600100)
5934                 return;
5935
5936         //
5937         // work as a STA
5938         //
5939         if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)       // no R66 tuning when SCANNING
5940                 return;
5941
5942         if ((pAd->OpMode == OPMODE_STA)
5943             && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5944             )
5945             && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
5946 #ifdef RTMP_MAC_PCI
5947             && (pAd->bPCIclkOff == FALSE)
5948 #endif // RTMP_MAC_PCI //
5949             ) {
5950                 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5951                 R66 = OrigR66Value;
5952
5953                 if (pAd->Antenna.field.RxPath > 1)
5954                         Rssi =
5955                             (pAd->StaCfg.RssiSample.AvgRssi0 +
5956                              pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
5957                 else
5958                         Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5959
5960                 if (pAd->LatchRfRegs.Channel <= 14) {   //BG band
5961 #ifdef RT30xx
5962                         // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
5963                         // Otherwise, it will have some throughput side effect when low RSSI
5964
5965                         if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
5966                             || IS_RT3390(pAd)) {
5967                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5968                                         R66 =
5969                                             0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20;
5970                                         if (OrigR66Value != R66) {
5971                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5972                                                     (pAd, BBP_R66, R66);
5973                                         }
5974                                 } else {
5975                                         R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
5976                                         if (OrigR66Value != R66) {
5977                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5978                                                     (pAd, BBP_R66, R66);
5979                                         }
5980                                 }
5981                         } else
5982 #endif // RT30xx //
5983                         {
5984                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5985                                         R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
5986                                         if (OrigR66Value != R66) {
5987                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5988                                                     (pAd, BBP_R66, R66);
5989                                         }
5990                                 } else {
5991                                         R66 = 0x2E + GET_LNA_GAIN(pAd);
5992                                         if (OrigR66Value != R66) {
5993                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5994                                                     (pAd, BBP_R66, R66);
5995                                         }
5996                                 }
5997                         }
5998                 } else {        //A band
5999                         if (pAd->CommonCfg.BBPCurrentBW == BW_20) {
6000                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6001                                         R66 =
6002                                             0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 +
6003                                             0x10;
6004                                         if (OrigR66Value != R66) {
6005                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6006                                                     (pAd, BBP_R66, R66);
6007                                         }
6008                                 } else {
6009                                         R66 =
6010                                             0x32 + (GET_LNA_GAIN(pAd) * 5) / 3;
6011                                         if (OrigR66Value != R66) {
6012                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6013                                                     (pAd, BBP_R66, R66);
6014                                         }
6015                                 }
6016                         } else {
6017                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6018                                         R66 =
6019                                             0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 +
6020                                             0x10;
6021                                         if (OrigR66Value != R66) {
6022                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6023                                                     (pAd, BBP_R66, R66);
6024                                         }
6025                                 } else {
6026                                         R66 =
6027                                             0x3A + (GET_LNA_GAIN(pAd) * 5) / 3;
6028                                         if (OrigR66Value != R66) {
6029                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6030                                                     (pAd, BBP_R66, R66);
6031                                         }
6032                                 }
6033                         }
6034                 }
6035
6036         }
6037 }
6038
6039 VOID RTMPSetAGCInitValue(IN PRTMP_ADAPTER pAd, IN UCHAR BandWidth)
6040 {
6041         UCHAR R66 = 0x30;
6042
6043         if (pAd->LatchRfRegs.Channel <= 14) {   // BG band
6044 #ifdef RT30xx
6045                 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6046
6047                 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
6048                     || IS_RT3390(pAd)) {
6049                         R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
6050                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6051                 } else
6052 #endif // RT30xx //
6053                 {
6054                         R66 = 0x2E + GET_LNA_GAIN(pAd);
6055                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6056                 }
6057         } else {                //A band
6058                 {
6059                         if (BandWidth == BW_20) {
6060                                 R66 =
6061                                     (UCHAR) (0x32 +
6062                                              (GET_LNA_GAIN(pAd) * 5) / 3);
6063                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6064                         } else {
6065                                 R66 =
6066                                     (UCHAR) (0x3A +
6067                                              (GET_LNA_GAIN(pAd) * 5) / 3);
6068                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6069                         }
6070                 }
6071         }
6072
6073 }