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