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