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