Staging: rt2860: reduce superfluous exclamation marks
[safe/jmp/linux-2.6] / 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 u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 };
43
44 u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
45 u8 RSN_OUI[] = { 0x00, 0x0f, 0xac };
46 u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
47 u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
48 u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 };
49 u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 };
50 u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c };
51 u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
52 u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c };
53
54 u8 RateSwitchTable[] = {
55 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
56         0x11, 0x00, 0, 0, 0,    /* Initial used item after association */
57         0x00, 0x00, 0, 40, 101,
58         0x01, 0x00, 1, 40, 50,
59         0x02, 0x00, 2, 35, 45,
60         0x03, 0x00, 3, 20, 45,
61         0x04, 0x21, 0, 30, 50,
62         0x05, 0x21, 1, 20, 50,
63         0x06, 0x21, 2, 20, 50,
64         0x07, 0x21, 3, 15, 50,
65         0x08, 0x21, 4, 15, 30,
66         0x09, 0x21, 5, 10, 25,
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 u8 RateSwitchTable11B[] = {
92 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
93         0x04, 0x03, 0, 0, 0,    /* Initial used item after association */
94         0x00, 0x00, 0, 40, 101,
95         0x01, 0x00, 1, 40, 50,
96         0x02, 0x00, 2, 35, 45,
97         0x03, 0x00, 3, 20, 45,
98 };
99
100 u8 RateSwitchTable11BG[] = {
101 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
102         0x0a, 0x00, 0, 0, 0,    /* Initial used item after association */
103         0x00, 0x00, 0, 40, 101,
104         0x01, 0x00, 1, 40, 50,
105         0x02, 0x00, 2, 35, 45,
106         0x03, 0x00, 3, 20, 45,
107         0x04, 0x10, 2, 20, 35,
108         0x05, 0x10, 3, 16, 35,
109         0x06, 0x10, 4, 10, 25,
110         0x07, 0x10, 5, 16, 25,
111         0x08, 0x10, 6, 10, 25,
112         0x09, 0x10, 7, 10, 13,
113 };
114
115 u8 RateSwitchTable11G[] = {
116 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
117         0x08, 0x00, 0, 0, 0,    /* Initial used item after association */
118         0x00, 0x10, 0, 20, 101,
119         0x01, 0x10, 1, 20, 35,
120         0x02, 0x10, 2, 20, 35,
121         0x03, 0x10, 3, 16, 35,
122         0x04, 0x10, 4, 10, 25,
123         0x05, 0x10, 5, 16, 25,
124         0x06, 0x10, 6, 10, 25,
125         0x07, 0x10, 7, 10, 13,
126 };
127
128 u8 RateSwitchTable11N1S[] = {
129 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
130         0x0c, 0x0a, 0, 0, 0,    /* Initial used item after association */
131         0x00, 0x00, 0, 40, 101,
132         0x01, 0x00, 1, 40, 50,
133         0x02, 0x00, 2, 25, 45,
134         0x03, 0x21, 0, 20, 35,
135         0x04, 0x21, 1, 20, 35,
136         0x05, 0x21, 2, 20, 35,
137         0x06, 0x21, 3, 15, 35,
138         0x07, 0x21, 4, 15, 30,
139         0x08, 0x21, 5, 10, 25,
140         0x09, 0x21, 6, 8, 14,
141         0x0a, 0x21, 7, 8, 14,
142         0x0b, 0x23, 7, 8, 14,
143 };
144
145 u8 RateSwitchTable11N2S[] = {
146 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
147         0x0e, 0x0c, 0, 0, 0,    /* Initial used item after association */
148         0x00, 0x00, 0, 40, 101,
149         0x01, 0x00, 1, 40, 50,
150         0x02, 0x00, 2, 25, 45,
151         0x03, 0x21, 0, 20, 35,
152         0x04, 0x21, 1, 20, 35,
153         0x05, 0x21, 2, 20, 35,
154         0x06, 0x21, 3, 15, 35,
155         0x07, 0x21, 4, 15, 30,
156         0x08, 0x20, 11, 15, 30,
157         0x09, 0x20, 12, 15, 30,
158         0x0a, 0x20, 13, 8, 20,
159         0x0b, 0x20, 14, 8, 20,
160         0x0c, 0x20, 15, 8, 25,
161         0x0d, 0x22, 15, 8, 15,
162 };
163
164 u8 RateSwitchTable11N3S[] = {
165 /* Item No.     Mode    Curr-MCS        TrainUp TrainDown       // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
166         0x0b, 0x00, 0, 0, 0,    /* 0x0a, 0x00,  0,  0,  0,      // Initial used item after association */
167         0x00, 0x21, 0, 30, 101,
168         0x01, 0x21, 1, 20, 50,
169         0x02, 0x21, 2, 20, 50,
170         0x03, 0x21, 3, 15, 50,
171         0x04, 0x21, 4, 15, 30,
172         0x05, 0x20, 11, 15, 30, /* Required by System-Alan @ 20080812 */
173         0x06, 0x20, 12, 15, 30, /* 0x05, 0x20, 12, 15, 30, */
174         0x07, 0x20, 13, 8, 20,  /* 0x06, 0x20, 13,  8, 20, */
175         0x08, 0x20, 14, 8, 20,  /* 0x07, 0x20, 14,  8, 20, */
176         0x09, 0x20, 15, 8, 25,  /* 0x08, 0x20, 15,  8, 25, */
177         0x0a, 0x22, 15, 8, 25,  /* 0x09, 0x22, 15,  8, 25, */
178 };
179
180 u8 RateSwitchTable11N2SForABand[] = {
181 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
182         0x0b, 0x09, 0, 0, 0,    /* Initial used item after association */
183         0x00, 0x21, 0, 30, 101,
184         0x01, 0x21, 1, 20, 50,
185         0x02, 0x21, 2, 20, 50,
186         0x03, 0x21, 3, 15, 50,
187         0x04, 0x21, 4, 15, 30,
188         0x05, 0x21, 5, 15, 30,
189         0x06, 0x20, 12, 15, 30,
190         0x07, 0x20, 13, 8, 20,
191         0x08, 0x20, 14, 8, 20,
192         0x09, 0x20, 15, 8, 25,
193         0x0a, 0x22, 15, 8, 25,
194 };
195
196 u8 RateSwitchTable11N3SForABand[] = {   /* 3*3 */
197 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
198         0x0b, 0x09, 0, 0, 0,    /* Initial used item after association */
199         0x00, 0x21, 0, 30, 101,
200         0x01, 0x21, 1, 20, 50,
201         0x02, 0x21, 2, 20, 50,
202         0x03, 0x21, 3, 15, 50,
203         0x04, 0x21, 4, 15, 30,
204         0x05, 0x21, 5, 15, 30,
205         0x06, 0x20, 12, 15, 30,
206         0x07, 0x20, 13, 8, 20,
207         0x08, 0x20, 14, 8, 20,
208         0x09, 0x20, 15, 8, 25,
209         0x0a, 0x22, 15, 8, 25,
210 };
211
212 u8 RateSwitchTable11BGN1S[] = {
213 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
214         0x0c, 0x0a, 0, 0, 0,    /* Initial used item after association */
215         0x00, 0x00, 0, 40, 101,
216         0x01, 0x00, 1, 40, 50,
217         0x02, 0x00, 2, 25, 45,
218         0x03, 0x21, 0, 20, 35,
219         0x04, 0x21, 1, 20, 35,
220         0x05, 0x21, 2, 20, 35,
221         0x06, 0x21, 3, 15, 35,
222         0x07, 0x21, 4, 15, 30,
223         0x08, 0x21, 5, 10, 25,
224         0x09, 0x21, 6, 8, 14,
225         0x0a, 0x21, 7, 8, 14,
226         0x0b, 0x23, 7, 8, 14,
227 };
228
229 u8 RateSwitchTable11BGN2S[] = {
230 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
231         0x0e, 0x0c, 0, 0, 0,    /* Initial used item after association */
232         0x00, 0x00, 0, 40, 101,
233         0x01, 0x00, 1, 40, 50,
234         0x02, 0x00, 2, 25, 45,
235         0x03, 0x21, 0, 20, 35,
236         0x04, 0x21, 1, 20, 35,
237         0x05, 0x21, 2, 20, 35,
238         0x06, 0x21, 3, 15, 35,
239         0x07, 0x21, 4, 15, 30,
240         0x08, 0x20, 11, 15, 30,
241         0x09, 0x20, 12, 15, 30,
242         0x0a, 0x20, 13, 8, 20,
243         0x0b, 0x20, 14, 8, 20,
244         0x0c, 0x20, 15, 8, 25,
245         0x0d, 0x22, 15, 8, 15,
246 };
247
248 u8 RateSwitchTable11BGN3S[] = { /* 3*3 */
249 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
250         0x0a, 0x00, 0, 0, 0,    /* Initial used item after association */
251         0x00, 0x21, 0, 30, 101, /*50 */
252         0x01, 0x21, 1, 20, 50,
253         0x02, 0x21, 2, 20, 50,
254         0x03, 0x21, 3, 20, 50,
255         0x04, 0x21, 4, 15, 50,
256         0x05, 0x20, 20, 15, 30,
257         0x06, 0x20, 21, 8, 20,
258         0x07, 0x20, 22, 8, 20,
259         0x08, 0x20, 23, 8, 25,
260         0x09, 0x22, 23, 8, 25,
261 };
262
263 u8 RateSwitchTable11BGN2SForABand[] = {
264 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
265         0x0b, 0x09, 0, 0, 0,    /* Initial used item after association */
266         0x00, 0x21, 0, 30, 101, /*50 */
267         0x01, 0x21, 1, 20, 50,
268         0x02, 0x21, 2, 20, 50,
269         0x03, 0x21, 3, 15, 50,
270         0x04, 0x21, 4, 15, 30,
271         0x05, 0x21, 5, 15, 30,
272         0x06, 0x20, 12, 15, 30,
273         0x07, 0x20, 13, 8, 20,
274         0x08, 0x20, 14, 8, 20,
275         0x09, 0x20, 15, 8, 25,
276         0x0a, 0x22, 15, 8, 25,
277 };
278
279 u8 RateSwitchTable11BGN3SForABand[] = { /* 3*3 */
280 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
281         0x0c, 0x09, 0, 0, 0,    /* Initial used item after association */
282         0x00, 0x21, 0, 30, 101, /*50 */
283         0x01, 0x21, 1, 20, 50,
284         0x02, 0x21, 2, 20, 50,
285         0x03, 0x21, 3, 15, 50,
286         0x04, 0x21, 4, 15, 30,
287         0x05, 0x21, 5, 15, 30,
288         0x06, 0x21, 12, 15, 30,
289         0x07, 0x20, 20, 15, 30,
290         0x08, 0x20, 21, 8, 20,
291         0x09, 0x20, 22, 8, 20,
292         0x0a, 0x20, 23, 8, 25,
293         0x0b, 0x22, 23, 8, 25,
294 };
295
296 extern u8 OfdmRateToRxwiMCS[];
297 /* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */
298 /* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */
299 unsigned long BasicRateMask[12] =
300     { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ ,
301 0xfffff00f /* 11 */ ,
302         0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ ,
303             0xfffff0ff /* 18 */ ,
304         0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ ,
305             0xffffffff /* 54 */
306 };
307
308 u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
309 u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
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 u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
319 u16 RateIdTo500Kbps[] =
320     { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
321
322 u8 SsidIe = IE_SSID;
323 u8 SupRateIe = IE_SUPP_RATES;
324 u8 ExtRateIe = IE_EXT_SUPP_RATES;
325 u8 HtCapIe = IE_HT_CAP;
326 u8 AddHtInfoIe = IE_ADD_HT;
327 u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET;
328 u8 ErpIe = IE_ERP;
329 u8 DsIe = IE_DS_PARM;
330 u8 TimIe = IE_TIM;
331 u8 WpaIe = IE_WPA;
332 u8 Wpa2Ie = IE_WPA2;
333 u8 IbssIe = IE_IBSS_PARM;
334
335 extern u8 WPA_OUI[];
336
337 u8 SES_OUI[] = { 0x00, 0x90, 0x4c };
338
339 u8 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 int MlmeInit(struct rt_rtmp_adapter *pAd)
360 {
361         int 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(struct rt_rtmp_adapter *pAd)
457 {
458         struct rt_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(struct rt_rtmp_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                 struct rt_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(struct rt_rtmp_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(void *SystemSpecific1,
693                       void *FunctionContext,
694                       void *SystemSpecific2, void *SystemSpecific3)
695 {
696         unsigned long TxTotalCnt;
697         struct rt_rtmp_adapter *pAd = (struct rt_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                         u32 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                                 u32 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(u8 *pSsid, u8 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(struct rt_rtmp_adapter *pAd,
942                            struct rt_mac_table_entry *pEntry,
943                            u8 ** ppTable,
944                            u8 *pTableSize, u8 *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(struct rt_rtmp_adapter *pAd)
1148 {
1149         unsigned long 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                         struct rt_mlme_start_req 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(struct rt_mlme_start_req), &StartReq);
1399                         pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1400                 }
1401
1402                 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1403                         struct rt_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                                 struct rt_mlme_scan_req 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                                                      (char *)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                                                     (struct rt_mlme_scan_req),
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(void *SystemSpecific1,
1491                   void *FunctionContext,
1492                   void *SystemSpecific2, void *SystemSpecific3)
1493 {
1494         struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
1495
1496         if (pAd != NULL) {
1497                 struct rt_mlme_disassoc_req 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(struct rt_mlme_disassoc_req),
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(struct rt_rtmp_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(struct rt_rtmp_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                 struct rt_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(struct rt_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(struct rt_rtmp_adapter *pAd, unsigned long Now32)
1586 {
1587         u16 i;
1588         struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1589         struct rt_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(struct rt_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(struct rt_rtmp_adapter *pAd)
1644 {
1645         u16 i;
1646         struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1647         struct rt_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(struct rt_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(struct rt_rtmp_adapter *pAd,
1703                    struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate)
1704 {
1705         u8 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 = (u16)(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(struct rt_rtmp_adapter *pAd)
1844 {
1845         u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1846         unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt;
1847         unsigned long TxErrorRatio = 0;
1848         BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
1849         struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
1850         u8 *pTable;
1851         u8 TableSize = 0;
1852         u8 InitTxRateIdx = 0, TrainUp, TrainDown;
1853         char Rssi, RssiOffset = 0;
1854         TX_STA_CNT1_STRUC StaTx1;
1855         TX_STA_CNT0_STRUC TxStaCnt0;
1856         unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1857         struct rt_mac_table_entry *pEntry;
1858         struct rt_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                                 unsigned long Index;
1940                                 unsigned long 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                     (struct rt_rtmp_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                             (struct rt_rtmp_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                     (struct rt_rtmp_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                         u8 TxRateIdx;
2044                         u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 =
2045                             0, MCS5 = 0, MCS6 = 0, MCS7 = 0;
2046                         u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2047                         u8 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                                     (struct rt_rtmp_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, however Atheros's chip has bugs when short GI */
2082                                 {
2083                                         MCS15 = idx;
2084                                 } else if (pCurrTxRate->CurrMCS == MCS_20)      /* 3*3 */
2085                                 {
2086                                         MCS20 = idx;
2087                                 } else if (pCurrTxRate->CurrMCS == MCS_21) {
2088                                         MCS21 = idx;
2089                                 } else if (pCurrTxRate->CurrMCS == MCS_22) {
2090                                         MCS22 = idx;
2091                                 } else if (pCurrTxRate->CurrMCS == MCS_23) {
2092                                         MCS23 = idx;
2093                                 }
2094                                 idx++;
2095                         }
2096
2097                         if (pAd->LatchRfRegs.Channel <= 14) {
2098                                 if (pAd->NicConfig2.field.ExternalLNAForG) {
2099                                         RssiOffset = 2;
2100                                 } else {
2101                                         RssiOffset = 5;
2102                                 }
2103                         } else {
2104                                 if (pAd->NicConfig2.field.ExternalLNAForA) {
2105                                         RssiOffset = 5;
2106                                 } else {
2107                                         RssiOffset = 8;
2108                                 }
2109                         }
2110
2111                         /*if (MCS15) */
2112                         if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) {    /* N mode with 3 stream // 3*3 */
2113                                 if (MCS23 && (Rssi >= -70))
2114                                         TxRateIdx = MCS23;
2115                                 else if (MCS22 && (Rssi >= -72))
2116                                         TxRateIdx = MCS22;
2117                                 else if (MCS21 && (Rssi >= -76))
2118                                         TxRateIdx = MCS21;
2119                                 else if (MCS20 && (Rssi >= -78))
2120                                         TxRateIdx = MCS20;
2121                                 else if (MCS4 && (Rssi >= -82))
2122                                         TxRateIdx = MCS4;
2123                                 else if (MCS3 && (Rssi >= -84))
2124                                         TxRateIdx = MCS3;
2125                                 else if (MCS2 && (Rssi >= -86))
2126                                         TxRateIdx = MCS2;
2127                                 else if (MCS1 && (Rssi >= -88))
2128                                         TxRateIdx = MCS1;
2129                                 else
2130                                         TxRateIdx = MCS0;
2131                         }
2132 /*              else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */
2133                         else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand))      /* 3*3 */
2134                         {       /* N mode with 2 stream */
2135                                 if (MCS15 && (Rssi >= (-70 + RssiOffset)))
2136                                         TxRateIdx = MCS15;
2137                                 else if (MCS14 && (Rssi >= (-72 + RssiOffset)))
2138                                         TxRateIdx = MCS14;
2139                                 else if (MCS13 && (Rssi >= (-76 + RssiOffset)))
2140                                         TxRateIdx = MCS13;
2141                                 else if (MCS12 && (Rssi >= (-78 + RssiOffset)))
2142                                         TxRateIdx = MCS12;
2143                                 else if (MCS4 && (Rssi >= (-82 + RssiOffset)))
2144                                         TxRateIdx = MCS4;
2145                                 else if (MCS3 && (Rssi >= (-84 + RssiOffset)))
2146                                         TxRateIdx = MCS3;
2147                                 else if (MCS2 && (Rssi >= (-86 + RssiOffset)))
2148                                         TxRateIdx = MCS2;
2149                                 else if (MCS1 && (Rssi >= (-88 + RssiOffset)))
2150                                         TxRateIdx = MCS1;
2151                                 else
2152                                         TxRateIdx = MCS0;
2153                         } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) {    /* N mode with 1 stream */
2154                                 if (MCS7 && (Rssi > (-72 + RssiOffset)))
2155                                         TxRateIdx = MCS7;
2156                                 else if (MCS6 && (Rssi > (-74 + RssiOffset)))
2157                                         TxRateIdx = MCS6;
2158                                 else if (MCS5 && (Rssi > (-77 + RssiOffset)))
2159                                         TxRateIdx = MCS5;
2160                                 else if (MCS4 && (Rssi > (-79 + RssiOffset)))
2161                                         TxRateIdx = MCS4;
2162                                 else if (MCS3 && (Rssi > (-81 + RssiOffset)))
2163                                         TxRateIdx = MCS3;
2164                                 else if (MCS2 && (Rssi > (-83 + RssiOffset)))
2165                                         TxRateIdx = MCS2;
2166                                 else if (MCS1 && (Rssi > (-86 + RssiOffset)))
2167                                         TxRateIdx = MCS1;
2168                                 else
2169                                         TxRateIdx = MCS0;
2170                         } else {        /* Legacy mode */
2171                                 if (MCS7 && (Rssi > -70))
2172                                         TxRateIdx = MCS7;
2173                                 else if (MCS6 && (Rssi > -74))
2174                                         TxRateIdx = MCS6;
2175                                 else if (MCS5 && (Rssi > -78))
2176                                         TxRateIdx = MCS5;
2177                                 else if (MCS4 && (Rssi > -82))
2178                                         TxRateIdx = MCS4;
2179                                 else if (MCS4 == 0)     /* for B-only mode */
2180                                         TxRateIdx = MCS3;
2181                                 else if (MCS3 && (Rssi > -85))
2182                                         TxRateIdx = MCS3;
2183                                 else if (MCS2 && (Rssi > -87))
2184                                         TxRateIdx = MCS2;
2185                                 else if (MCS1 && (Rssi > -90))
2186                                         TxRateIdx = MCS1;
2187                                 else
2188                                         TxRateIdx = MCS0;
2189                         }
2190
2191                         /*              if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */
2192                         {
2193                                 pEntry->CurrTxRateIndex = TxRateIdx;
2194                                 pNextTxRate =
2195                                     (struct rt_rtmp_tx_rate_switch *) &
2196                                     pTable[(pEntry->CurrTxRateIndex + 1) * 5];
2197                                 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2198                         }
2199
2200                         NdisZeroMemory(pEntry->TxQuality,
2201                                        sizeof(u16)*
2202                                        MAX_STEP_OF_TX_RATE_SWITCH);
2203                         NdisZeroMemory(pEntry->PER,
2204                                        sizeof(u8)*
2205                                        MAX_STEP_OF_TX_RATE_SWITCH);
2206                         pEntry->fLastSecAccordingRSSI = TRUE;
2207                         /* reset all OneSecTx counters */
2208                         RESET_ONE_SEC_TX_CNT(pEntry);
2209
2210                         continue;
2211                 }
2212
2213                 if (pEntry->fLastSecAccordingRSSI == TRUE) {
2214                         pEntry->fLastSecAccordingRSSI = FALSE;
2215                         pEntry->LastSecTxRateChangeAction = 0;
2216                         /* reset all OneSecTx counters */
2217                         RESET_ONE_SEC_TX_CNT(pEntry);
2218
2219                         continue;
2220                 }
2221
2222                 do {
2223                         BOOLEAN bTrainUpDown = FALSE;
2224
2225                         pEntry->CurrTxRateStableTime++;
2226
2227                         /* downgrade TX quality if PER >= Rate-Down threshold */
2228                         if (TxErrorRatio >= TrainDown) {
2229                                 bTrainUpDown = TRUE;
2230                                 pEntry->TxQuality[CurrRateIdx] =
2231                                     DRS_TX_QUALITY_WORST_BOUND;
2232                         }
2233                         /* upgrade TX quality if PER <= Rate-Up threshold */
2234                         else if (TxErrorRatio <= TrainUp) {
2235                                 bTrainUpDown = TRUE;
2236                                 bUpgradeQuality = TRUE;
2237                                 if (pEntry->TxQuality[CurrRateIdx])
2238                                         pEntry->TxQuality[CurrRateIdx]--;       /* quality very good in CurrRate */
2239
2240                                 if (pEntry->TxRateUpPenalty)
2241                                         pEntry->TxRateUpPenalty--;
2242                                 else if (pEntry->TxQuality[UpRateIdx])
2243                                         pEntry->TxQuality[UpRateIdx]--; /* may improve next UP rate's quality */
2244                         }
2245
2246                         pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio;
2247
2248                         if (bTrainUpDown) {
2249                                 /* perform DRS - consider TxRate Down first, then rate up. */
2250                                 if ((CurrRateIdx != DownRateIdx)
2251                                     && (pEntry->TxQuality[CurrRateIdx] >=
2252                                         DRS_TX_QUALITY_WORST_BOUND)) {
2253                                         pEntry->CurrTxRateIndex = DownRateIdx;
2254                                 } else if ((CurrRateIdx != UpRateIdx)
2255                                            && (pEntry->TxQuality[UpRateIdx] <=
2256                                                0)) {
2257                                         pEntry->CurrTxRateIndex = UpRateIdx;
2258                                 }
2259                         }
2260                 } while (FALSE);
2261
2262                 /* if rate-up happen, clear all bad history of all TX rates */
2263                 if (pEntry->CurrTxRateIndex > CurrRateIdx) {
2264                         pEntry->CurrTxRateStableTime = 0;
2265                         pEntry->TxRateUpPenalty = 0;
2266                         pEntry->LastSecTxRateChangeAction = 1;  /* rate UP */
2267                         NdisZeroMemory(pEntry->TxQuality,
2268                                        sizeof(u16)*
2269                                        MAX_STEP_OF_TX_RATE_SWITCH);
2270                         NdisZeroMemory(pEntry->PER,
2271                                        sizeof(u8)*
2272                                        MAX_STEP_OF_TX_RATE_SWITCH);
2273
2274                         /* */
2275                         /* For TxRate fast train up */
2276                         /* */
2277                         if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2278                                 RTMPSetTimer(&pAd->StaCfg.
2279                                              StaQuickResponeForRateUpTimer,
2280                                              100);
2281
2282                                 pAd->StaCfg.
2283                                     StaQuickResponeForRateUpTimerRunning = TRUE;
2284                         }
2285                         bTxRateChanged = TRUE;
2286                 }
2287                 /* if rate-down happen, only clear DownRate's bad history */
2288                 else if (pEntry->CurrTxRateIndex < CurrRateIdx) {
2289                         pEntry->CurrTxRateStableTime = 0;
2290                         pEntry->TxRateUpPenalty = 0;    /* no penalty */
2291                         pEntry->LastSecTxRateChangeAction = 2;  /* rate DOWN */
2292                         pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2293                         pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2294
2295                         /* */
2296                         /* For TxRate fast train down */
2297                         /* */
2298                         if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2299                                 RTMPSetTimer(&pAd->StaCfg.
2300                                              StaQuickResponeForRateUpTimer,
2301                                              100);
2302
2303                                 pAd->StaCfg.
2304                                     StaQuickResponeForRateUpTimerRunning = TRUE;
2305                         }
2306                         bTxRateChanged = TRUE;
2307                 } else {
2308                         pEntry->LastSecTxRateChangeAction = 0;  /* rate no change */
2309                         bTxRateChanged = FALSE;
2310                 }
2311
2312                 pEntry->LastTxOkCount = TxSuccess;
2313                 {
2314                         u8 tmpTxRate;
2315
2316                         /* to fix tcp ack issue */
2317                         if (!bTxRateChanged
2318                             && (pAd->RalinkCounters.OneSecReceivedByteCount >
2319                                 (pAd->RalinkCounters.
2320                                  OneSecTransmittedByteCount * 5))) {
2321                                 tmpTxRate = DownRateIdx;
2322                                 DBGPRINT_RAW(RT_DEBUG_TRACE,
2323                                              ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2324                                               pAd->RalinkCounters.
2325                                               OneSecReceivedByteCount,
2326                                               pAd->RalinkCounters.
2327                                               OneSecTransmittedByteCount,
2328                                               pEntry->CurrTxRateIndex,
2329                                               tmpTxRate));
2330                         } else {
2331                                 tmpTxRate = pEntry->CurrTxRateIndex;
2332                         }
2333
2334                         pNextTxRate =
2335                             (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) *
2336                                                             5];
2337                 }
2338                 if (bTxRateChanged && pNextTxRate) {
2339                         MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2340                 }
2341                 /* reset all OneSecTx counters */
2342                 RESET_ONE_SEC_TX_CNT(pEntry);
2343         }
2344 }
2345
2346 /*
2347         ========================================================================
2348         Routine Description:
2349                 Station side, Auto TxRate faster train up timer call back function.
2350
2351         Arguments:
2352                 SystemSpecific1                 - Not used.
2353                 FunctionContext                 - Pointer to our Adapter context.
2354                 SystemSpecific2                 - Not used.
2355                 SystemSpecific3                 - Not used.
2356
2357         Return Value:
2358                 None
2359
2360         ========================================================================
2361 */
2362 void StaQuickResponeForRateUpExec(void *SystemSpecific1,
2363                                   void *FunctionContext,
2364                                   void *SystemSpecific2,
2365                                   void *SystemSpecific3)
2366 {
2367         struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
2368         u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2369         unsigned long TxTotalCnt;
2370         unsigned long TxErrorRatio = 0;
2371         BOOLEAN bTxRateChanged; /*, bUpgradeQuality = FALSE; */
2372         struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
2373         u8 *pTable;
2374         u8 TableSize = 0;
2375         u8 InitTxRateIdx = 0, TrainUp, TrainDown;
2376         TX_STA_CNT1_STRUC StaTx1;
2377         TX_STA_CNT0_STRUC TxStaCnt0;
2378         char Rssi, ratio;
2379         unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2380         struct rt_mac_table_entry *pEntry;
2381         unsigned long i;
2382
2383         pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2384
2385         /* */
2386         /* walk through MAC table, see if need to change AP's TX rate toward each entry */
2387         /* */
2388         for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
2389                 pEntry = &pAd->MacTab.Content[i];
2390
2391                 /* check if this entry need to switch rate automatically */
2392                 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2393                         continue;
2394
2395                 if (INFRA_ON(pAd) && (i == 1))
2396                         Rssi = RTMPMaxRssi(pAd,
2397                                            pAd->StaCfg.RssiSample.AvgRssi0,
2398                                            pAd->StaCfg.RssiSample.AvgRssi1,
2399                                            pAd->StaCfg.RssiSample.AvgRssi2);
2400                 else
2401                         Rssi = RTMPMaxRssi(pAd,
2402                                            pEntry->RssiSample.AvgRssi0,
2403                                            pEntry->RssiSample.AvgRssi1,
2404                                            pEntry->RssiSample.AvgRssi2);
2405
2406                 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2407
2408                 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
2409                                       &InitTxRateIdx);
2410
2411                 /* decide the next upgrade rate and downgrade rate, if any */
2412                 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
2413                         UpRateIdx = CurrRateIdx + 1;
2414                         DownRateIdx = CurrRateIdx - 1;
2415                 } else if (CurrRateIdx == 0) {
2416                         UpRateIdx = CurrRateIdx + 1;
2417                         DownRateIdx = CurrRateIdx;
2418                 } else if (CurrRateIdx == (TableSize - 1)) {
2419                         UpRateIdx = CurrRateIdx;
2420                         DownRateIdx = CurrRateIdx - 1;
2421                 }
2422
2423                 pCurrTxRate =
2424                     (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
2425
2426                 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2427                         TrainUp =
2428                             (pCurrTxRate->TrainUp +
2429                              (pCurrTxRate->TrainUp >> 1));
2430                         TrainDown =
2431                             (pCurrTxRate->TrainDown +
2432                              (pCurrTxRate->TrainDown >> 1));
2433                 } else {
2434                         TrainUp = pCurrTxRate->TrainUp;
2435                         TrainDown = pCurrTxRate->TrainDown;
2436                 }
2437
2438                 if (pAd->MacTab.Size == 1) {
2439                         /* Update statistic counter */
2440                         RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2441                         RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2442
2443                         TxRetransmit = StaTx1.field.TxRetransmit;
2444                         TxSuccess = StaTx1.field.TxSuccess;
2445                         TxFailCount = TxStaCnt0.field.TxFailCount;
2446                         TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2447
2448                         pAd->RalinkCounters.OneSecTxRetryOkCount +=
2449                             StaTx1.field.TxRetransmit;
2450                         pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
2451                             StaTx1.field.TxSuccess;
2452                         pAd->RalinkCounters.OneSecTxFailCount +=
2453                             TxStaCnt0.field.TxFailCount;
2454                         pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
2455                             StaTx1.field.TxSuccess;
2456                         pAd->WlanCounters.RetryCount.u.LowPart +=
2457                             StaTx1.field.TxRetransmit;
2458                         pAd->WlanCounters.FailedCount.u.LowPart +=
2459                             TxStaCnt0.field.TxFailCount;
2460
2461                         if (TxTotalCnt)
2462                                 TxErrorRatio =
2463                                     ((TxRetransmit +
2464                                       TxFailCount) * 100) / TxTotalCnt;
2465                 } else {
2466                         TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2467                             pEntry->OneSecTxRetryOkCount +
2468                             pEntry->OneSecTxFailCount;
2469
2470                         if (TxTotalCnt)
2471                                 TxErrorRatio =
2472                                     ((pEntry->OneSecTxRetryOkCount +
2473                                       pEntry->OneSecTxFailCount) * 100) /
2474                                     TxTotalCnt;
2475                 }
2476
2477                 /* */
2478                 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2479                 /*         (criteria copied from RT2500 for Netopia case) */
2480                 /* */
2481                 if (TxTotalCnt <= 12) {
2482                         NdisZeroMemory(pAd->DrsCounters.TxQuality,
2483                                        sizeof(u16)*
2484                                        MAX_STEP_OF_TX_RATE_SWITCH);
2485                         NdisZeroMemory(pAd->DrsCounters.PER,
2486                                        sizeof(u8)*
2487                                        MAX_STEP_OF_TX_RATE_SWITCH);
2488
2489                         if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2490                             && (CurrRateIdx != DownRateIdx)) {
2491                                 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2492                                 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2493                                     DRS_TX_QUALITY_WORST_BOUND;
2494                         } else
2495                             if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2496                                  2) && (CurrRateIdx != UpRateIdx)) {
2497                                 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2498                         }
2499
2500                         DBGPRINT_RAW(RT_DEBUG_TRACE,
2501                                      ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2502                         return;
2503                 }
2504
2505                 do {
2506                         unsigned long OneSecTxNoRetryOKRationCount;
2507
2508                         if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2509                                 ratio = 5;
2510                         else
2511                                 ratio = 4;
2512
2513                         /* downgrade TX quality if PER >= Rate-Down threshold */
2514                         if (TxErrorRatio >= TrainDown) {
2515                                 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2516                                     DRS_TX_QUALITY_WORST_BOUND;
2517                         }
2518
2519                         pAd->DrsCounters.PER[CurrRateIdx] =
2520                             (u8)TxErrorRatio;
2521
2522                         OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2523
2524                         /* perform DRS - consider TxRate Down first, then rate up. */
2525                         if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2526                             && (CurrRateIdx != DownRateIdx)) {
2527                                 if ((pAd->DrsCounters.LastTxOkCount + 2) >=
2528                                     OneSecTxNoRetryOKRationCount) {
2529                                         pAd->CommonCfg.TxRateIndex =
2530                                             DownRateIdx;
2531                                         pAd->DrsCounters.
2532                                             TxQuality[CurrRateIdx] =
2533                                             DRS_TX_QUALITY_WORST_BOUND;
2534
2535                                 }
2536
2537                         } else
2538                             if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2539                                  2) && (CurrRateIdx != UpRateIdx)) {
2540                                 if ((TxErrorRatio >= 50)
2541                                     || (TxErrorRatio >= TrainDown)) {
2542
2543                                 } else if ((pAd->DrsCounters.LastTxOkCount + 2)
2544                                            >= OneSecTxNoRetryOKRationCount) {
2545                                         pAd->CommonCfg.TxRateIndex = UpRateIdx;
2546                                 }
2547                         }
2548                 } while (FALSE);
2549
2550                 /* if rate-up happen, clear all bad history of all TX rates */
2551                 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) {
2552                         pAd->DrsCounters.TxRateUpPenalty = 0;
2553                         NdisZeroMemory(pAd->DrsCounters.TxQuality,
2554                                        sizeof(u16)*
2555                                        MAX_STEP_OF_TX_RATE_SWITCH);
2556                         NdisZeroMemory(pAd->DrsCounters.PER,
2557                                        sizeof(u8)*
2558                                        MAX_STEP_OF_TX_RATE_SWITCH);
2559                         bTxRateChanged = TRUE;
2560                 }
2561                 /* if rate-down happen, only clear DownRate's bad history */
2562                 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) {
2563                         DBGPRINT_RAW(RT_DEBUG_TRACE,
2564                                      ("QuickDRS: --TX rate from %d to %d \n",
2565                                       CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2566
2567                         pAd->DrsCounters.TxRateUpPenalty = 0;   /* no penalty */
2568                         pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] =
2569                             0;
2570                         pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2571                         bTxRateChanged = TRUE;
2572                 } else {
2573                         bTxRateChanged = FALSE;
2574                 }
2575
2576                 pNextTxRate =
2577                     (struct rt_rtmp_tx_rate_switch *) &
2578                     pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5];
2579                 if (bTxRateChanged && pNextTxRate) {
2580                         MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2581                 }
2582         }
2583 }
2584
2585 /*
2586         ==========================================================================
2587         Description:
2588                 This routine is executed periodically inside MlmePeriodicExec() after
2589                 association with an AP.
2590                 It checks if StaCfg.Psm is consistent with user policy (recorded in
2591                 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2592                 there're some conditions to consider:
2593                 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2594                    the time when Mibss==TRUE
2595                 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2596                    if outgoing traffic available in TxRing or MgmtRing.
2597         Output:
2598                 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2599
2600         IRQL = DISPATCH_LEVEL
2601
2602         ==========================================================================
2603  */
2604 void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32)
2605 {
2606         unsigned long PowerMode;
2607
2608         /* condition - */
2609         /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */
2610         /* 2. user wants either MAX_PSP or FAST_PSP */
2611         /* 3. but current psm is not in PWR_SAVE */
2612         /* 4. CNTL state machine is not doing SCANning */
2613         /* 5. no TX SUCCESS event for the past 1-sec period */
2614         PowerMode = pAd->StaCfg.WindowsPowerMode;
2615
2616         if (INFRA_ON(pAd) &&
2617             (PowerMode != Ndis802_11PowerModeCAM) &&
2618             (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2619 /*              (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */
2620             (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
2621             RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2622             /*&&
2623                (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2624                (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2625             ) {
2626                 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2627                 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2628                 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
2629                 if (!
2630                     (pAd->CommonCfg.bAPSDCapable
2631                      && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
2632                         RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2633                 } else {
2634                         RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2635                 }
2636         }
2637 }
2638
2639 /* IRQL = PASSIVE_LEVEL */
2640 /* IRQL = DISPATCH_LEVEL */
2641 void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm)
2642 {
2643         AUTO_RSP_CFG_STRUC csr4;
2644
2645         pAd->StaCfg.Psm = psm;
2646         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2647         csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0;
2648         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2649
2650         DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2651 }
2652
2653 /*
2654         ==========================================================================
2655         Description:
2656                 This routine calculates TxPER, RxPER of the past N-sec period. And
2657                 according to the calculation result, ChannelQuality is calculated here
2658                 to decide if current AP is still doing the job.
2659
2660                 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2661         Output:
2662                 StaCfg.ChannelQuality - 0..100
2663
2664         IRQL = DISPATCH_LEVEL
2665
2666         NOTE: This routine decide channle quality based on RX CRC error ratio.
2667                 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2668                 is performed right before this routine, so that this routine can decide
2669                 channel quality based on the most up-to-date information
2670         ==========================================================================
2671  */
2672 void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd,
2673                                  struct rt_mac_table_entry *pMacEntry, unsigned long Now32)
2674 {
2675         unsigned long TxOkCnt, TxCnt, TxPER, TxPRR;
2676         unsigned long RxCnt, RxPER;
2677         u8 NorRssi;
2678         char MaxRssi;
2679         struct rt_rssi_sample *pRssiSample = NULL;
2680         u32 OneSecTxNoRetryOkCount = 0;
2681         u32 OneSecTxRetryOkCount = 0;
2682         u32 OneSecTxFailCount = 0;
2683         u32 OneSecRxOkCnt = 0;
2684         u32 OneSecRxFcsErrCnt = 0;
2685         unsigned long ChannelQuality = 0;       /* 0..100, Channel Quality Indication for Roaming */
2686         unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime;
2687
2688         if (pAd->OpMode == OPMODE_STA) {
2689                 pRssiSample = &pAd->StaCfg.RssiSample;
2690                 OneSecTxNoRetryOkCount =
2691                     pAd->RalinkCounters.OneSecTxNoRetryOkCount;
2692                 OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2693                 OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2694                 OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2695                 OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
2696         }
2697
2698         MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
2699                               pRssiSample->LastRssi1, pRssiSample->LastRssi2);
2700
2701         /* */
2702         /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */
2703         /* */
2704         TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2705         TxCnt = TxOkCnt + OneSecTxFailCount;
2706         if (TxCnt < 5) {
2707                 TxPER = 0;
2708                 TxPRR = 0;
2709         } else {
2710                 TxPER = (OneSecTxFailCount * 100) / TxCnt;
2711                 TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2712         }
2713
2714         /* */
2715         /* calculate RX PER - don't take RxPER into consideration if too few sample */
2716         /* */
2717         RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2718         if (RxCnt < 5)
2719                 RxPER = 0;
2720         else
2721                 RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
2722
2723         /* */
2724         /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */
2725         /* */
2726         if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) &&     /* no heavy traffic */
2727             ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) {
2728                 DBGPRINT(RT_DEBUG_TRACE,
2729                          ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2730                           BeaconLostTime, TxOkCnt));
2731                 ChannelQuality = 0;
2732         } else {
2733                 /* Normalize Rssi */
2734                 if (MaxRssi > -40)
2735                         NorRssi = 100;
2736                 else if (MaxRssi < -90)
2737                         NorRssi = 0;
2738                 else
2739                         NorRssi = (MaxRssi + 90) * 2;
2740
2741                 /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER        (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */
2742                 ChannelQuality = (RSSI_WEIGHTING * NorRssi +
2743                                   TX_WEIGHTING * (100 - TxPRR) +
2744                                   RX_WEIGHTING * (100 - RxPER)) / 100;
2745         }
2746
2747         if (pAd->OpMode == OPMODE_STA)
2748                 pAd->Mlme.ChannelQuality =
2749                     (ChannelQuality > 100) ? 100 : ChannelQuality;
2750
2751 }
2752
2753 /* IRQL = DISPATCH_LEVEL */
2754 void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble)
2755 {
2756         AUTO_RSP_CFG_STRUC csr4;
2757
2758         /* */
2759         /* Always use Long preamble before verifiation short preamble functionality works well. */
2760         /* Todo: remove the following line if short preamble functionality works */
2761         /* */
2762         /*TxPreamble = Rt802_11PreambleLong; */
2763
2764         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2765         if (TxPreamble == Rt802_11PreambleLong) {
2766                 DBGPRINT(RT_DEBUG_TRACE,
2767                          ("MlmeSetTxPreamble (= long PREAMBLE)\n"));
2768                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2769                 csr4.field.AutoResponderPreamble = 0;
2770         } else {
2771                 /* NOTE: 1Mbps should always use long preamble */
2772                 DBGPRINT(RT_DEBUG_TRACE,
2773                          ("MlmeSetTxPreamble (= short PREAMBLE)\n"));
2774                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2775                 csr4.field.AutoResponderPreamble = 1;
2776         }
2777
2778         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2779 }
2780
2781 /*
2782     ==========================================================================
2783     Description:
2784         Update basic rate bitmap
2785     ==========================================================================
2786  */
2787
2788 void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter)
2789 {
2790         int i, j;
2791         /* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
2792         u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2793         u8 *sup_p = pAdapter->CommonCfg.SupRate;
2794         u8 *ext_p = pAdapter->CommonCfg.ExtRate;
2795         unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2796
2797         /* if A mode, always use fix BasicRateBitMap */
2798         /*if (pAdapter->CommonCfg.Channel == PHY_11A) */
2799         if (pAdapter->CommonCfg.Channel > 14)
2800                 pAdapter->CommonCfg.BasicRateBitmap = 0x150;    /* 6, 12, 24M */
2801         /* End of if */
2802
2803         if (pAdapter->CommonCfg.BasicRateBitmap > 4095) {
2804                 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2805                 return;
2806         }
2807         /* End of if */
2808         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2809                 sup_p[i] &= 0x7f;
2810                 ext_p[i] &= 0x7f;
2811         }                       /* End of for */
2812
2813         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2814                 if (bitmap & (1 << i)) {
2815                         for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2816                                 if (sup_p[j] == rate[i])
2817                                         sup_p[j] |= 0x80;
2818                                 /* End of if */
2819                         }       /* End of for */
2820
2821                         for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2822                                 if (ext_p[j] == rate[i])
2823                                         ext_p[j] |= 0x80;
2824                                 /* End of if */
2825                         }       /* End of for */
2826                 }               /* End of if */
2827         }                       /* End of for */
2828 }                               /* End of UpdateBasicRateBitmap */
2829
2830 /* IRQL = PASSIVE_LEVEL */
2831 /* IRQL = DISPATCH_LEVEL */
2832 /* bLinkUp is to identify the inital link speed. */
2833 /* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */
2834 void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx)
2835 {
2836         int i, num;
2837         u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2838         u8 MinSupport = RATE_54;
2839         unsigned long BasicRateBitmap = 0;
2840         u8 CurrBasicRate = RATE_1;
2841         u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2842         PHTTRANSMIT_SETTING pHtPhy = NULL;
2843         PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2844         PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2845         BOOLEAN *auto_rate_cur_p;
2846         u8 HtMcs = MCS_AUTO;
2847
2848         /* find max desired rate */
2849         UpdateBasicRateBitmap(pAd);
2850
2851         num = 0;
2852         auto_rate_cur_p = NULL;
2853         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2854                 switch (pAd->CommonCfg.DesireRate[i] & 0x7f) {
2855                 case 2:
2856                         Rate = RATE_1;
2857                         num++;
2858                         break;
2859                 case 4:
2860                         Rate = RATE_2;
2861                         num++;
2862                         break;
2863                 case 11:
2864                         Rate = RATE_5_5;
2865                         num++;
2866                         break;
2867                 case 22:
2868                         Rate = RATE_11;
2869                         num++;
2870                         break;
2871                 case 12:
2872                         Rate = RATE_6;
2873                         num++;
2874                         break;
2875                 case 18:
2876                         Rate = RATE_9;
2877                         num++;
2878                         break;
2879                 case 24:
2880                         Rate = RATE_12;
2881                         num++;
2882                         break;
2883                 case 36:
2884                         Rate = RATE_18;
2885                         num++;
2886                         break;
2887                 case 48:
2888                         Rate = RATE_24;
2889                         num++;
2890                         break;
2891                 case 72:
2892                         Rate = RATE_36;
2893                         num++;
2894                         break;
2895                 case 96:
2896                         Rate = RATE_48;
2897                         num++;
2898                         break;
2899                 case 108:
2900                         Rate = RATE_54;
2901                         num++;
2902                         break;
2903                         /*default: Rate = RATE_1;   break; */
2904                 }
2905                 if (MaxDesire < Rate)
2906                         MaxDesire = Rate;
2907         }
2908
2909 /*=========================================================================== */
2910 /*=========================================================================== */
2911         {
2912                 pHtPhy = &pAd->StaCfg.HTPhyMode;
2913                 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2914                 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2915
2916                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2917                 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2918
2919                 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2920                     (pAd->CommonCfg.PhyMode == PHY_11B) &&
2921                     (MaxDesire > RATE_11)) {
2922                         MaxDesire = RATE_11;
2923                 }
2924         }
2925
2926         pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2927         pMinHtPhy->word = 0;
2928         pMaxHtPhy->word = 0;
2929         pHtPhy->word = 0;
2930
2931         /* Auto rate switching is enabled only if more than one DESIRED RATES are */
2932         /* specified; otherwise disabled */
2933         if (num <= 1) {
2934                 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2935                 /*pAd->CommonCfg.bAutoTxRateSwitch      = FALSE; */
2936                 *auto_rate_cur_p = FALSE;
2937         } else {
2938                 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2939                 /*pAd->CommonCfg.bAutoTxRateSwitch      = TRUE; */
2940                 *auto_rate_cur_p = TRUE;
2941         }
2942
2943         if (HtMcs != MCS_AUTO) {
2944                 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2945                 /*pAd->CommonCfg.bAutoTxRateSwitch      = FALSE; */
2946                 *auto_rate_cur_p = FALSE;
2947         } else {
2948                 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2949                 /*pAd->CommonCfg.bAutoTxRateSwitch      = TRUE; */
2950                 *auto_rate_cur_p = TRUE;
2951         }
2952
2953         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
2954                 pSupRate = &pAd->StaActive.SupRate[0];
2955                 pExtRate = &pAd->StaActive.ExtRate[0];
2956                 SupRateLen = pAd->StaActive.SupRateLen;
2957                 ExtRateLen = pAd->StaActive.ExtRateLen;
2958         } else {
2959                 pSupRate = &pAd->CommonCfg.SupRate[0];
2960                 pExtRate = &pAd->CommonCfg.ExtRate[0];
2961                 SupRateLen = pAd->CommonCfg.SupRateLen;
2962                 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2963         }
2964
2965         /* find max supported rate */
2966         for (i = 0; i < SupRateLen; i++) {
2967                 switch (pSupRate[i] & 0x7f) {
2968                 case 2:
2969                         Rate = RATE_1;
2970                         if (pSupRate[i] & 0x80)
2971                                 BasicRateBitmap |= 0x0001;
2972                         break;
2973                 case 4:
2974                         Rate = RATE_2;
2975                         if (pSupRate[i] & 0x80)
2976                                 BasicRateBitmap |= 0x0002;
2977                         break;
2978                 case 11:
2979                         Rate = RATE_5_5;
2980                         if (pSupRate[i] & 0x80)
2981                                 BasicRateBitmap |= 0x0004;
2982                         break;
2983                 case 22:
2984                         Rate = RATE_11;
2985                         if (pSupRate[i] & 0x80)
2986                                 BasicRateBitmap |= 0x0008;
2987                         break;
2988                 case 12:
2989                         Rate = RATE_6;  /*if (pSupRate[i] & 0x80) */
2990                         BasicRateBitmap |= 0x0010;
2991                         break;
2992                 case 18:
2993                         Rate = RATE_9;
2994                         if (pSupRate[i] & 0x80)
2995                                 BasicRateBitmap |= 0x0020;
2996                         break;
2997                 case 24:
2998                         Rate = RATE_12; /*if (pSupRate[i] & 0x80) */
2999                         BasicRateBitmap |= 0x0040;
3000                         break;
3001                 case 36:
3002                         Rate = RATE_18;
3003                         if (pSupRate[i] & 0x80)
3004                                 BasicRateBitmap |= 0x0080;
3005                         break;
3006                 case 48:
3007                         Rate = RATE_24; /*if (pSupRate[i] & 0x80) */
3008                         BasicRateBitmap |= 0x0100;
3009                         break;
3010                 case 72:
3011                         Rate = RATE_36;
3012                         if (pSupRate[i] & 0x80)
3013                                 BasicRateBitmap |= 0x0200;
3014                         break;
3015                 case 96:
3016                         Rate = RATE_48;
3017                         if (pSupRate[i] & 0x80)
3018                                 BasicRateBitmap |= 0x0400;
3019                         break;
3020                 case 108:
3021                         Rate = RATE_54;
3022                         if (pSupRate[i] & 0x80)
3023                                 BasicRateBitmap |= 0x0800;
3024                         break;
3025                 default:
3026                         Rate = RATE_1;
3027                         break;
3028                 }
3029                 if (MaxSupport < Rate)
3030                         MaxSupport = Rate;
3031
3032                 if (MinSupport > Rate)
3033                         MinSupport = Rate;
3034         }
3035
3036         for (i = 0; i < ExtRateLen; i++) {
3037                 switch (pExtRate[i] & 0x7f) {
3038                 case 2:
3039                         Rate = RATE_1;
3040                         if (pExtRate[i] & 0x80)
3041                                 BasicRateBitmap |= 0x0001;
3042                         break;
3043                 case 4:
3044                         Rate = RATE_2;
3045                         if (pExtRate[i] & 0x80)
3046                                 BasicRateBitmap |= 0x0002;
3047                         break;
3048                 case 11:
3049                         Rate = RATE_5_5;
3050                         if (pExtRate[i] & 0x80)
3051                                 BasicRateBitmap |= 0x0004;
3052                         break;
3053                 case 22:
3054                         Rate = RATE_11;
3055                         if (pExtRate[i] & 0x80)
3056                                 BasicRateBitmap |= 0x0008;
3057                         break;
3058                 case 12:
3059                         Rate = RATE_6;  /*if (pExtRate[i] & 0x80) */
3060                         BasicRateBitmap |= 0x0010;
3061                         break;
3062                 case 18:
3063                         Rate = RATE_9;
3064                         if (pExtRate[i] & 0x80)
3065                                 BasicRateBitmap |= 0x0020;
3066                         break;
3067                 case 24:
3068                         Rate = RATE_12; /*if (pExtRate[i] & 0x80) */
3069                         BasicRateBitmap |= 0x0040;
3070                         break;
3071                 case 36:
3072                         Rate = RATE_18;
3073                         if (pExtRate[i] & 0x80)
3074                                 BasicRateBitmap |= 0x0080;
3075                         break;
3076                 case 48:
3077                         Rate = RATE_24; /*if (pExtRate[i] & 0x80) */
3078                         BasicRateBitmap |= 0x0100;
3079                         break;
3080                 case 72:
3081                         Rate = RATE_36;
3082                         if (pExtRate[i] & 0x80)
3083                                 BasicRateBitmap |= 0x0200;
3084                         break;
3085                 case 96:
3086                         Rate = RATE_48;
3087                         if (pExtRate[i] & 0x80)
3088                                 BasicRateBitmap |= 0x0400;
3089                         break;
3090                 case 108:
3091                         Rate = RATE_54;
3092                         if (pExtRate[i] & 0x80)
3093                                 BasicRateBitmap |= 0x0800;
3094                         break;
3095                 default:
3096                         Rate = RATE_1;
3097                         break;
3098                 }
3099                 if (MaxSupport < Rate)
3100                         MaxSupport = Rate;
3101
3102                 if (MinSupport > Rate)
3103                         MinSupport = Rate;
3104         }
3105
3106         RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3107
3108         /* bug fix */
3109         /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */
3110
3111         /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */
3112         /* the DURATION field of outgoing uniicast DATA/MGMT frame */
3113         for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
3114                 if (BasicRateBitmap & (0x01 << i))
3115                         CurrBasicRate = (u8)i;
3116                 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3117         }
3118
3119         DBGPRINT(RT_DEBUG_TRACE,
3120                  ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3121                   RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3122         /* max tx rate = min {max desire rate, max supported rate} */
3123         if (MaxSupport < MaxDesire)
3124                 pAd->CommonCfg.MaxTxRate = MaxSupport;
3125         else
3126                 pAd->CommonCfg.MaxTxRate = MaxDesire;
3127
3128         pAd->CommonCfg.MinTxRate = MinSupport;
3129         /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */
3130         /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */
3131         /* on average RSSI */
3132         /*       1. RSSI >= -70db, start at 54 Mbps (short distance) */
3133         /*       2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */
3134         /*       3. -75 > RSSI, start at 11 Mbps (long distance) */
3135         if (*auto_rate_cur_p) {
3136                 short dbm = 0;
3137
3138                 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3139
3140                 if (bLinkUp == TRUE)
3141                         pAd->CommonCfg.TxRate = RATE_24;
3142                 else
3143                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3144
3145                 if (dbm < -75)
3146                         pAd->CommonCfg.TxRate = RATE_11;
3147                 else if (dbm < -70)
3148                         pAd->CommonCfg.TxRate = RATE_24;
3149
3150                 /* should never exceed MaxTxRate (consider 11B-only mode) */
3151                 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3152                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3153
3154                 pAd->CommonCfg.TxRateIndex = 0;
3155         } else {
3156                 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3157                 pHtPhy->field.MCS =
3158                     (pAd->CommonCfg.MaxTxRate >
3159                      3) ? (pAd->CommonCfg.MaxTxRate -
3160                            4) : pAd->CommonCfg.MaxTxRate;
3161                 pHtPhy->field.MODE =
3162                     (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3163
3164                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC =
3165                     pHtPhy->field.STBC;
3166                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI =
3167                     pHtPhy->field.ShortGI;
3168                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS =
3169                     pHtPhy->field.MCS;
3170                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE =
3171                     pHtPhy->field.MODE;
3172         }
3173
3174         if (pAd->CommonCfg.TxRate <= RATE_11) {
3175                 pMaxHtPhy->field.MODE = MODE_CCK;
3176                 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3177                 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3178         } else {
3179                 pMaxHtPhy->field.MODE = MODE_OFDM;
3180                 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3181                 if (pAd->CommonCfg.MinTxRate >= RATE_6
3182                     && (pAd->CommonCfg.MinTxRate <= RATE_54)) {
3183                         pMinHtPhy->field.MCS =
3184                             OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
3185                 } else {
3186                         pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3187                 }
3188         }
3189
3190         pHtPhy->word = (pMaxHtPhy->word);
3191         if (bLinkUp && (pAd->OpMode == OPMODE_STA)) {
3192                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3193                 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word =
3194                     pMaxHtPhy->word;
3195                 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word =
3196                     pMinHtPhy->word;
3197         } else {
3198                 switch (pAd->CommonCfg.PhyMode) {
3199                 case PHY_11BG_MIXED:
3200                 case PHY_11B:
3201                 case PHY_11BGN_MIXED:
3202                         pAd->CommonCfg.MlmeRate = RATE_1;
3203                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3204                         pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3205
3206 /*#ifdef        WIFI_TEST */
3207                         pAd->CommonCfg.RtsRate = RATE_11;
3208 /*#else */
3209 /*                              pAd->CommonCfg.RtsRate = RATE_1; */
3210 /*#endif */
3211                         break;
3212                 case PHY_11G:
3213                 case PHY_11A:
3214                 case PHY_11AGN_MIXED:
3215                 case PHY_11GN_MIXED:
3216                 case PHY_11N_2_4G:
3217                 case PHY_11AN_MIXED:
3218                 case PHY_11N_5G:
3219                         pAd->CommonCfg.MlmeRate = RATE_6;
3220                         pAd->CommonCfg.RtsRate = RATE_6;
3221                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3222                         pAd->CommonCfg.MlmeTransmit.field.MCS =
3223                             OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3224                         break;
3225                 case PHY_11ABG_MIXED:
3226                 case PHY_11ABGN_MIXED:
3227                         if (pAd->CommonCfg.Channel <= 14) {
3228                                 pAd->CommonCfg.MlmeRate = RATE_1;
3229                                 pAd->CommonCfg.RtsRate = RATE_1;
3230                                 pAd->CommonCfg.MlmeTransmit.field.MODE =
3231                                     MODE_CCK;
3232                                 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3233                         } else {
3234                                 pAd->CommonCfg.MlmeRate = RATE_6;
3235                                 pAd->CommonCfg.RtsRate = RATE_6;
3236                                 pAd->CommonCfg.MlmeTransmit.field.MODE =
3237                                     MODE_OFDM;
3238                                 pAd->CommonCfg.MlmeTransmit.field.MCS =
3239                                     OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3240                         }
3241                         break;
3242                 default:        /* error */
3243                         pAd->CommonCfg.MlmeRate = RATE_6;
3244                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3245                         pAd->CommonCfg.MlmeTransmit.field.MCS =
3246                             OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3247                         pAd->CommonCfg.RtsRate = RATE_1;
3248                         break;
3249                 }
3250                 /* */
3251                 /* Keep Basic Mlme Rate. */
3252                 /* */
3253                 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word =
3254                     pAd->CommonCfg.MlmeTransmit.word;
3255                 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3256                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3257                             OfdmRateToRxwiMCS[RATE_24];
3258                 else
3259                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3260                             RATE_1;
3261                 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3262         }
3263
3264         DBGPRINT(RT_DEBUG_TRACE,
3265                  (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3266                   RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
3267                   RateIdToMbps[pAd->CommonCfg.MaxTxRate],
3268                   RateIdToMbps[pAd->CommonCfg.MinTxRate],
3269                   /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3270                   *auto_rate_cur_p));
3271         DBGPRINT(RT_DEBUG_TRACE,
3272                  (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3273                   RateIdToMbps[pAd->CommonCfg.TxRate],
3274                   RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3275         DBGPRINT(RT_DEBUG_TRACE,
3276                  ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3277                   pAd->CommonCfg.MlmeTransmit.word,
3278                   pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
3279                   pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
3280                   pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word));
3281 }
3282
3283 /*
3284         ==========================================================================
3285         Description:
3286                 This function update HT Rate setting.
3287                 Input Wcid value is valid for 2 case :
3288                 1. it's used for Station in infra mode that copy AP rate to Mactable.
3289                 2. OR Station   in adhoc mode to copy peer's HT rate to Mactable.
3290
3291  IRQL = DISPATCH_LEVEL
3292
3293         ==========================================================================
3294  */
3295 void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx)
3296 {
3297         u8 StbcMcs;             /*j, StbcMcs, bitmask; */
3298         char i;                 /* 3*3 */
3299         struct rt_ht_capability *pRtHtCap = NULL;
3300         struct rt_ht_phy_info *pActiveHtPhy = NULL;
3301         unsigned long BasicMCS;
3302         u8 j, bitmask;
3303         struct rt_ht_phy_info *pDesireHtPhy = NULL;
3304         PHTTRANSMIT_SETTING pHtPhy = NULL;
3305         PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3306         PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3307         BOOLEAN *auto_rate_cur_p;
3308
3309         DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n"));
3310
3311         auto_rate_cur_p = NULL;
3312
3313         {
3314                 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3315                 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3316                 pHtPhy = &pAd->StaCfg.HTPhyMode;
3317                 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3318                 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3319
3320                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3321         }
3322
3323         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
3324                 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3325                         return;
3326
3327                 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3328                 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3329                 StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3330                 BasicMCS =
3331                     pAd->MlmeAux.AddHtInfo.MCSSet[0] +
3332                     (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3333                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3334                     && (pAd->Antenna.field.TxPath == 2))
3335                         pMaxHtPhy->field.STBC = STBC_USE;
3336                 else
3337                         pMaxHtPhy->field.STBC = STBC_NONE;
3338         } else {
3339                 if (pDesireHtPhy->bHtEnable == FALSE)
3340                         return;
3341
3342                 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3343                 StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3344                 BasicMCS =
3345                     pAd->CommonCfg.AddHTInfo.MCSSet[0] +
3346                     (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3347                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3348                     && (pAd->Antenna.field.TxPath == 2))
3349                         pMaxHtPhy->field.STBC = STBC_USE;
3350                 else
3351                         pMaxHtPhy->field.STBC = STBC_NONE;
3352         }
3353
3354         /* Decide MAX ht rate. */
3355         if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3356                 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3357         else
3358                 pMaxHtPhy->field.MODE = MODE_HTMIX;
3359
3360         if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth)
3361             && (pRtHtCap->ChannelWidth))
3362                 pMaxHtPhy->field.BW = BW_40;
3363         else
3364                 pMaxHtPhy->field.BW = BW_20;
3365
3366         if (pMaxHtPhy->field.BW == BW_20)
3367                 pMaxHtPhy->field.ShortGI =
3368                     (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->
3369                      ShortGIfor20);
3370         else
3371                 pMaxHtPhy->field.ShortGI =
3372                     (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->
3373                      ShortGIfor40);
3374
3375         if (pDesireHtPhy->MCSSet[4] != 0) {
3376                 pMaxHtPhy->field.MCS = 32;
3377         }
3378
3379         for (i = 23; i >= 0; i--)       /* 3*3 */
3380         {
3381                 j = i / 8;
3382                 bitmask = (1 << (i - (j * 8)));
3383
3384                 if ((pActiveHtPhy->MCSSet[j] & bitmask)
3385                     && (pDesireHtPhy->MCSSet[j] & bitmask)) {
3386                         pMaxHtPhy->field.MCS = i;
3387                         break;
3388                 }
3389
3390                 if (i == 0)
3391                         break;
3392         }
3393
3394         /* Copy MIN ht rate.  rt2860??? */
3395         pMinHtPhy->field.BW = BW_20;
3396         pMinHtPhy->field.MCS = 0;
3397         pMinHtPhy->field.STBC = 0;
3398         pMinHtPhy->field.ShortGI = 0;
3399         /*If STA assigns fixed rate. update to fixed here. */
3400         if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) {
3401                 if (pDesireHtPhy->MCSSet[4] != 0) {
3402                         pMaxHtPhy->field.MCS = 32;
3403                         pMinHtPhy->field.MCS = 32;
3404                         DBGPRINT(RT_DEBUG_TRACE,
3405                                  ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3406                                   pMinHtPhy->field.MCS));
3407                 }
3408
3409                 for (i = 23; (char)i >= 0; i--) /* 3*3 */
3410                 {
3411                         j = i / 8;
3412                         bitmask = (1 << (i - (j * 8)));
3413                         if ((pDesireHtPhy->MCSSet[j] & bitmask)
3414                             && (pActiveHtPhy->MCSSet[j] & bitmask)) {
3415                                 pMaxHtPhy->field.MCS = i;
3416                                 pMinHtPhy->field.MCS = i;
3417                                 break;
3418                         }
3419                         if (i == 0)
3420                                 break;
3421                 }
3422         }
3423
3424         /* Decide ht rate */
3425         pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3426         pHtPhy->field.BW = pMaxHtPhy->field.BW;
3427         pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3428         pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3429         pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3430
3431         /* use default now. rt2860 */
3432         if (pDesireHtPhy->MCSSet[0] != 0xff)
3433                 *auto_rate_cur_p = FALSE;
3434         else
3435                 *auto_rate_cur_p = TRUE;
3436
3437         DBGPRINT(RT_DEBUG_TRACE,
3438                  (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n",
3439                   pAd->CommonCfg.DesiredHtPhy.AmsduSize));
3440         DBGPRINT(RT_DEBUG_TRACE,
3441                  ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n",
3442                   pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW,
3443                   pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3444         DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n"));
3445 }
3446
3447 void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab)
3448 {
3449         int i;
3450
3451         Tab->numAsOriginator = 0;
3452         Tab->numAsRecipient = 0;
3453         Tab->numDoneOriginator = 0;
3454         NdisAllocateSpinLock(&pAd->BATabLock);
3455         for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
3456                 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3457                 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3458         }
3459         for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
3460                 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3461         }
3462 }
3463
3464 /* IRQL = DISPATCH_LEVEL */
3465 void MlmeRadioOff(struct rt_rtmp_adapter *pAd)
3466 {
3467         RTMP_MLME_RADIO_OFF(pAd);
3468 }
3469
3470 /* IRQL = DISPATCH_LEVEL */
3471 void MlmeRadioOn(struct rt_rtmp_adapter *pAd)
3472 {
3473         RTMP_MLME_RADIO_ON(pAd);
3474 }
3475
3476 /* =========================================================================================== */
3477 /* bss_table.c */
3478 /* =========================================================================================== */
3479
3480 /*! \brief initialize BSS table
3481  *      \param p_tab pointer to the table
3482  *      \return none
3483  *      \pre
3484  *      \post
3485
3486  IRQL = PASSIVE_LEVEL
3487  IRQL = DISPATCH_LEVEL
3488
3489  */
3490 void BssTableInit(struct rt_bss_table *Tab)
3491 {
3492         int i;
3493
3494         Tab->BssNr = 0;
3495         Tab->BssOverlapNr = 0;
3496         for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) {
3497                 NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry));
3498                 Tab->BssEntry[i].Rssi = -127;   /* initial the rssi as a minimum value */
3499         }
3500 }
3501
3502 /*! \brief search the BSS table by SSID
3503  *      \param p_tab pointer to the bss table
3504  *      \param ssid SSID string
3505  *      \return index of the table, BSS_NOT_FOUND if not in the table
3506  *      \pre
3507  *      \post
3508  *      \note search by sequential search
3509
3510  IRQL = DISPATCH_LEVEL
3511
3512  */
3513 unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel)
3514 {
3515         u8 i;
3516
3517         for (i = 0; i < Tab->BssNr; i++) {
3518                 /* */
3519                 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3520                 /* We should distinguish this case. */
3521                 /* */
3522                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3523                      ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3524                     MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) {
3525                         return i;
3526                 }
3527         }
3528         return (unsigned long)BSS_NOT_FOUND;
3529 }
3530
3531 unsigned long BssSsidTableSearch(struct rt_bss_table *Tab,
3532                          u8 *pBssid,
3533                          u8 *pSsid, u8 SsidLen, u8 Channel)
3534 {
3535         u8 i;
3536
3537         for (i = 0; i < Tab->BssNr; i++) {
3538                 /* */
3539                 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3540                 /* We should distinguish this case. */
3541                 /* */
3542                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3543                      ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3544                     MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3545                     SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3546                                Tab->BssEntry[i].SsidLen)) {
3547                         return i;
3548                 }
3549         }
3550         return (unsigned long)BSS_NOT_FOUND;
3551 }
3552
3553 unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab,
3554                              u8 *Bssid,
3555                              u8 *pSsid,
3556                              u8 SsidLen, u8 Channel)
3557 {
3558         u8 i;
3559
3560         for (i = 0; i < Tab->BssNr; i++) {
3561                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3562                      ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3563                     MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3564                     (SSID_EQUAL
3565                      (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3566                       Tab->BssEntry[i].SsidLen)
3567                      || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen))
3568                      ||
3569                      (NdisEqualMemory
3570                       (Tab->BssEntry[i].Ssid, ZeroSsid,
3571                        Tab->BssEntry[i].SsidLen)))) {
3572                         return i;
3573                 }
3574         }
3575         return (unsigned long)BSS_NOT_FOUND;
3576 }
3577
3578 unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab,
3579                                u8 *pSsid, u8 SsidLen)
3580 {
3581         u8 i;
3582
3583         for (i = 0; i < Tab->BssNr; i++) {
3584                 if (SSID_EQUAL
3585                     (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3586                      Tab->BssEntry[i].SsidLen)) {
3587                         return i;
3588                 }
3589         }
3590         return (unsigned long)BSS_NOT_FOUND;
3591 }
3592
3593 /* IRQL = DISPATCH_LEVEL */
3594 void BssTableDeleteEntry(struct rt_bss_table *Tab,
3595                          u8 *pBssid, u8 Channel)
3596 {
3597         u8 i, j;
3598
3599         for (i = 0; i < Tab->BssNr; i++) {
3600                 if ((Tab->BssEntry[i].Channel == Channel) &&
3601                     (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) {
3602                         for (j = i; j < Tab->BssNr - 1; j++) {
3603                                 NdisMoveMemory(&(Tab->BssEntry[j]),
3604                                                &(Tab->BssEntry[j + 1]),
3605                                                sizeof(struct rt_bss_entry));
3606                         }
3607                         NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]),
3608                                        sizeof(struct rt_bss_entry));
3609                         Tab->BssNr -= 1;
3610                         return;
3611                 }
3612         }
3613 }
3614
3615 /*
3616         ========================================================================
3617         Routine Description:
3618                 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3619
3620         Arguments:
3621         // IRQL = DISPATCH_LEVEL
3622         ========================================================================
3623 */
3624 void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd,
3625                            struct rt_ba_ori_entry *pBAORIEntry)
3626 {
3627
3628         if (pBAORIEntry->ORI_BA_Status != Originator_NONE) {
3629                 NdisAcquireSpinLock(&pAd->BATabLock);
3630                 if (pBAORIEntry->ORI_BA_Status == Originator_Done) {
3631                         pAd->BATable.numAsOriginator -= 1;
3632                         DBGPRINT(RT_DEBUG_TRACE,
3633                                  ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3634                                   pAd->BATable.numAsRecipient));
3635                         /* Erase Bitmap flag. */
3636                 }
3637                 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID)));      /* If STA mode,  erase flag here */
3638                 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;    /* If STA mode,  erase flag here */
3639                 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3640                 pBAORIEntry->Token = 1;
3641                 /* Not clear Sequence here. */
3642                 NdisReleaseSpinLock(&pAd->BATabLock);
3643         }
3644 }
3645
3646 /*! \brief
3647  *      \param
3648  *      \return
3649  *      \pre
3650  *      \post
3651
3652  IRQL = DISPATCH_LEVEL
3653
3654  */
3655 void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * pCfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo,  /* AP might use this additional ht info IE */
3656                  u8 HtCapabilityLen,
3657                  u8 AddHtInfoLen,
3658                  u8 NewExtChanOffset,
3659                  u8 Channel,
3660                  char Rssi,
3661                  IN LARGE_INTEGER TimeStamp,
3662                  u8 CkipFlag,
3663                  struct rt_edca_parm *pEdcaParm,
3664                  struct rt_qos_capability_parm *pQosCapability,
3665                  struct rt_qbss_load_parm *pQbssLoad,
3666                  u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
3667 {
3668         COPY_MAC_ADDR(pBss->Bssid, pBssid);
3669         /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */
3670         pBss->Hidden = 1;
3671         if (SsidLen > 0) {
3672                 /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */
3673                 /* Or send beacon /probe response with SSID len matching real SSID length, */
3674                 /* but SSID is all zero. such as "00-00-00-00" with length 4. */
3675                 /* We have to prevent this case overwrite correct table */
3676                 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) {
3677                         NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3678                         NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3679                         pBss->SsidLen = SsidLen;
3680                         pBss->Hidden = 0;
3681                 }
3682         } else
3683                 pBss->SsidLen = 0;
3684         pBss->BssType = BssType;
3685         pBss->BeaconPeriod = BeaconPeriod;
3686         if (BssType == BSS_INFRA) {
3687                 if (pCfParm->bValid) {
3688                         pBss->CfpCount = pCfParm->CfpCount;
3689                         pBss->CfpPeriod = pCfParm->CfpPeriod;
3690                         pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3691                         pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3692                 }
3693         } else {
3694                 pBss->AtimWin = AtimWin;
3695         }
3696
3697         pBss->CapabilityInfo = CapabilityInfo;
3698         /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */
3699         /* Combine with AuthMode, they will decide the connection methods. */
3700         pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3701         ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3702         if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3703                 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3704         else
3705                 NdisMoveMemory(pBss->SupRate, SupRate,
3706                                MAX_LEN_OF_SUPPORTED_RATES);
3707         pBss->SupRateLen = SupRateLen;
3708         ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3709         NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3710         pBss->NewExtChanOffset = NewExtChanOffset;
3711         pBss->ExtRateLen = ExtRateLen;
3712         pBss->Channel = Channel;
3713         pBss->CentralChannel = Channel;
3714         pBss->Rssi = Rssi;
3715         /* Update CkipFlag. if not exists, the value is 0x0 */
3716         pBss->CkipFlag = CkipFlag;
3717
3718         /* New for microsoft Fixed IEs */
3719         NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3720         pBss->FixIEs.BeaconInterval = BeaconPeriod;
3721         pBss->FixIEs.Capabilities = CapabilityInfo;
3722
3723         /* New for microsoft Variable IEs */
3724         if (LengthVIE != 0) {
3725                 pBss->VarIELen = LengthVIE;
3726                 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3727         } else {
3728                 pBss->VarIELen = 0;
3729         }
3730
3731         pBss->AddHtInfoLen = 0;
3732         pBss->HtCapabilityLen = 0;
3733         if (HtCapabilityLen > 0) {
3734                 pBss->HtCapabilityLen = HtCapabilityLen;
3735                 NdisMoveMemory(&pBss->HtCapability, pHtCapability,
3736                                HtCapabilityLen);
3737                 if (AddHtInfoLen > 0) {
3738                         pBss->AddHtInfoLen = AddHtInfoLen;
3739                         NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo,
3740                                        AddHtInfoLen);
3741
3742                         if ((pAddHtInfo->ControlChan > 2)
3743                             && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
3744                                 EXTCHA_BELOW)
3745                             && (pHtCapability->HtCapInfo.ChannelWidth ==
3746                                 BW_40)) {
3747                                 pBss->CentralChannel =
3748                                     pAddHtInfo->ControlChan - 2;
3749                         } else
3750                             if ((pAddHtInfo->AddHtInfo.ExtChanOffset ==
3751                                  EXTCHA_ABOVE)
3752                                 && (pHtCapability->HtCapInfo.ChannelWidth ==
3753                                     BW_40)) {
3754                                 pBss->CentralChannel =
3755                                     pAddHtInfo->ControlChan + 2;
3756                         }
3757                 }
3758         }
3759
3760         BssCipherParse(pBss);
3761
3762         /* new for QOS */
3763         if (pEdcaParm)
3764                 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm));
3765         else
3766                 pBss->EdcaParm.bValid = FALSE;
3767         if (pQosCapability)
3768                 NdisMoveMemory(&pBss->QosCapability, pQosCapability,
3769                                sizeof(struct rt_qos_capability_parm));
3770         else
3771                 pBss->QosCapability.bValid = FALSE;
3772         if (pQbssLoad)
3773                 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad,
3774                                sizeof(struct rt_qbss_load_parm));
3775         else
3776                 pBss->QbssLoad.bValid = FALSE;
3777
3778         {
3779                 struct rt_eid * pEid;
3780                 u16 Length = 0;
3781
3782                 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3783                 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3784                 pEid = (struct rt_eid *) pVIE;
3785                 while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) {
3786                         switch (pEid->Eid) {
3787                         case IE_WPA:
3788                                 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) {
3789                                         if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3790                                                 pBss->WpaIE.IELen = 0;
3791                                                 break;
3792                                         }
3793                                         pBss->WpaIE.IELen = pEid->Len + 2;
3794                                         NdisMoveMemory(pBss->WpaIE.IE, pEid,
3795                                                        pBss->WpaIE.IELen);
3796                                 }
3797                                 break;
3798                         case IE_RSN:
3799                                 if (NdisEqualMemory
3800                                     (pEid->Octet + 2, RSN_OUI, 3)) {
3801                                         if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3802                                                 pBss->RsnIE.IELen = 0;
3803                                                 break;
3804                                         }
3805                                         pBss->RsnIE.IELen = pEid->Len + 2;
3806                                         NdisMoveMemory(pBss->RsnIE.IE, pEid,
3807                                                        pBss->RsnIE.IELen);
3808                                 }
3809                                 break;
3810                         }
3811                         Length = Length + 2 + (u16)pEid->Len;   /* Eid[1] + Len[1]+ content[Len] */
3812                         pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len);
3813                 }
3814         }
3815 }
3816
3817 /*!
3818  *      \brief insert an entry into the bss table
3819  *      \param p_tab The BSS table
3820  *      \param Bssid BSSID
3821  *      \param ssid SSID
3822  *      \param ssid_len Length of SSID
3823  *      \param bss_type
3824  *      \param beacon_period
3825  *      \param timestamp
3826  *      \param p_cf
3827  *      \param atim_win
3828  *      \param cap
3829  *      \param rates
3830  *      \param rates_len
3831  *      \param channel_idx
3832  *      \return none
3833  *      \pre
3834  *      \post
3835  *      \note If SSID is identical, the old entry will be replaced by the new one
3836
3837  IRQL = DISPATCH_LEVEL
3838
3839  */
3840 unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *Tab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo,      /* AP might use this additional ht info IE */
3841                        u8 HtCapabilityLen,
3842                        u8 AddHtInfoLen,
3843                        u8 NewExtChanOffset,
3844                        u8 ChannelNo,
3845                        char Rssi,
3846                        IN LARGE_INTEGER TimeStamp,
3847                        u8 CkipFlag,
3848                        struct rt_edca_parm *pEdcaParm,
3849                        struct rt_qos_capability_parm *pQosCapability,
3850                        struct rt_qbss_load_parm *pQbssLoad,
3851                        u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
3852 {
3853         unsigned long Idx;
3854
3855         Idx =
3856             BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen,
3857                                    ChannelNo);
3858         if (Idx == BSS_NOT_FOUND) {
3859                 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) {
3860                         /* */
3861                         /* It may happen when BSS Table was full. */
3862                         /* The desired AP will not be added into BSS Table */
3863                         /* In this case, if we found the desired AP then overwrite BSS Table. */
3864                         /* */
3865                         if (!OPSTATUS_TEST_FLAG
3866                             (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
3867                                 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid)
3868                                     || SSID_EQUAL(pAd->MlmeAux.Ssid,
3869                                                   pAd->MlmeAux.SsidLen, Ssid,
3870                                                   SsidLen)) {
3871                                         Idx = Tab->BssOverlapNr;
3872                                         BssEntrySet(pAd, &Tab->BssEntry[Idx],
3873                                                     pBssid, Ssid, SsidLen,
3874                                                     BssType, BeaconPeriod,
3875                                                     CfParm, AtimWin,
3876                                                     CapabilityInfo, SupRate,
3877                                                     SupRateLen, ExtRate,
3878                                                     ExtRateLen, pHtCapability,
3879                                                     pAddHtInfo, HtCapabilityLen,
3880                                                     AddHtInfoLen,
3881                                                     NewExtChanOffset, ChannelNo,
3882                                                     Rssi, TimeStamp, CkipFlag,
3883                                                     pEdcaParm, pQosCapability,
3884                                                     pQbssLoad, LengthVIE, pVIE);
3885                                         Tab->BssOverlapNr =
3886                                             (Tab->BssOverlapNr++) %
3887                                             MAX_LEN_OF_BSS_TABLE;
3888                                 }
3889                                 return Idx;
3890                         } else {
3891                                 return BSS_NOT_FOUND;
3892                         }
3893                 }
3894                 Idx = Tab->BssNr;
3895                 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen,
3896                             BssType, BeaconPeriod, CfParm, AtimWin,
3897                             CapabilityInfo, SupRate, SupRateLen, ExtRate,
3898                             ExtRateLen, pHtCapability, pAddHtInfo,
3899                             HtCapabilityLen, AddHtInfoLen, NewExtChanOffset,
3900                             ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm,
3901                             pQosCapability, pQbssLoad, LengthVIE, pVIE);
3902                 Tab->BssNr++;
3903         } else {
3904                 /* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
3905                 if ((SSID_EQUAL
3906                      (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid,
3907                       Tab->BssEntry[Idx].SsidLen))
3908                     ||
3909                     (NdisEqualMemory
3910                      (Tab->BssEntry[Idx].Ssid, ZeroSsid,
3911                       Tab->BssEntry[Idx].SsidLen))) {
3912                         BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid,
3913                                     SsidLen, BssType, BeaconPeriod, CfParm,
3914                                     AtimWin, CapabilityInfo, SupRate,
3915                                     SupRateLen, ExtRate, ExtRateLen,
3916                                     pHtCapability, pAddHtInfo, HtCapabilityLen,
3917                                     AddHtInfoLen, NewExtChanOffset, ChannelNo,
3918                                     Rssi, TimeStamp, CkipFlag, pEdcaParm,
3919                                     pQosCapability, pQbssLoad, LengthVIE, pVIE);
3920                 }
3921         }
3922
3923         return Idx;
3924 }
3925
3926 /* IRQL = DISPATCH_LEVEL */
3927 void BssTableSsidSort(struct rt_rtmp_adapter *pAd,
3928                       struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen)
3929 {
3930         int i;
3931         BssTableInit(OutTab);
3932
3933         for (i = 0; i < pAd->ScanTab.BssNr; i++) {
3934                 struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i];
3935                 BOOLEAN bIsHiddenApIncluded = FALSE;
3936
3937                 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3938                      (pAd->MlmeAux.Channel > 14) &&
3939                      RadarChannelCheck(pAd, pInBss->Channel))
3940                     ) {
3941                         if (pInBss->Hidden)
3942                                 bIsHiddenApIncluded = TRUE;
3943                 }
3944
3945                 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3946                     (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen)
3947                      || bIsHiddenApIncluded)) {
3948                         struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3949
3950                         /* 2.4G/5G N only mode */
3951                         if ((pInBss->HtCapabilityLen == 0) &&
3952                             ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
3953                              || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
3954                                 DBGPRINT(RT_DEBUG_TRACE,
3955                                          ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3956                                 continue;
3957                         }
3958                         /* New for WPA2 */
3959                         /* Check the Authmode first */
3960                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
3961                                 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
3962                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
3963                                     && (pAd->StaCfg.AuthMode !=
3964                                         pInBss->AuthModeAux))
3965                                         /* None matched */
3966                                         continue;
3967
3968                                 /* Check cipher suite, AP must have more secured cipher than station setting */
3969                                 if ((pAd->StaCfg.AuthMode ==
3970                                      Ndis802_11AuthModeWPA)
3971                                     || (pAd->StaCfg.AuthMode ==
3972                                         Ndis802_11AuthModeWPAPSK)) {
3973                                         /* If it's not mixed mode, we should only let BSS pass with the same encryption */
3974                                         if (pInBss->WPA.bMixMode == FALSE)
3975                                                 if (pAd->StaCfg.WepStatus !=
3976                                                     pInBss->WPA.GroupCipher)
3977                                                         continue;
3978
3979                                         /* check group cipher */
3980                                         if ((pAd->StaCfg.WepStatus <
3981                                              pInBss->WPA.GroupCipher)
3982                                             && (pInBss->WPA.GroupCipher !=
3983                                                 Ndis802_11GroupWEP40Enabled)
3984                                             && (pInBss->WPA.GroupCipher !=
3985                                                 Ndis802_11GroupWEP104Enabled))
3986                                                 continue;
3987
3988                                         /* check pairwise cipher, skip if none matched */
3989                                         /* If profile set to AES, let it pass without question. */
3990                                         /* If profile set to TKIP, we must find one mateched */
3991                                         if ((pAd->StaCfg.WepStatus ==
3992                                              Ndis802_11Encryption2Enabled)
3993                                             && (pAd->StaCfg.WepStatus !=
3994                                                 pInBss->WPA.PairCipher)
3995                                             && (pAd->StaCfg.WepStatus !=
3996                                                 pInBss->WPA.PairCipherAux))
3997                                                 continue;
3998                                 } else
3999                                     if ((pAd->StaCfg.AuthMode ==
4000                                          Ndis802_11AuthModeWPA2)
4001                                         || (pAd->StaCfg.AuthMode ==
4002                                             Ndis802_11AuthModeWPA2PSK)) {
4003                                         /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4004                                         if (pInBss->WPA2.bMixMode == FALSE)
4005                                                 if (pAd->StaCfg.WepStatus !=
4006                                                     pInBss->WPA2.GroupCipher)
4007                                                         continue;
4008
4009                                         /* check group cipher */
4010                                         if ((pAd->StaCfg.WepStatus <
4011                                              pInBss->WPA.GroupCipher)
4012                                             && (pInBss->WPA2.GroupCipher !=
4013                                                 Ndis802_11GroupWEP40Enabled)
4014                                             && (pInBss->WPA2.GroupCipher !=
4015                                                 Ndis802_11GroupWEP104Enabled))
4016                                                 continue;
4017
4018                                         /* check pairwise cipher, skip if none matched */
4019                                         /* If profile set to AES, let it pass without question. */
4020                                         /* If profile set to TKIP, we must find one mateched */
4021                                         if ((pAd->StaCfg.WepStatus ==
4022                                              Ndis802_11Encryption2Enabled)
4023                                             && (pAd->StaCfg.WepStatus !=
4024                                                 pInBss->WPA2.PairCipher)
4025                                             && (pAd->StaCfg.WepStatus !=
4026                                                 pInBss->WPA2.PairCipherAux))
4027                                                 continue;
4028                                 }
4029                         }
4030                         /* Bss Type matched, SSID matched. */
4031                         /* We will check wepstatus for qualification Bss */
4032                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) {
4033                                 DBGPRINT(RT_DEBUG_TRACE,
4034                                          ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4035                                           pAd->StaCfg.WepStatus,
4036                                           pInBss->WepStatus));
4037                                 /* */
4038                                 /* For the SESv2 case, we will not qualify WepStatus. */
4039                                 /* */
4040                                 if (!pInBss->bSES)
4041                                         continue;
4042                         }
4043                         /* Since the AP is using hidden SSID, and we are trying to connect to ANY */
4044                         /* It definitely will fail. So, skip it. */
4045                         /* CCX also require not even try to connect it! */
4046                         if (SsidLen == 0)
4047                                 continue;
4048
4049                         /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4050                         /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4051                         if ((pInBss->CentralChannel != pInBss->Channel) &&
4052                             (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4053                              BW_40)) {
4054                                 if (RTMPCheckChannel
4055                                     (pAd, pInBss->CentralChannel,
4056                                      pInBss->Channel) == FALSE) {
4057                                         pAd->CommonCfg.RegTransmitSetting.field.
4058                                             BW = BW_20;
4059                                         SetCommonHT(pAd);
4060                                         pAd->CommonCfg.RegTransmitSetting.field.
4061                                             BW = BW_40;
4062                                 } else {
4063                                         if (pAd->CommonCfg.DesiredHtPhy.
4064                                             ChannelWidth == BAND_WIDTH_20) {
4065                                                 SetCommonHT(pAd);
4066                                         }
4067                                 }
4068                         }
4069                         /* copy matching BSS from InTab to OutTab */
4070                         NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
4071
4072                         OutTab->BssNr++;
4073                 } else if ((pInBss->BssType == pAd->StaCfg.BssType)
4074                            && (SsidLen == 0)) {
4075                         struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4076
4077                         /* 2.4G/5G N only mode */
4078                         if ((pInBss->HtCapabilityLen == 0) &&
4079                             ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
4080                              || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
4081                                 DBGPRINT(RT_DEBUG_TRACE,
4082                                          ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4083                                 continue;
4084                         }
4085                         /* New for WPA2 */
4086                         /* Check the Authmode first */
4087                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
4088                                 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
4089                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
4090                                     && (pAd->StaCfg.AuthMode !=
4091                                         pInBss->AuthModeAux))
4092                                         /* None matched */
4093                                         continue;
4094
4095                                 /* Check cipher suite, AP must have more secured cipher than station setting */
4096                                 if ((pAd->StaCfg.AuthMode ==
4097                                      Ndis802_11AuthModeWPA)
4098                                     || (pAd->StaCfg.AuthMode ==
4099                                         Ndis802_11AuthModeWPAPSK)) {
4100                                         /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4101                                         if (pInBss->WPA.bMixMode == FALSE)
4102                                                 if (pAd->StaCfg.WepStatus !=
4103                                                     pInBss->WPA.GroupCipher)
4104                                                         continue;
4105
4106                                         /* check group cipher */
4107                                         if (pAd->StaCfg.WepStatus <
4108                                             pInBss->WPA.GroupCipher)
4109                                                 continue;
4110
4111                                         /* check pairwise cipher, skip if none matched */
4112                                         /* If profile set to AES, let it pass without question. */
4113                                         /* If profile set to TKIP, we must find one mateched */
4114                                         if ((pAd->StaCfg.WepStatus ==
4115                                              Ndis802_11Encryption2Enabled)
4116                                             && (pAd->StaCfg.WepStatus !=
4117                                                 pInBss->WPA.PairCipher)
4118                                             && (pAd->StaCfg.WepStatus !=
4119                                                 pInBss->WPA.PairCipherAux))
4120                                                 continue;
4121                                 } else
4122                                     if ((pAd->StaCfg.AuthMode ==
4123                                          Ndis802_11AuthModeWPA2)
4124                                         || (pAd->StaCfg.AuthMode ==
4125                                             Ndis802_11AuthModeWPA2PSK)) {
4126                                         /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4127                                         if (pInBss->WPA2.bMixMode == FALSE)
4128                                                 if (pAd->StaCfg.WepStatus !=
4129                                                     pInBss->WPA2.GroupCipher)
4130                                                         continue;
4131
4132                                         /* check group cipher */
4133                                         if (pAd->StaCfg.WepStatus <
4134                                             pInBss->WPA2.GroupCipher)
4135                                                 continue;
4136
4137                                         /* check pairwise cipher, skip if none matched */
4138                                         /* If profile set to AES, let it pass without question. */
4139                                         /* If profile set to TKIP, we must find one mateched */
4140                                         if ((pAd->StaCfg.WepStatus ==
4141                                              Ndis802_11Encryption2Enabled)
4142                                             && (pAd->StaCfg.WepStatus !=
4143                                                 pInBss->WPA2.PairCipher)
4144                                             && (pAd->StaCfg.WepStatus !=
4145                                                 pInBss->WPA2.PairCipherAux))
4146                                                 continue;
4147                                 }
4148                         }
4149                         /* Bss Type matched, SSID matched. */
4150                         /* We will check wepstatus for qualification Bss */
4151                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4152                                 continue;
4153
4154                         /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4155                         /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4156                         if ((pInBss->CentralChannel != pInBss->Channel) &&
4157                             (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4158                              BW_40)) {
4159                                 if (RTMPCheckChannel
4160                                     (pAd, pInBss->CentralChannel,
4161                                      pInBss->Channel) == FALSE) {
4162                                         pAd->CommonCfg.RegTransmitSetting.field.
4163                                             BW = BW_20;
4164                                         SetCommonHT(pAd);
4165                                         pAd->CommonCfg.RegTransmitSetting.field.
4166                                             BW = BW_40;
4167                                 }
4168                         }
4169                         /* copy matching BSS from InTab to OutTab */
4170                         NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
4171
4172                         OutTab->BssNr++;
4173                 }
4174
4175                 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4176                         break;
4177         }
4178
4179         BssTableSortByRssi(OutTab);
4180 }
4181
4182 /* IRQL = DISPATCH_LEVEL */
4183 void BssTableSortByRssi(struct rt_bss_table *OutTab)
4184 {
4185         int i, j;
4186         struct rt_bss_entry TmpBss;
4187
4188         for (i = 0; i < OutTab->BssNr - 1; i++) {
4189                 for (j = i + 1; j < OutTab->BssNr; j++) {
4190                         if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) {
4191                                 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j],
4192                                                sizeof(struct rt_bss_entry));
4193                                 NdisMoveMemory(&OutTab->BssEntry[j],
4194                                                &OutTab->BssEntry[i],
4195                                                sizeof(struct rt_bss_entry));
4196                                 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss,
4197                                                sizeof(struct rt_bss_entry));
4198                         }
4199                 }
4200         }
4201 }
4202
4203 void BssCipherParse(struct rt_bss_entry *pBss)
4204 {
4205         struct rt_eid * pEid;
4206         u8 *pTmp;
4207         struct rt_rsn_ie_header * pRsnHeader;
4208         struct rt_cipher_suite_struct * pCipher;
4209         struct rt_akm_suite * pAKM;
4210         u16 Count;
4211         int Length;
4212         NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4213
4214         /* */
4215         /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */
4216         /* */
4217         if (pBss->Privacy) {
4218                 pBss->WepStatus = Ndis802_11WEPEnabled;
4219         } else {
4220                 pBss->WepStatus = Ndis802_11WEPDisabled;
4221         }
4222         /* Set default to disable & open authentication before parsing variable IE */
4223         pBss->AuthMode = Ndis802_11AuthModeOpen;
4224         pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4225
4226         /* Init WPA setting */
4227         pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4228         pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4229         pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4230         pBss->WPA.RsnCapability = 0;
4231         pBss->WPA.bMixMode = FALSE;
4232
4233         /* Init WPA2 setting */
4234         pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4235         pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4236         pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4237         pBss->WPA2.RsnCapability = 0;
4238         pBss->WPA2.bMixMode = FALSE;
4239
4240         Length = (int)pBss->VarIELen;
4241
4242         while (Length > 0) {
4243                 /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */
4244                 pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length;
4245                 pEid = (struct rt_eid *) pTmp;
4246                 switch (pEid->Eid) {
4247                 case IE_WPA:
4248                         if (NdisEqualMemory(pEid->Octet, SES_OUI, 3)
4249                             && (pEid->Len == 7)) {
4250                                 pBss->bSES = TRUE;
4251                                 break;
4252                         } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) !=
4253                                    1) {
4254                                 /* if unsupported vendor specific IE */
4255                                 break;
4256                         }
4257                         /* Skip OUI, version, and multicast suite */
4258                         /* This part should be improved in the future when AP supported multiple cipher suite. */
4259                         /* For now, it's OK since almost all APs have fixed cipher suite supported. */
4260                         /* pTmp = (u8 *)pEid->Octet; */
4261                         pTmp += 11;
4262
4263                         /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
4264                         /*      Value      Meaning */
4265                         /*      0                       None */
4266                         /*      1                       WEP-40 */
4267                         /*      2                       Tkip */
4268                         /*      3                       WRAP */
4269                         /*      4                       AES */
4270                         /*      5                       WEP-104 */
4271                         /* Parse group cipher */
4272                         switch (*pTmp) {
4273                         case 1:
4274                                 pBss->WPA.GroupCipher =
4275                                     Ndis802_11GroupWEP40Enabled;
4276                                 break;
4277                         case 5:
4278                                 pBss->WPA.GroupCipher =
4279                                     Ndis802_11GroupWEP104Enabled;
4280                                 break;
4281                         case 2:
4282                                 pBss->WPA.GroupCipher =
4283                                     Ndis802_11Encryption2Enabled;
4284                                 break;
4285                         case 4:
4286                                 pBss->WPA.GroupCipher =
4287                                     Ndis802_11Encryption3Enabled;
4288                                 break;
4289                         default:
4290                                 break;
4291                         }
4292                         /* number of unicast suite */
4293                         pTmp += 1;
4294
4295                         /* skip all unicast cipher suites */
4296                         /*Count = *(u16 *)pTmp; */
4297                         Count = (pTmp[1] << 8) + pTmp[0];
4298                         pTmp += sizeof(u16);
4299
4300                         /* Parsing all unicast cipher suite */
4301                         while (Count > 0) {
4302                                 /* Skip OUI */
4303                                 pTmp += 3;
4304                                 TmpCipher = Ndis802_11WEPDisabled;
4305                                 switch (*pTmp) {
4306                                 case 1:
4307                                 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4308                                         TmpCipher =
4309                                             Ndis802_11Encryption1Enabled;
4310                                         break;
4311                                 case 2:
4312                                         TmpCipher =
4313                                             Ndis802_11Encryption2Enabled;
4314                                         break;
4315                                 case 4:
4316                                         TmpCipher =
4317                                             Ndis802_11Encryption3Enabled;
4318                                         break;
4319                                 default:
4320                                         break;
4321                                 }
4322                                 if (TmpCipher > pBss->WPA.PairCipher) {
4323                                         /* Move the lower cipher suite to PairCipherAux */
4324                                         pBss->WPA.PairCipherAux =
4325                                             pBss->WPA.PairCipher;
4326                                         pBss->WPA.PairCipher = TmpCipher;
4327                                 } else {
4328                                         pBss->WPA.PairCipherAux = TmpCipher;
4329                                 }
4330                                 pTmp++;
4331                                 Count--;
4332                         }
4333
4334                         /* 4. get AKM suite counts */
4335                         /*Count = *(u16 *)pTmp; */
4336                         Count = (pTmp[1] << 8) + pTmp[0];
4337                         pTmp += sizeof(u16);
4338                         pTmp += 3;
4339
4340                         switch (*pTmp) {
4341                         case 1:
4342                                 /* Set AP support WPA-enterprise mode */
4343                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4344                                         pBss->AuthMode = Ndis802_11AuthModeWPA;
4345                                 else
4346                                         pBss->AuthModeAux =
4347                                             Ndis802_11AuthModeWPA;
4348                                 break;
4349                         case 2:
4350                                 /* Set AP support WPA-PSK mode */
4351                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4352                                         pBss->AuthMode =
4353                                             Ndis802_11AuthModeWPAPSK;
4354                                 else
4355                                         pBss->AuthModeAux =
4356                                             Ndis802_11AuthModeWPAPSK;
4357                                 break;
4358                         default:
4359                                 break;
4360                         }
4361                         pTmp += 1;
4362
4363                         /* Fixed for WPA-None */
4364                         if (pBss->BssType == BSS_ADHOC) {
4365                                 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4366                                 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4367                                 pBss->WepStatus = pBss->WPA.GroupCipher;
4368                                 /* Patched bugs for old driver */
4369                                 if (pBss->WPA.PairCipherAux ==
4370                                     Ndis802_11WEPDisabled)
4371                                         pBss->WPA.PairCipherAux =
4372                                             pBss->WPA.GroupCipher;
4373                         } else
4374                                 pBss->WepStatus = pBss->WPA.PairCipher;
4375
4376                         /* Check the Pair & Group, if different, turn on mixed mode flag */
4377                         if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4378                                 pBss->WPA.bMixMode = TRUE;
4379
4380                         break;
4381
4382                 case IE_RSN:
4383                         pRsnHeader = (struct rt_rsn_ie_header *) pTmp;
4384
4385                         /* 0. Version must be 1 */
4386                         if (le2cpu16(pRsnHeader->Version) != 1)
4387                                 break;
4388                         pTmp += sizeof(struct rt_rsn_ie_header);
4389
4390                         /* 1. Check group cipher */
4391                         pCipher = (struct rt_cipher_suite_struct *) pTmp;
4392                         if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4393                                 break;
4394
4395                         /* Parse group cipher */
4396                         switch (pCipher->Type) {
4397                         case 1:
4398                                 pBss->WPA2.GroupCipher =
4399                                     Ndis802_11GroupWEP40Enabled;
4400                                 break;
4401                         case 5:
4402                                 pBss->WPA2.GroupCipher =
4403                                     Ndis802_11GroupWEP104Enabled;
4404                                 break;
4405                         case 2:
4406                                 pBss->WPA2.GroupCipher =
4407                                     Ndis802_11Encryption2Enabled;
4408                                 break;
4409                         case 4:
4410                                 pBss->WPA2.GroupCipher =
4411                                     Ndis802_11Encryption3Enabled;
4412                                 break;
4413                         default:
4414                                 break;
4415                         }
4416                         /* set to correct offset for next parsing */
4417                         pTmp += sizeof(struct rt_cipher_suite_struct);
4418
4419                         /* 2. Get pairwise cipher counts */
4420                         /*Count = *(u16 *)pTmp; */
4421                         Count = (pTmp[1] << 8) + pTmp[0];
4422                         pTmp += sizeof(u16);
4423
4424                         /* 3. Get pairwise cipher */
4425                         /* Parsing all unicast cipher suite */
4426                         while (Count > 0) {
4427                                 /* Skip OUI */
4428                                 pCipher = (struct rt_cipher_suite_struct *) pTmp;
4429                                 TmpCipher = Ndis802_11WEPDisabled;
4430                                 switch (pCipher->Type) {
4431                                 case 1:
4432                                 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4433                                         TmpCipher =
4434                                             Ndis802_11Encryption1Enabled;
4435                                         break;
4436                                 case 2:
4437                                         TmpCipher =
4438                                             Ndis802_11Encryption2Enabled;
4439                                         break;
4440                                 case 4:
4441                                         TmpCipher =
4442                                             Ndis802_11Encryption3Enabled;
4443                                         break;
4444                                 default:
4445                                         break;
4446                                 }
4447                                 if (TmpCipher > pBss->WPA2.PairCipher) {
4448                                         /* Move the lower cipher suite to PairCipherAux */
4449                                         pBss->WPA2.PairCipherAux =
4450                                             pBss->WPA2.PairCipher;
4451                                         pBss->WPA2.PairCipher = TmpCipher;
4452                                 } else {
4453                                         pBss->WPA2.PairCipherAux = TmpCipher;
4454                                 }
4455                                 pTmp += sizeof(struct rt_cipher_suite_struct);
4456                                 Count--;
4457                         }
4458
4459                         /* 4. get AKM suite counts */
4460                         /*Count = *(u16 *)pTmp; */
4461                         Count = (pTmp[1] << 8) + pTmp[0];
4462                         pTmp += sizeof(u16);
4463
4464                         /* 5. Get AKM ciphers */
4465                         /* Parsing all AKM ciphers */
4466                         while (Count > 0) {
4467                                 pAKM = (struct rt_akm_suite *) pTmp;
4468                                 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4469                                         break;
4470
4471                                 switch (pAKM->Type) {
4472                                 case 1:
4473                                         /* Set AP support WPA-enterprise mode */
4474                                         if (pBss->AuthMode ==
4475                                             Ndis802_11AuthModeOpen)
4476                                                 pBss->AuthMode =
4477                                                     Ndis802_11AuthModeWPA2;
4478                                         else
4479                                                 pBss->AuthModeAux =
4480                                                     Ndis802_11AuthModeWPA2;
4481                                         break;
4482                                 case 2:
4483                                         /* Set AP support WPA-PSK mode */
4484                                         if (pBss->AuthMode ==
4485                                             Ndis802_11AuthModeOpen)
4486                                                 pBss->AuthMode =
4487                                                     Ndis802_11AuthModeWPA2PSK;
4488                                         else
4489                                                 pBss->AuthModeAux =
4490                                                     Ndis802_11AuthModeWPA2PSK;
4491                                         break;
4492                                 default:
4493                                         if (pBss->AuthMode ==
4494                                             Ndis802_11AuthModeOpen)
4495                                                 pBss->AuthMode =
4496                                                     Ndis802_11AuthModeMax;
4497                                         else
4498                                                 pBss->AuthModeAux =
4499                                                     Ndis802_11AuthModeMax;
4500                                         break;
4501                                 }
4502                                 pTmp += (Count * sizeof(struct rt_akm_suite));
4503                                 Count--;
4504                         }
4505
4506                         /* Fixed for WPA-None */
4507                         if (pBss->BssType == BSS_ADHOC) {
4508                                 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4509                                 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4510                                 pBss->WPA.PairCipherAux =
4511                                     pBss->WPA2.PairCipherAux;
4512                                 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4513                                 pBss->WepStatus = pBss->WPA.GroupCipher;
4514                                 /* Patched bugs for old driver */
4515                                 if (pBss->WPA.PairCipherAux ==
4516                                     Ndis802_11WEPDisabled)
4517                                         pBss->WPA.PairCipherAux =
4518                                             pBss->WPA.GroupCipher;
4519                         }
4520                         pBss->WepStatus = pBss->WPA2.PairCipher;
4521
4522                         /* 6. Get RSN capability */
4523                         /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */
4524                         pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0];
4525                         pTmp += sizeof(u16);
4526
4527                         /* Check the Pair & Group, if different, turn on mixed mode flag */
4528                         if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4529                                 pBss->WPA2.bMixMode = TRUE;
4530
4531                         break;
4532                 default:
4533                         break;
4534                 }
4535                 Length -= (pEid->Len + 2);
4536         }
4537 }
4538
4539 /* =========================================================================================== */
4540 /* mac_table.c */
4541 /* =========================================================================================== */
4542
4543 /*! \brief generates a random mac address value for IBSS BSSID
4544  *      \param Addr the bssid location
4545  *      \return none
4546  *      \pre
4547  *      \post
4548  */
4549 void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr)
4550 {
4551         int i;
4552
4553         for (i = 0; i < MAC_ADDR_LEN; i++) {
4554                 pAddr[i] = RandomByte(pAd);
4555         }
4556
4557         pAddr[0] = (pAddr[0] & 0xfe) | 0x02;    /* the first 2 bits must be 01xxxxxxxx */
4558 }
4559
4560 /*! \brief init the management mac frame header
4561  *      \param p_hdr mac header
4562  *      \param subtype subtype of the frame
4563  *      \param p_ds destination address, don't care if it is a broadcast address
4564  *      \return none
4565  *      \pre the station has the following information in the pAd->StaCfg
4566  *       - bssid
4567  *       - station address
4568  *      \post
4569  *      \note this function initializes the following field
4570
4571         IRQL = PASSIVE_LEVEL
4572         IRQL = DISPATCH_LEVEL
4573
4574  */
4575 void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd,
4576                       struct rt_header_802_11 * pHdr80211,
4577                       u8 SubType,
4578                       u8 ToDs, u8 *pDA, u8 *pBssid)
4579 {
4580         NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
4581
4582         pHdr80211->FC.Type = BTYPE_MGMT;
4583         pHdr80211->FC.SubType = SubType;
4584 /*      if (SubType == SUBTYPE_ACK)     // sample, no use, it will conflict with ACTION frame sub type */
4585 /*              pHdr80211->FC.Type = BTYPE_CNTL; */
4586         pHdr80211->FC.ToDs = ToDs;
4587         COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4588         COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4589         COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4590 }
4591
4592 /* =========================================================================================== */
4593 /* mem_mgmt.c */
4594 /* =========================================================================================== */
4595
4596 /*!***************************************************************************
4597  * This routine build an outgoing frame, and fill all information specified
4598  * in argument list to the frame body. The actual frame size is the summation
4599  * of all arguments.
4600  * input params:
4601  *              Buffer - pointer to a pre-allocated memory segment
4602  *              args - a list of <int arg_size, arg> pairs.
4603  *              NOTE NOTE NOTE! the last argument must be NULL, otherwise this
4604  *                                                 function will FAIL!
4605  * return:
4606  *              Size of the buffer
4607  * usage:
4608  *              MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4609
4610  IRQL = PASSIVE_LEVEL
4611         IRQL = DISPATCH_LEVEL
4612
4613  ****************************************************************************/
4614 unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...)
4615 {
4616         u8 *p;
4617         int leng;
4618         unsigned long TotLeng;
4619         va_list Args;
4620
4621         /* calculates the total length */
4622         TotLeng = 0;
4623         va_start(Args, FrameLen);
4624         do {
4625                 leng = va_arg(Args, int);
4626                 if (leng == END_OF_ARGS) {
4627                         break;
4628                 }
4629                 p = va_arg(Args, void *);
4630                 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4631                 TotLeng = TotLeng + leng;
4632         } while (TRUE);
4633
4634         va_end(Args);           /* clean up */
4635         *FrameLen = TotLeng;
4636         return TotLeng;
4637 }
4638
4639 /* =========================================================================================== */
4640 /* mlme_queue.c */
4641 /* =========================================================================================== */
4642
4643 /*! \brief      Initialize The MLME Queue, used by MLME Functions
4644  *      \param  *Queue     The MLME Queue
4645  *      \return Always     Return NDIS_STATE_SUCCESS in this implementation
4646  *      \pre
4647  *      \post
4648  *      \note   Because this is done only once (at the init stage), no need to be locked
4649
4650  IRQL = PASSIVE_LEVEL
4651
4652  */
4653 int MlmeQueueInit(struct rt_mlme_queue *Queue)
4654 {
4655         int i;
4656
4657         NdisAllocateSpinLock(&Queue->Lock);
4658
4659         Queue->Num = 0;
4660         Queue->Head = 0;
4661         Queue->Tail = 0;
4662
4663         for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) {
4664                 Queue->Entry[i].Occupied = FALSE;
4665                 Queue->Entry[i].MsgLen = 0;
4666                 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4667         }
4668
4669         return NDIS_STATUS_SUCCESS;
4670 }
4671
4672 /*! \brief       Enqueue a message for other threads, if they want to send messages to MLME thread
4673  *      \param  *Queue    The MLME Queue
4674  *      \param   Machine  The State Machine Id
4675  *      \param   MsgType  The Message Type
4676  *      \param   MsgLen   The Message length
4677  *      \param  *Msg      The message pointer
4678  *      \return  TRUE if enqueue is successful, FALSE if the queue is full
4679  *      \pre
4680  *      \post
4681  *      \note    The message has to be initialized
4682
4683         IRQL = PASSIVE_LEVEL
4684         IRQL = DISPATCH_LEVEL
4685
4686  */
4687 BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd,
4688                     unsigned long Machine,
4689                     unsigned long MsgType, unsigned long MsgLen, void * Msg)
4690 {
4691         int Tail;
4692         struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
4693
4694         /* Do nothing if the driver is starting halt state. */
4695         /* This might happen when timer already been fired before cancel timer with mlmehalt */
4696         if (RTMP_TEST_FLAG
4697             (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4698                 return FALSE;
4699
4700         /* First check the size, it MUST not exceed the mlme queue size */
4701         if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4702                 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n",
4703                               MsgLen));
4704                 return FALSE;
4705         }
4706
4707         if (MlmeQueueFull(Queue)) {
4708                 return FALSE;
4709         }
4710
4711         NdisAcquireSpinLock(&(Queue->Lock));
4712         Tail = Queue->Tail;
4713         Queue->Tail++;
4714         Queue->Num++;
4715         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
4716                 Queue->Tail = 0;
4717         }
4718
4719         Queue->Entry[Tail].Wcid = RESERVED_WCID;
4720         Queue->Entry[Tail].Occupied = TRUE;
4721         Queue->Entry[Tail].Machine = Machine;
4722         Queue->Entry[Tail].MsgType = MsgType;
4723         Queue->Entry[Tail].MsgLen = MsgLen;
4724
4725         if (Msg != NULL) {
4726                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4727         }
4728
4729         NdisReleaseSpinLock(&(Queue->Lock));
4730         return TRUE;
4731 }
4732
4733 /*! \brief       This function is used when Recv gets a MLME message
4734  *      \param  *Queue                   The MLME Queue
4735  *      \param   TimeStampHigh   The upper 32 bit of timestamp
4736  *      \param   TimeStampLow    The lower 32 bit of timestamp
4737  *      \param   Rssi                    The receiving RSSI strength
4738  *      \param   MsgLen                  The length of the message
4739  *      \param  *Msg                     The message pointer
4740  *      \return  TRUE if everything ok, FALSE otherwise (like Queue Full)
4741  *      \pre
4742  *      \post
4743
4744  IRQL = DISPATCH_LEVEL
4745
4746  */
4747 BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd,
4748                            unsigned long Wcid,
4749                            unsigned long TimeStampHigh,
4750                            unsigned long TimeStampLow,
4751                            u8 Rssi0,
4752                            u8 Rssi1,
4753                            u8 Rssi2,
4754                            unsigned long MsgLen, void * Msg, u8 Signal)
4755 {
4756         int Tail, Machine;
4757         struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg;
4758         int MsgType;
4759         struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
4760
4761         /* Do nothing if the driver is starting halt state. */
4762         /* This might happen when timer already been fired before cancel timer with mlmehalt */
4763         if (RTMP_TEST_FLAG
4764             (pAd,
4765              fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) {
4766                 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4767                 return FALSE;
4768         }
4769         /* First check the size, it MUST not exceed the mlme queue size */
4770         if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4771                 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4772                 return FALSE;
4773         }
4774
4775         if (MlmeQueueFull(Queue)) {
4776                 return FALSE;
4777         }
4778
4779         {
4780                 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) {
4781                         DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType));
4782                         return FALSE;
4783                 }
4784         }
4785
4786         /* OK, we got all the informations, it is time to put things into queue */
4787         NdisAcquireSpinLock(&(Queue->Lock));
4788         Tail = Queue->Tail;
4789         Queue->Tail++;
4790         Queue->Num++;
4791         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
4792                 Queue->Tail = 0;
4793         }
4794         Queue->Entry[Tail].Occupied = TRUE;
4795         Queue->Entry[Tail].Machine = Machine;
4796         Queue->Entry[Tail].MsgType = MsgType;
4797         Queue->Entry[Tail].MsgLen = MsgLen;
4798         Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4799         Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4800         Queue->Entry[Tail].Rssi0 = Rssi0;
4801         Queue->Entry[Tail].Rssi1 = Rssi1;
4802         Queue->Entry[Tail].Rssi2 = Rssi2;
4803         Queue->Entry[Tail].Signal = Signal;
4804         Queue->Entry[Tail].Wcid = (u8)Wcid;
4805
4806         Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4807
4808         if (Msg != NULL) {
4809                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4810         }
4811
4812         NdisReleaseSpinLock(&(Queue->Lock));
4813
4814         RTMP_MLME_HANDLER(pAd);
4815
4816         return TRUE;
4817 }
4818
4819 /*! \brief       Dequeue a message from the MLME Queue
4820  *      \param  *Queue    The MLME Queue
4821  *      \param  *Elem     The message dequeued from MLME Queue
4822  *      \return  TRUE if the Elem contains something, FALSE otherwise
4823  *      \pre
4824  *      \post
4825
4826  IRQL = DISPATCH_LEVEL
4827
4828  */
4829 BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem)
4830 {
4831         NdisAcquireSpinLock(&(Queue->Lock));
4832         *Elem = &(Queue->Entry[Queue->Head]);
4833         Queue->Num--;
4834         Queue->Head++;
4835         if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) {
4836                 Queue->Head = 0;
4837         }
4838         NdisReleaseSpinLock(&(Queue->Lock));
4839         return TRUE;
4840 }
4841
4842 /* IRQL = DISPATCH_LEVEL */
4843 void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd)
4844 {
4845 #ifdef RTMP_MAC_PCI
4846         struct rt_mlme_queue_elem *Elem = NULL;
4847 #endif /* RTMP_MAC_PCI // */
4848         BOOLEAN Cancelled;
4849
4850         DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4851
4852 #ifdef RTMP_MAC_PCI
4853         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4854         if (pAd->Mlme.bRunning) {
4855                 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4856                 return;
4857         } else {
4858                 pAd->Mlme.bRunning = TRUE;
4859         }
4860         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4861
4862         /* Remove all Mlme queues elements */
4863         while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
4864                 /*From message type, determine which state machine I should drive */
4865                 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
4866                         /* free MLME element */
4867                         Elem->Occupied = FALSE;
4868                         Elem->MsgLen = 0;
4869
4870                 } else {
4871                         DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4872                 }
4873         }
4874 #endif /* RTMP_MAC_PCI // */
4875
4876         {
4877                 /* Cancel all timer events */
4878                 /* Be careful to cancel new added timer */
4879                 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4880                 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4881                 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4882                 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4883                 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4884                 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4885
4886         }
4887
4888         /* Change back to original channel in case of doing scan */
4889         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4890         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4891
4892         /* Resume MSDU which is turned off durning scan */
4893         RTMPResumeMsduTransmission(pAd);
4894
4895         {
4896                 /* Set all state machines back IDLE */
4897                 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4898                 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4899                 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4900                 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4901                 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4902                 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4903         }
4904
4905 #ifdef RTMP_MAC_PCI
4906         /* Remove running state */
4907         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4908         pAd->Mlme.bRunning = FALSE;
4909         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4910 #endif /* RTMP_MAC_PCI // */
4911 }
4912
4913 /*! \brief      test if the MLME Queue is empty
4914  *      \param  *Queue    The MLME Queue
4915  *      \return TRUE if the Queue is empty, FALSE otherwise
4916  *      \pre
4917  *      \post
4918
4919  IRQL = DISPATCH_LEVEL
4920
4921  */
4922 BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue)
4923 {
4924         BOOLEAN Ans;
4925
4926         NdisAcquireSpinLock(&(Queue->Lock));
4927         Ans = (Queue->Num == 0);
4928         NdisReleaseSpinLock(&(Queue->Lock));
4929
4930         return Ans;
4931 }
4932
4933 /*! \brief       test if the MLME Queue is full
4934  *      \param   *Queue          The MLME Queue
4935  *      \return  TRUE if the Queue is empty, FALSE otherwise
4936  *      \pre
4937  *      \post
4938
4939  IRQL = PASSIVE_LEVEL
4940  IRQL = DISPATCH_LEVEL
4941
4942  */
4943 BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue)
4944 {
4945         BOOLEAN Ans;
4946
4947         NdisAcquireSpinLock(&(Queue->Lock));
4948         Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE
4949                || Queue->Entry[Queue->Tail].Occupied);
4950         NdisReleaseSpinLock(&(Queue->Lock));
4951
4952         return Ans;
4953 }
4954
4955 /*! \brief       The destructor of MLME Queue
4956  *      \param
4957  *      \return
4958  *      \pre
4959  *      \post
4960  *      \note   Clear Mlme Queue, Set Queue->Num to Zero.
4961
4962  IRQL = PASSIVE_LEVEL
4963
4964  */
4965 void MlmeQueueDestroy(struct rt_mlme_queue *pQueue)
4966 {
4967         NdisAcquireSpinLock(&(pQueue->Lock));
4968         pQueue->Num = 0;
4969         pQueue->Head = 0;
4970         pQueue->Tail = 0;
4971         NdisReleaseSpinLock(&(pQueue->Lock));
4972         NdisFreeSpinLock(&(pQueue->Lock));
4973 }
4974
4975 /*! \brief       To substitute the message type if the message is coming from external
4976  *      \param  pFrame             The frame received
4977  *      \param  *Machine           The state machine
4978  *      \param  *MsgType           the message type for the state machine
4979  *      \return TRUE if the substitution is successful, FALSE otherwise
4980  *      \pre
4981  *      \post
4982
4983  IRQL = DISPATCH_LEVEL
4984
4985  */
4986 BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd,
4987                      struct rt_frame_802_11 * pFrame,
4988                      int * Machine, int * MsgType)
4989 {
4990         u16 Seq, Alg;
4991         u8 EAPType;
4992         u8 *pData;
4993
4994         /* Pointer to start of data frames including SNAP header */
4995         pData = (u8 *)pFrame + LENGTH_802_11;
4996
4997         /* The only data type will pass to this function is EAPOL frame */
4998         if (pFrame->Hdr.FC.Type == BTYPE_DATA) {
4999                 {
5000                         *Machine = WPA_STATE_MACHINE;
5001                         EAPType =
5002                             *((u8 *) pFrame + LENGTH_802_11 +
5003                               LENGTH_802_1_H + 1);
5004                         return (WpaMsgTypeSubst(EAPType, (int *) MsgType));
5005                 }
5006         }
5007
5008         switch (pFrame->Hdr.FC.SubType) {
5009         case SUBTYPE_ASSOC_REQ:
5010                 *Machine = ASSOC_STATE_MACHINE;
5011                 *MsgType = MT2_PEER_ASSOC_REQ;
5012                 break;
5013         case SUBTYPE_ASSOC_RSP:
5014                 *Machine = ASSOC_STATE_MACHINE;
5015                 *MsgType = MT2_PEER_ASSOC_RSP;
5016                 break;
5017         case SUBTYPE_REASSOC_REQ:
5018                 *Machine = ASSOC_STATE_MACHINE;
5019                 *MsgType = MT2_PEER_REASSOC_REQ;
5020                 break;
5021         case SUBTYPE_REASSOC_RSP:
5022                 *Machine = ASSOC_STATE_MACHINE;
5023                 *MsgType = MT2_PEER_REASSOC_RSP;
5024                 break;
5025         case SUBTYPE_PROBE_REQ:
5026                 *Machine = SYNC_STATE_MACHINE;
5027                 *MsgType = MT2_PEER_PROBE_REQ;
5028                 break;
5029         case SUBTYPE_PROBE_RSP:
5030                 *Machine = SYNC_STATE_MACHINE;
5031                 *MsgType = MT2_PEER_PROBE_RSP;
5032                 break;
5033         case SUBTYPE_BEACON:
5034                 *Machine = SYNC_STATE_MACHINE;
5035                 *MsgType = MT2_PEER_BEACON;
5036                 break;
5037         case SUBTYPE_ATIM:
5038                 *Machine = SYNC_STATE_MACHINE;
5039                 *MsgType = MT2_PEER_ATIM;
5040                 break;
5041         case SUBTYPE_DISASSOC:
5042                 *Machine = ASSOC_STATE_MACHINE;
5043                 *MsgType = MT2_PEER_DISASSOC_REQ;
5044                 break;
5045         case SUBTYPE_AUTH:
5046                 /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
5047                 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16));
5048                 NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16));
5049                 if (Seq == 1 || Seq == 3) {
5050                         *Machine = AUTH_RSP_STATE_MACHINE;
5051                         *MsgType = MT2_PEER_AUTH_ODD;
5052                 } else if (Seq == 2 || Seq == 4) {
5053                         if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) {
5054                                 *Machine = AUTH_STATE_MACHINE;
5055                                 *MsgType = MT2_PEER_AUTH_EVEN;
5056                         }
5057                 } else {
5058                         return FALSE;
5059                 }
5060                 break;
5061         case SUBTYPE_DEAUTH:
5062                 *Machine = AUTH_RSP_STATE_MACHINE;
5063                 *MsgType = MT2_PEER_DEAUTH;
5064                 break;
5065         case SUBTYPE_ACTION:
5066                 *Machine = ACTION_STATE_MACHINE;
5067                 /*  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
5068                 if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) {
5069                         *MsgType = MT2_ACT_INVALID;
5070                 } else {
5071                         *MsgType = (pFrame->Octet[0] & 0x7F);
5072                 }
5073                 break;
5074         default:
5075                 return FALSE;
5076                 break;
5077         }
5078
5079         return TRUE;
5080 }
5081
5082 /* =========================================================================================== */
5083 /* state_machine.c */
5084 /* =========================================================================================== */
5085
5086 /*! \brief Initialize the state machine.
5087  *      \param *S                       pointer to the state machine
5088  *      \param  Trans           State machine transition function
5089  *      \param  StNr            number of states
5090  *      \param  MsgNr           number of messages
5091  *      \param  DefFunc         default function, when there is invalid state/message combination
5092  *      \param  InitState       initial state of the state machine
5093  *      \param  Base            StateMachine base, internal use only
5094  *      \pre p_sm should be a legal pointer
5095  *      \post
5096
5097  IRQL = PASSIVE_LEVEL
5098
5099  */
5100 void StateMachineInit(struct rt_state_machine *S,
5101                       IN STATE_MACHINE_FUNC Trans[],
5102                       unsigned long StNr,
5103                       unsigned long MsgNr,
5104                       IN STATE_MACHINE_FUNC DefFunc,
5105                       unsigned long InitState, unsigned long Base)
5106 {
5107         unsigned long i, j;
5108
5109         /* set number of states and messages */
5110         S->NrState = StNr;
5111         S->NrMsg = MsgNr;
5112         S->Base = Base;
5113
5114         S->TransFunc = Trans;
5115
5116         /* init all state transition to default function */
5117         for (i = 0; i < StNr; i++) {
5118                 for (j = 0; j < MsgNr; j++) {
5119                         S->TransFunc[i * MsgNr + j] = DefFunc;
5120                 }
5121         }
5122
5123         /* set the starting state */
5124         S->CurrState = InitState;
5125 }
5126
5127 /*! \brief This function fills in the function pointer into the cell in the state machine
5128  *      \param *S       pointer to the state machine
5129  *      \param St       state
5130  *      \param Msg      incoming message
5131  *      \param f        the function to be executed when (state, message) combination occurs at the state machine
5132  *      \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
5133  *      \post
5134
5135  IRQL = PASSIVE_LEVEL
5136
5137  */
5138 void StateMachineSetAction(struct rt_state_machine *S,
5139                            unsigned long St,
5140                            unsigned long Msg, IN STATE_MACHINE_FUNC Func)
5141 {
5142         unsigned long MsgIdx;
5143
5144         MsgIdx = Msg - S->Base;
5145
5146         if (St < S->NrState && MsgIdx < S->NrMsg) {
5147                 /* boundary checking before setting the action */
5148                 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5149         }
5150 }
5151
5152 /*! \brief       This function does the state transition
5153  *      \param   *Adapter the NIC adapter pointer
5154  *      \param   *S       the state machine
5155  *      \param   *Elem    the message to be executed
5156  *      \return   None
5157
5158  IRQL = DISPATCH_LEVEL
5159
5160  */
5161 void StateMachinePerformAction(struct rt_rtmp_adapter *pAd,
5162                                struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem)
5163 {
5164         (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))
5165             (pAd, Elem);
5166 }
5167
5168 /*
5169         ==========================================================================
5170         Description:
5171                 The drop function, when machine executes this, the message is simply
5172                 ignored. This function does nothing, the message is freed in
5173                 StateMachinePerformAction()
5174         ==========================================================================
5175  */
5176 void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
5177 {
5178 }
5179
5180 /* =========================================================================================== */
5181 /* lfsr.c */
5182 /* =========================================================================================== */
5183
5184 /*
5185         ==========================================================================
5186         Description:
5187
5188         IRQL = PASSIVE_LEVEL
5189
5190         ==========================================================================
5191  */
5192 void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed)
5193 {
5194         if (Seed == 0)
5195                 pAd->Mlme.ShiftReg = 1;
5196         else
5197                 pAd->Mlme.ShiftReg = Seed;
5198 }
5199
5200 /*
5201         ==========================================================================
5202         Description:
5203         ==========================================================================
5204  */
5205 u8 RandomByte(struct rt_rtmp_adapter *pAd)
5206 {
5207         unsigned long i;
5208         u8 R, Result;
5209
5210         R = 0;
5211
5212         if (pAd->Mlme.ShiftReg == 0)
5213                 NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg);
5214
5215         for (i = 0; i < 8; i++) {
5216                 if (pAd->Mlme.ShiftReg & 0x00000001) {
5217                         pAd->Mlme.ShiftReg =
5218                             ((pAd->Mlme.
5219                               ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5220                         Result = 1;
5221                 } else {
5222                         pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5223                         Result = 0;
5224                 }
5225                 R = (R << 1) | Result;
5226         }
5227
5228         return R;
5229 }
5230
5231 /*
5232         ========================================================================
5233
5234         Routine Description:
5235                 Verify the support rate for different PHY type
5236
5237         Arguments:
5238                 pAd                             Pointer to our adapter
5239
5240         Return Value:
5241                 None
5242
5243         IRQL = PASSIVE_LEVEL
5244
5245         ========================================================================
5246 */
5247 void RTMPCheckRates(struct rt_rtmp_adapter *pAd,
5248                     IN u8 SupRate[], IN u8 * SupRateLen)
5249 {
5250         u8 RateIdx, i, j;
5251         u8 NewRate[12], NewRateLen;
5252
5253         NewRateLen = 0;
5254
5255         if (pAd->CommonCfg.PhyMode == PHY_11B)
5256                 RateIdx = 4;
5257         else
5258                 RateIdx = 12;
5259
5260         /* Check for support rates exclude basic rate bit */
5261         for (i = 0; i < *SupRateLen; i++)
5262                 for (j = 0; j < RateIdx; j++)
5263                         if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5264                                 NewRate[NewRateLen++] = SupRate[i];
5265
5266         *SupRateLen = NewRateLen;
5267         NdisMoveMemory(SupRate, NewRate, NewRateLen);
5268 }
5269
5270 BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd,
5271                          u8 CentralChannel, u8 Channel)
5272 {
5273         u8 k;
5274         u8 UpperChannel = 0, LowerChannel = 0;
5275         u8 NoEffectChannelinList = 0;
5276
5277         /* Find upper and lower channel according to 40MHz current operation. */
5278         if (CentralChannel < Channel) {
5279                 UpperChannel = Channel;
5280                 if (CentralChannel > 2)
5281                         LowerChannel = CentralChannel - 2;
5282                 else
5283                         return FALSE;
5284         } else if (CentralChannel > Channel) {
5285                 UpperChannel = CentralChannel + 2;
5286                 LowerChannel = Channel;
5287         }
5288
5289         for (k = 0; k < pAd->ChannelListNum; k++) {
5290                 if (pAd->ChannelList[k].Channel == UpperChannel) {
5291                         NoEffectChannelinList++;
5292                 }
5293                 if (pAd->ChannelList[k].Channel == LowerChannel) {
5294                         NoEffectChannelinList++;
5295                 }
5296         }
5297
5298         DBGPRINT(RT_DEBUG_TRACE,
5299                  ("Total Channel in Channel List = [%d]\n",
5300                   NoEffectChannelinList));
5301         if (NoEffectChannelinList == 2)
5302                 return TRUE;
5303         else
5304                 return FALSE;
5305 }
5306
5307 /*
5308         ========================================================================
5309
5310         Routine Description:
5311                 Verify the support rate for HT phy type
5312
5313         Arguments:
5314                 pAd                             Pointer to our adapter
5315
5316         Return Value:
5317                 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
5318
5319         IRQL = PASSIVE_LEVEL
5320
5321         ========================================================================
5322 */
5323 BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd,
5324                     u8 Wcid,
5325                     struct rt_ht_capability_ie * pHtCapability,
5326                     struct rt_add_ht_info_ie * pAddHtInfo)
5327 {
5328         if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5329                 return FALSE;
5330
5331         /* If use AMSDU, set flag. */
5332         if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
5333                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5334                                        fCLIENT_STATUS_AMSDU_INUSED);
5335         /* Save Peer Capability */
5336         if (pHtCapability->HtCapInfo.ShortGIfor20)
5337                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5338                                        fCLIENT_STATUS_SGI20_CAPABLE);
5339         if (pHtCapability->HtCapInfo.ShortGIfor40)
5340                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5341                                        fCLIENT_STATUS_SGI40_CAPABLE);
5342         if (pHtCapability->HtCapInfo.TxSTBC)
5343                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5344                                        fCLIENT_STATUS_TxSTBC_CAPABLE);
5345         if (pHtCapability->HtCapInfo.RxSTBC)
5346                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5347                                        fCLIENT_STATUS_RxSTBC_CAPABLE);
5348         if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) {
5349                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5350                                        fCLIENT_STATUS_RDG_CAPABLE);
5351         }
5352
5353         if (Wcid < MAX_LEN_OF_MAC_TABLE) {
5354                 pAd->MacTab.Content[Wcid].MpduDensity =
5355                     pHtCapability->HtCapParm.MpduDensity;
5356         }
5357         /* Will check ChannelWidth for MCSSet[4] below */
5358         pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
5359         switch (pAd->CommonCfg.RxStream) {
5360         case 1:
5361                 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5362                 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5363                 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5364                 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5365                 break;
5366         case 2:
5367                 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5368                 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5369                 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5370                 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5371                 break;
5372         case 3:
5373                 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5374                 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5375                 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5376                 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5377                 break;
5378         }
5379
5380         pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth =
5381             pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.
5382             ChannelWidth;
5383
5384         DBGPRINT(RT_DEBUG_TRACE,
5385                  ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5386                   pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth,
5387                   pAddHtInfo->AddHtInfo.RecomWidth,
5388                   pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5389                   pAd->NicConfig2.field.BW40MAvailForA,
5390                   pAd->NicConfig2.field.BW40MAvailForG,
5391                   pAd->CommonCfg.PhyMode));
5392
5393         pAd->MlmeAux.HtCapability.HtCapInfo.GF =
5394             pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF;
5395
5396         /* Send Assoc Req with my HT capability. */
5397         pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =
5398             pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5399         pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =
5400             pAd->CommonCfg.DesiredHtPhy.MimoPs;
5401         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =
5402             (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->
5403                                                           HtCapInfo.
5404                                                           ShortGIfor20);
5405         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =
5406             (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->
5407                                                           HtCapInfo.
5408                                                           ShortGIfor40);
5409         pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =
5410             (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo.
5411                                                     RxSTBC);
5412         pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =
5413             (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo.
5414                                                     TxSTBC);
5415         pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor =
5416             pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5417         pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity =
5418             pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5419         pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC =
5420             pHtCapability->ExtHtCapInfo.PlusHTC;
5421         pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC =
5422             pHtCapability->ExtHtCapInfo.PlusHTC;
5423         if (pAd->CommonCfg.bRdg) {
5424                 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport =
5425                     pHtCapability->ExtHtCapInfo.RDGSupport;
5426                 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5427         }
5428
5429         if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
5430                 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;      /* BW20 can't transmit MCS32 */
5431
5432         COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5433         return TRUE;
5434 }
5435
5436 /*
5437         ========================================================================
5438
5439         Routine Description:
5440                 Verify the support rate for different PHY type
5441
5442         Arguments:
5443                 pAd                             Pointer to our adapter
5444
5445         Return Value:
5446                 None
5447
5448         IRQL = PASSIVE_LEVEL
5449
5450         ========================================================================
5451 */
5452 void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd)
5453 {
5454         u8 MinimumRate;
5455         u8 ProperMlmeRate;      /*= RATE_54; */
5456         u8 i, j, RateIdx = 12;  /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
5457         BOOLEAN bMatch = FALSE;
5458
5459         switch (pAd->CommonCfg.PhyMode) {
5460         case PHY_11B:
5461                 ProperMlmeRate = RATE_11;
5462                 MinimumRate = RATE_1;
5463                 break;
5464         case PHY_11BG_MIXED:
5465         case PHY_11ABGN_MIXED:
5466         case PHY_11BGN_MIXED:
5467                 if ((pAd->MlmeAux.SupRateLen == 4) &&
5468                     (pAd->MlmeAux.ExtRateLen == 0))
5469                         /* B only AP */
5470                         ProperMlmeRate = RATE_11;
5471                 else
5472                         ProperMlmeRate = RATE_24;
5473
5474                 if (pAd->MlmeAux.Channel <= 14)
5475                         MinimumRate = RATE_1;
5476                 else
5477                         MinimumRate = RATE_6;
5478                 break;
5479         case PHY_11A:
5480         case PHY_11N_2_4G:      /* rt2860 need to check mlmerate for 802.11n */
5481         case PHY_11GN_MIXED:
5482         case PHY_11AGN_MIXED:
5483         case PHY_11AN_MIXED:
5484         case PHY_11N_5G:
5485                 ProperMlmeRate = RATE_24;
5486                 MinimumRate = RATE_6;
5487                 break;
5488         case PHY_11ABG_MIXED:
5489                 ProperMlmeRate = RATE_24;
5490                 if (pAd->MlmeAux.Channel <= 14)
5491                         MinimumRate = RATE_1;
5492                 else
5493                         MinimumRate = RATE_6;
5494                 break;
5495         default:                /* error */
5496                 ProperMlmeRate = RATE_1;
5497                 MinimumRate = RATE_1;
5498                 break;
5499         }
5500
5501         for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) {
5502                 for (j = 0; j < RateIdx; j++) {
5503                         if ((pAd->MlmeAux.SupRate[i] & 0x7f) ==
5504                             RateIdTo500Kbps[j]) {
5505                                 if (j == ProperMlmeRate) {
5506                                         bMatch = TRUE;
5507                                         break;
5508                                 }
5509                         }
5510                 }
5511
5512                 if (bMatch)
5513                         break;
5514         }
5515
5516         if (bMatch == FALSE) {
5517                 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) {
5518                         for (j = 0; j < RateIdx; j++) {
5519                                 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) ==
5520                                     RateIdTo500Kbps[j]) {
5521                                         if (j == ProperMlmeRate) {
5522                                                 bMatch = TRUE;
5523                                                 break;
5524                                         }
5525                                 }
5526                         }
5527
5528                         if (bMatch)
5529                                 break;
5530                 }
5531         }
5532
5533         if (bMatch == FALSE) {
5534                 ProperMlmeRate = MinimumRate;
5535         }
5536
5537         pAd->CommonCfg.MlmeRate = MinimumRate;
5538         pAd->CommonCfg.RtsRate = ProperMlmeRate;
5539         if (pAd->CommonCfg.MlmeRate >= RATE_6) {
5540                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
5541                 pAd->CommonCfg.MlmeTransmit.field.MCS =
5542                     OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5543                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5544                     MODE_OFDM;
5545                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5546                     OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5547         } else {
5548                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5549                 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
5550                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5551                     MODE_CCK;
5552                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5553                     pAd->CommonCfg.MlmeRate;
5554         }
5555
5556         DBGPRINT(RT_DEBUG_TRACE,
5557                  ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n",
5558                   pAd->CommonCfg.MlmeTransmit.word));
5559 }
5560
5561 char RTMPMaxRssi(struct rt_rtmp_adapter *pAd,
5562                  char Rssi0, char Rssi1, char Rssi2)
5563 {
5564         char larger = -127;
5565
5566         if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) {
5567                 larger = Rssi0;
5568         }
5569
5570         if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) {
5571                 larger = max(Rssi0, Rssi1);
5572         }
5573
5574         if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) {
5575                 larger = max(larger, Rssi2);
5576         }
5577
5578         if (larger == -127)
5579                 larger = 0;
5580
5581         return larger;
5582 }
5583
5584 /*
5585     ========================================================================
5586     Routine Description:
5587         Periodic evaluate antenna link status
5588
5589     Arguments:
5590         pAd         - Adapter pointer
5591
5592     Return Value:
5593         None
5594
5595     ========================================================================
5596 */
5597 void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd)
5598 {
5599         u8 BBPR3 = 0;
5600
5601         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5602                            fRTMP_ADAPTER_HALT_IN_PROGRESS |
5603                            fRTMP_ADAPTER_RADIO_OFF |
5604                            fRTMP_ADAPTER_NIC_NOT_EXIST |
5605                            fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5606             OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5607 #ifdef RT30xx
5608             || (pAd->EepromAccess)
5609 #endif /* RT30xx // */
5610 #ifdef RT3090
5611             || (pAd->bPCIclkOff == TRUE)
5612 #endif /* RT3090 // */
5613             )
5614                 return;
5615
5616         {
5617                 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5618                 /*      return; */
5619
5620                 {
5621
5622                         if (pAd->StaCfg.Psm == PWR_SAVE)
5623                                 return;
5624
5625                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5626                         BBPR3 &= (~0x18);
5627                         if (pAd->Antenna.field.RxPath == 3) {
5628                                 BBPR3 |= (0x10);
5629                         } else if (pAd->Antenna.field.RxPath == 2) {
5630                                 BBPR3 |= (0x8);
5631                         } else if (pAd->Antenna.field.RxPath == 1) {
5632                                 BBPR3 |= (0x0);
5633                         }
5634                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5635 #ifdef RTMP_MAC_PCI
5636                         pAd->StaCfg.BBPR3 = BBPR3;
5637 #endif /* RTMP_MAC_PCI // */
5638                         if (OPSTATUS_TEST_FLAG
5639                             (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5640                             ) {
5641                                 unsigned long TxTotalCnt =
5642                                     pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5643                                     pAd->RalinkCounters.OneSecTxRetryOkCount +
5644                                     pAd->RalinkCounters.OneSecTxFailCount;
5645
5646                                 /* dynamic adjust antenna evaluation period according to the traffic */
5647                                 if (TxTotalCnt > 50) {
5648                                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5649                                                      20);
5650                                         pAd->Mlme.bLowThroughput = FALSE;
5651                                 } else {
5652                                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5653                                                      300);
5654                                         pAd->Mlme.bLowThroughput = TRUE;
5655                                 }
5656                         }
5657                 }
5658
5659         }
5660
5661 }
5662
5663 /*
5664     ========================================================================
5665     Routine Description:
5666         After evaluation, check antenna link status
5667
5668     Arguments:
5669         pAd         - Adapter pointer
5670
5671     Return Value:
5672         None
5673
5674     ========================================================================
5675 */
5676 void AsicRxAntEvalTimeout(void *SystemSpecific1,
5677                           void *FunctionContext,
5678                           void *SystemSpecific2, void *SystemSpecific3)
5679 {
5680         struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
5681         u8 BBPR3 = 0;
5682         char larger = -127, rssi0, rssi1, rssi2;
5683
5684         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5685                            fRTMP_ADAPTER_HALT_IN_PROGRESS |
5686                            fRTMP_ADAPTER_RADIO_OFF |
5687                            fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5688             OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5689 #ifdef RT30xx
5690             || (pAd->EepromAccess)
5691 #endif /* RT30xx // */
5692 #ifdef RT3090
5693             || (pAd->bPCIclkOff == TRUE)
5694 #endif /* RT3090 // */
5695             )
5696                 return;
5697
5698         {
5699                 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5700                 /*      return; */
5701                 {
5702                         if (pAd->StaCfg.Psm == PWR_SAVE)
5703                                 return;
5704
5705                         /* if the traffic is low, use average rssi as the criteria */
5706                         if (pAd->Mlme.bLowThroughput == TRUE) {
5707                                 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5708                                 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5709                                 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
5710                         } else {
5711                                 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5712                                 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5713                                 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5714                         }
5715
5716                         if (pAd->Antenna.field.RxPath == 3) {
5717                                 larger = max(rssi0, rssi1);
5718
5719                                 if (larger > (rssi2 + 20))
5720                                         pAd->Mlme.RealRxPath = 2;
5721                                 else
5722                                         pAd->Mlme.RealRxPath = 3;
5723                         } else if (pAd->Antenna.field.RxPath == 2) {
5724                                 if (rssi0 > (rssi1 + 20))
5725                                         pAd->Mlme.RealRxPath = 1;
5726                                 else
5727                                         pAd->Mlme.RealRxPath = 2;
5728                         }
5729
5730                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5731                         BBPR3 &= (~0x18);
5732                         if (pAd->Mlme.RealRxPath == 3) {
5733                                 BBPR3 |= (0x10);
5734                         } else if (pAd->Mlme.RealRxPath == 2) {
5735                                 BBPR3 |= (0x8);
5736                         } else if (pAd->Mlme.RealRxPath == 1) {
5737                                 BBPR3 |= (0x0);
5738                         }
5739                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5740 #ifdef RTMP_MAC_PCI
5741                         pAd->StaCfg.BBPR3 = BBPR3;
5742 #endif /* RTMP_MAC_PCI // */
5743                 }
5744         }
5745
5746 }
5747
5748 void APSDPeriodicExec(void *SystemSpecific1,
5749                       void *FunctionContext,
5750                       void *SystemSpecific2, void *SystemSpecific3)
5751 {
5752         struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
5753
5754         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5755                 return;
5756
5757         pAd->CommonCfg.TriggerTimerCount++;
5758
5759 /* Driver should not send trigger frame, it should be send by application layer */
5760 /*
5761         if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5762                 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5763                 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5764         {
5765                 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5766                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5767                 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5768                 pAd->CommonCfg.TriggerTimerCount = 0;
5769                 pAd->CommonCfg.bInServicePeriod = TRUE;
5770         }*/
5771 }
5772
5773 /*
5774     ========================================================================
5775     Routine Description:
5776         Set/reset MAC registers according to bPiggyBack parameter
5777
5778     Arguments:
5779         pAd         - Adapter pointer
5780         bPiggyBack  - Enable / Disable Piggy-Back
5781
5782     Return Value:
5783         None
5784
5785     ========================================================================
5786 */
5787 void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack)
5788 {
5789         TX_LINK_CFG_STRUC TxLinkCfg;
5790
5791         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5792
5793         TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5794         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5795 }
5796
5797 /*
5798     ========================================================================
5799     Routine Description:
5800         check if this entry need to switch rate automatically
5801
5802     Arguments:
5803         pAd
5804         pEntry
5805
5806     Return Value:
5807         TURE
5808         FALSE
5809
5810     ========================================================================
5811 */
5812 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd,
5813                                            struct rt_mac_table_entry *pEntry)
5814 {
5815         BOOLEAN result = TRUE;
5816
5817         {
5818                 /* only associated STA counts */
5819                 if (pEntry && (pEntry->ValidAsCLI)
5820                     && (pEntry->Sst == SST_ASSOC)) {
5821                         result = pAd->StaCfg.bAutoTxRateSwitch;
5822                 } else
5823                         result = FALSE;
5824         }
5825
5826         return result;
5827 }
5828
5829 BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd)
5830 {
5831         {
5832                 if (pAd->StaCfg.bAutoTxRateSwitch)
5833                         return TRUE;
5834         }
5835         return FALSE;
5836 }
5837
5838 /*
5839     ========================================================================
5840     Routine Description:
5841         check if this entry need to fix tx legacy rate
5842
5843     Arguments:
5844         pAd
5845         pEntry
5846
5847     Return Value:
5848         TURE
5849         FALSE
5850
5851     ========================================================================
5852 */
5853 u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
5854 {
5855         u8 tx_mode = FIXED_TXMODE_HT;
5856
5857         {
5858                 tx_mode =
5859                     (u8)pAd->StaCfg.DesiredTransmitSetting.field.
5860                     FixedTxMode;
5861         }
5862
5863         return tx_mode;
5864 }
5865
5866 /*
5867     ========================================================================
5868     Routine Description:
5869         Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5870
5871     Arguments:
5872         pAd
5873         pEntry
5874
5875     Return Value:
5876         TURE
5877         FALSE
5878
5879     ========================================================================
5880 */
5881 void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry)
5882 {
5883         HTTRANSMIT_SETTING TransmitSetting;
5884
5885         if (fixed_tx_mode == FIXED_TXMODE_HT)
5886                 return;
5887
5888         TransmitSetting.word = 0;
5889
5890         TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5891         TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5892
5893         if (fixed_tx_mode == FIXED_TXMODE_CCK) {
5894                 TransmitSetting.field.MODE = MODE_CCK;
5895                 /* CCK mode allow MCS 0~3 */
5896                 if (TransmitSetting.field.MCS > MCS_3)
5897                         TransmitSetting.field.MCS = MCS_3;
5898         } else {
5899                 TransmitSetting.field.MODE = MODE_OFDM;
5900                 /* OFDM mode allow MCS 0~7 */
5901                 if (TransmitSetting.field.MCS > MCS_7)
5902                         TransmitSetting.field.MCS = MCS_7;
5903         }
5904
5905         if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) {
5906                 pEntry->HTPhyMode.word = TransmitSetting.word;
5907                 DBGPRINT(RT_DEBUG_TRACE,
5908                          ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5909                           pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE),
5910                           pEntry->HTPhyMode.field.MCS));
5911         }
5912 }
5913
5914 /*
5915         ==========================================================================
5916         Description:
5917                 dynamic tune BBP R66 to find a balance between sensibility and
5918                 noise isolation
5919
5920         IRQL = DISPATCH_LEVEL
5921
5922         ==========================================================================
5923  */
5924 void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd)
5925 {
5926         u8 OrigR66Value = 0, R66;       /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */
5927         char Rssi;
5928
5929         /* 2860C did not support Fase CCA, therefore can't tune */
5930         if (pAd->MACVersion == 0x28600100)
5931                 return;
5932
5933         /* */
5934         /* work as a STA */
5935         /* */
5936         if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)       /* no R66 tuning when SCANNING */
5937                 return;
5938
5939         if ((pAd->OpMode == OPMODE_STA)
5940             && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5941             )
5942             && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
5943 #ifdef RTMP_MAC_PCI
5944             && (pAd->bPCIclkOff == FALSE)
5945 #endif /* RTMP_MAC_PCI // */
5946             ) {
5947                 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5948                 R66 = OrigR66Value;
5949
5950                 if (pAd->Antenna.field.RxPath > 1)
5951                         Rssi =
5952                             (pAd->StaCfg.RssiSample.AvgRssi0 +
5953                              pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
5954                 else
5955                         Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5956
5957                 if (pAd->LatchRfRegs.Channel <= 14) {   /*BG band */
5958 #ifdef RT30xx
5959                         /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */
5960                         /* Otherwise, it will have some throughput side effect when low RSSI */
5961
5962                         if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
5963                             || IS_RT3390(pAd)) {
5964                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5965                                         R66 =
5966                                             0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20;
5967                                         if (OrigR66Value != R66) {
5968                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5969                                                     (pAd, BBP_R66, R66);
5970                                         }
5971                                 } else {
5972                                         R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
5973                                         if (OrigR66Value != R66) {
5974                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5975                                                     (pAd, BBP_R66, R66);
5976                                         }
5977                                 }
5978                         } else
5979 #endif /* RT30xx // */
5980                         {
5981                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5982                                         R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
5983                                         if (OrigR66Value != R66) {
5984                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5985                                                     (pAd, BBP_R66, R66);
5986                                         }
5987                                 } else {
5988                                         R66 = 0x2E + GET_LNA_GAIN(pAd);
5989                                         if (OrigR66Value != R66) {
5990                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
5991                                                     (pAd, BBP_R66, R66);
5992                                         }
5993                                 }
5994                         }
5995                 } else {        /*A band */
5996                         if (pAd->CommonCfg.BBPCurrentBW == BW_20) {
5997                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5998                                         R66 =
5999                                             0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 +
6000                                             0x10;
6001                                         if (OrigR66Value != R66) {
6002                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6003                                                     (pAd, BBP_R66, R66);
6004                                         }
6005                                 } else {
6006                                         R66 =
6007                                             0x32 + (GET_LNA_GAIN(pAd) * 5) / 3;
6008                                         if (OrigR66Value != R66) {
6009                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6010                                                     (pAd, BBP_R66, R66);
6011                                         }
6012                                 }
6013                         } else {
6014                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6015                                         R66 =
6016                                             0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 +
6017                                             0x10;
6018                                         if (OrigR66Value != R66) {
6019                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6020                                                     (pAd, BBP_R66, R66);
6021                                         }
6022                                 } else {
6023                                         R66 =
6024                                             0x3A + (GET_LNA_GAIN(pAd) * 5) / 3;
6025                                         if (OrigR66Value != R66) {
6026                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID
6027                                                     (pAd, BBP_R66, R66);
6028                                         }
6029                                 }
6030                         }
6031                 }
6032
6033         }
6034 }
6035
6036 void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth)
6037 {
6038         u8 R66 = 0x30;
6039
6040         if (pAd->LatchRfRegs.Channel <= 14) {   /* BG band */
6041 #ifdef RT30xx
6042                 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6043
6044                 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
6045                     || IS_RT3390(pAd)) {
6046                         R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
6047                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6048                 } else
6049 #endif /* RT30xx // */
6050                 {
6051                         R66 = 0x2E + GET_LNA_GAIN(pAd);
6052                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6053                 }
6054         } else {                /*A band */
6055                 {
6056                         if (BandWidth == BW_20) {
6057                                 R66 =
6058                                     (u8)(0x32 +
6059                                              (GET_LNA_GAIN(pAd) * 5) / 3);
6060                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6061                         } else {
6062                                 R66 =
6063                                     (u8)(0x3A +
6064                                              (GET_LNA_GAIN(pAd) * 5) / 3);
6065                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6066                         }
6067                 }
6068         }
6069
6070 }