d0a3b6b70feb93048cade2e00e352da9795ab31d
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2860 / common / mlme.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27         Module Name:
28         mlme.c
29
30         Abstract:
31
32         Revision History:
33         Who                     When                    What
34         --------        ----------              ----------------------------------------------
35         John Chang      2004-08-25              Modify from RT2500 code base
36         John Chang      2004-09-06              modified for RT2600
37 */
38
39 #include "../rt_config.h"
40 #include <stdarg.h>
41
42 UCHAR   CISCO_OUI[] = {0x00, 0x40, 0x96};
43
44 UCHAR   WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR   RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR   WME_INFO_ELEM[]  = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
47 UCHAR   WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
48 UCHAR   Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
49 UCHAR   RALINK_OUI[]  = {0x00, 0x0c, 0x43};
50 UCHAR   BROADCOM_OUI[]  = {0x00, 0x90, 0x4c};
51 UCHAR   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
52 UCHAR   PRE_N_HT_OUI[]  = {0x00, 0x90, 0x4c};
53
54 UCHAR RateSwitchTable[] = {
55 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
56     0x11, 0x00,  0,  0,  0,                                             // Initial used item after association
57     0x00, 0x00,  0, 40, 101,
58     0x01, 0x00,  1, 40, 50,
59     0x02, 0x00,  2, 35, 45,
60     0x03, 0x00,  3, 20, 45,
61     0x04, 0x21,  0, 30, 50,
62     0x05, 0x21,  1, 20, 50,
63     0x06, 0x21,  2, 20, 50,
64     0x07, 0x21,  3, 15, 50,
65     0x08, 0x21,  4, 15, 30,
66     0x09, 0x21,  5, 10, 25,
67     0x0a, 0x21,  6,  8, 25,
68     0x0b, 0x21,  7,  8, 25,
69     0x0c, 0x20, 12,  15, 30,
70     0x0d, 0x20, 13,  8, 20,
71     0x0e, 0x20, 14,  8, 20,
72     0x0f, 0x20, 15,  8, 25,
73     0x10, 0x22, 15,  8, 25,
74     0x11, 0x00,  0,  0,  0,
75     0x12, 0x00,  0,  0,  0,
76     0x13, 0x00,  0,  0,  0,
77     0x14, 0x00,  0,  0,  0,
78     0x15, 0x00,  0,  0,  0,
79     0x16, 0x00,  0,  0,  0,
80     0x17, 0x00,  0,  0,  0,
81     0x18, 0x00,  0,  0,  0,
82     0x19, 0x00,  0,  0,  0,
83     0x1a, 0x00,  0,  0,  0,
84     0x1b, 0x00,  0,  0,  0,
85     0x1c, 0x00,  0,  0,  0,
86     0x1d, 0x00,  0,  0,  0,
87     0x1e, 0x00,  0,  0,  0,
88     0x1f, 0x00,  0,  0,  0,
89 };
90
91 UCHAR RateSwitchTable11B[] = {
92 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
93     0x04, 0x03,  0,  0,  0,                                             // Initial used item after association
94     0x00, 0x00,  0, 40, 101,
95     0x01, 0x00,  1, 40, 50,
96     0x02, 0x00,  2, 35, 45,
97     0x03, 0x00,  3, 20, 45,
98 };
99
100 UCHAR RateSwitchTable11BG[] = {
101 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
102     0x0a, 0x00,  0,  0,  0,                                             // Initial used item after association
103     0x00, 0x00,  0, 40, 101,
104     0x01, 0x00,  1, 40, 50,
105     0x02, 0x00,  2, 35, 45,
106     0x03, 0x00,  3, 20, 45,
107     0x04, 0x10,  2, 20, 35,
108     0x05, 0x10,  3, 16, 35,
109     0x06, 0x10,  4, 10, 25,
110     0x07, 0x10,  5, 16, 25,
111     0x08, 0x10,  6, 10, 25,
112     0x09, 0x10,  7, 10, 13,
113 };
114
115 UCHAR RateSwitchTable11G[] = {
116 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
117     0x08, 0x00,  0,  0,  0,                                             // Initial used item after association
118     0x00, 0x10,  0, 20, 101,
119     0x01, 0x10,  1, 20, 35,
120     0x02, 0x10,  2, 20, 35,
121     0x03, 0x10,  3, 16, 35,
122     0x04, 0x10,  4, 10, 25,
123     0x05, 0x10,  5, 16, 25,
124     0x06, 0x10,  6, 10, 25,
125     0x07, 0x10,  7, 10, 13,
126 };
127
128 UCHAR RateSwitchTable11N1S[] = {
129 // Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
130     0x09, 0x00,  0,  0,  0,                                             // Initial used item after association
131     0x00, 0x21,  0, 30, 101,
132     0x01, 0x21,  1, 20, 50,
133     0x02, 0x21,  2, 20, 50,
134     0x03, 0x21,  3, 15, 50,
135     0x04, 0x21,  4, 15, 30,
136     0x05, 0x21,  5, 10, 25,
137     0x06, 0x21,  6,  8, 14,
138     0x07, 0x21,  7,  8, 14,
139     0x08, 0x23,  7,  8, 14,
140 };
141
142 UCHAR RateSwitchTable11N2S[] = {
143 // 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)
144     0x0a, 0x00,  0,  0,  0,      // Initial used item after association
145     0x00, 0x21,  0, 30, 101,
146     0x01, 0x21,  1, 20, 50,
147     0x02, 0x21,  2, 20, 50,
148     0x03, 0x21,  3, 15, 50,
149     0x04, 0x21,  4, 15, 30,
150     0x05, 0x20, 12,  15, 30,
151     0x06, 0x20, 13,  8, 20,
152     0x07, 0x20, 14,  8, 20,
153     0x08, 0x20, 15,  8, 25,
154     0x09, 0x22, 15,  8, 25,
155 };
156
157 UCHAR RateSwitchTable11N3S[] = {
158 // 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)
159     0x0a, 0x00,  0,  0,  0,      // Initial used item after association
160     0x00, 0x21,  0, 30, 101,
161     0x01, 0x21,  1, 20, 50,
162     0x02, 0x21,  2, 20, 50,
163     0x03, 0x21,  3, 15, 50,
164     0x04, 0x21,  4, 15, 30,
165     0x05, 0x20, 12,  15, 30,
166     0x06, 0x20, 13,  8, 20,
167     0x07, 0x20, 14,  8, 20,
168     0x08, 0x20, 15,  8, 25,
169     0x09, 0x22, 15,  8, 25,
170 };
171
172 UCHAR RateSwitchTable11N2SForABand[] = {
173 // 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)
174     0x0b, 0x09,  0,  0,  0,                                             // Initial used item after association
175     0x00, 0x21,  0, 30, 101,
176     0x01, 0x21,  1, 20, 50,
177     0x02, 0x21,  2, 20, 50,
178     0x03, 0x21,  3, 15, 50,
179     0x04, 0x21,  4, 15, 30,
180     0x05, 0x21,  5, 15, 30,
181     0x06, 0x20, 12,  15, 30,
182     0x07, 0x20, 13,  8, 20,
183     0x08, 0x20, 14,  8, 20,
184     0x09, 0x20, 15,  8, 25,
185     0x0a, 0x22, 15,  8, 25,
186 };
187
188 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
189 // 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)
190     0x0b, 0x09,  0,  0,  0,                                             // Initial used item after association
191     0x00, 0x21,  0, 30, 101,
192     0x01, 0x21,  1, 20, 50,
193     0x02, 0x21,  2, 20, 50,
194     0x03, 0x21,  3, 15, 50,
195     0x04, 0x21,  4, 15, 30,
196     0x05, 0x21,  5, 15, 30,
197     0x06, 0x20, 12,  15, 30,
198     0x07, 0x20, 13,  8, 20,
199     0x08, 0x20, 14,  8, 20,
200     0x09, 0x20, 15,  8, 25,
201     0x0a, 0x22, 15,  8, 25,
202 };
203
204 UCHAR RateSwitchTable11BGN1S[] = {
205 // 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)
206     0x0d, 0x00,  0,  0,  0,                                             // Initial used item after association
207     0x00, 0x00,  0, 40, 101,
208     0x01, 0x00,  1, 40, 50,
209     0x02, 0x00,  2, 35, 45,
210     0x03, 0x00,  3, 20, 45,
211     0x04, 0x21,  0, 30,101,     //50
212     0x05, 0x21,  1, 20, 50,
213     0x06, 0x21,  2, 20, 50,
214     0x07, 0x21,  3, 15, 50,
215     0x08, 0x21,  4, 15, 30,
216     0x09, 0x21,  5, 10, 25,
217     0x0a, 0x21,  6,  8, 14,
218     0x0b, 0x21,  7,  8, 14,
219         0x0c, 0x23,  7,  8, 14,
220 };
221
222 UCHAR RateSwitchTable11BGN2S[] = {
223 // 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)
224     0x0a, 0x00,  0,  0,  0,                                             // Initial used item after association
225     0x00, 0x21,  0, 30,101,     //50
226     0x01, 0x21,  1, 20, 50,
227     0x02, 0x21,  2, 20, 50,
228     0x03, 0x21,  3, 15, 50,
229     0x04, 0x21,  4, 15, 30,
230     0x05, 0x20, 12, 15, 30,
231     0x06, 0x20, 13,  8, 20,
232     0x07, 0x20, 14,  8, 20,
233     0x08, 0x20, 15,  8, 25,
234     0x09, 0x22, 15,  8, 25,
235 };
236
237 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
238 // 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)
239     0x0a, 0x00,  0,  0,  0,                                             // Initial used item after association
240     0x00, 0x21,  0, 30,101,     //50
241     0x01, 0x21,  1, 20, 50,
242     0x02, 0x21,  2, 20, 50,
243     0x03, 0x21,  3, 20, 50,
244     0x04, 0x21,  4, 15, 50,
245     0x05, 0x20, 20, 15, 30,
246     0x06, 0x20, 21,  8, 20,
247     0x07, 0x20, 22,  8, 20,
248     0x08, 0x20, 23,  8, 25,
249     0x09, 0x22, 23,  8, 25,
250 };
251
252 UCHAR RateSwitchTable11BGN2SForABand[] = {
253 // 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)
254     0x0b, 0x09,  0,  0,  0,                                             // Initial used item after association
255     0x00, 0x21,  0, 30,101,     //50
256     0x01, 0x21,  1, 20, 50,
257     0x02, 0x21,  2, 20, 50,
258     0x03, 0x21,  3, 15, 50,
259     0x04, 0x21,  4, 15, 30,
260     0x05, 0x21,  5, 15, 30,
261     0x06, 0x20, 12, 15, 30,
262     0x07, 0x20, 13,  8, 20,
263     0x08, 0x20, 14,  8, 20,
264     0x09, 0x20, 15,  8, 25,
265     0x0a, 0x22, 15,  8, 25,
266 };
267
268 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
269 // 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)
270     0x0c, 0x09,  0,  0,  0,                                             // Initial used item after association
271     0x00, 0x21,  0, 30,101,     //50
272     0x01, 0x21,  1, 20, 50,
273     0x02, 0x21,  2, 20, 50,
274     0x03, 0x21,  3, 15, 50,
275     0x04, 0x21,  4, 15, 30,
276     0x05, 0x21,  5, 15, 30,
277     0x06, 0x21, 12, 15, 30,
278     0x07, 0x20, 20, 15, 30,
279     0x08, 0x20, 21,  8, 20,
280     0x09, 0x20, 22,  8, 20,
281     0x0a, 0x20, 23,  8, 25,
282     0x0b, 0x22, 23,  8, 25,
283 };
284
285 PUCHAR ReasonString[] = {
286         /* 0  */         "Reserved",
287         /* 1  */         "Unspecified Reason",
288         /* 2  */         "Previous Auth no longer valid",
289         /* 3  */         "STA is leaving / has left",
290         /* 4  */         "DIS-ASSOC due to inactivity",
291         /* 5  */         "AP unable to hanle all associations",
292         /* 6  */         "class 2 error",
293         /* 7  */         "class 3 error",
294         /* 8  */         "STA is leaving / has left",
295         /* 9  */         "require auth before assoc/re-assoc",
296         /* 10 */         "Reserved",
297         /* 11 */         "Reserved",
298         /* 12 */         "Reserved",
299         /* 13 */         "invalid IE",
300         /* 14 */         "MIC error",
301         /* 15 */         "4-way handshake timeout",
302         /* 16 */         "2-way (group key) handshake timeout",
303         /* 17 */         "4-way handshake IE diff among AssosReq/Rsp/Beacon",
304         /* 18 */
305 };
306
307 extern UCHAR     OfdmRateToRxwiMCS[];
308 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
309 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
310 ULONG BasicRateMask[12]                         = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
311                                                                           0xfffff01f /* 6 */     , 0xfffff03f /* 9 */     , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
312                                                                           0xfffff1ff /* 24 */    , 0xfffff3ff /* 36 */    , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
313
314 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1,  0x00, 0x00, 0x00, 0x00, 0x00};
315 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
316 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]  = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
317
318 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
319 //              this value, then it's quaranteed capable of operating in 36 mbps TX rate in
320 //              clean environment.
321 //                                                                TxRate: 1   2   5.5   11       6        9    12       18       24   36   48   54       72  100
322 CHAR RssiSafeLevelForTxRate[] ={  -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
323
324 UCHAR  RateIdToMbps[]    = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
325 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
326
327 UCHAR  SsidIe    = IE_SSID;
328 UCHAR  SupRateIe = IE_SUPP_RATES;
329 UCHAR  ExtRateIe = IE_EXT_SUPP_RATES;
330 UCHAR  HtCapIe = IE_HT_CAP;
331 UCHAR  AddHtInfoIe = IE_ADD_HT;
332 UCHAR  NewExtChanIe = IE_SECONDARY_CH_OFFSET;
333 UCHAR  ErpIe     = IE_ERP;
334 UCHAR  DsIe      = IE_DS_PARM;
335 UCHAR  TimIe     = IE_TIM;
336 UCHAR  WpaIe     = IE_WPA;
337 UCHAR  Wpa2Ie    = IE_WPA2;
338 UCHAR  IbssIe    = IE_IBSS_PARM;
339 UCHAR  Ccx2Ie    = IE_CCX_V2;
340
341 extern UCHAR    WPA_OUI[];
342
343 UCHAR   SES_OUI[] = {0x00, 0x90, 0x4c};
344
345 UCHAR   ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
346         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
347
348 // Reset the RFIC setting to new series
349 RTMP_RF_REGS RF2850RegTable[] = {
350 //              ch       R1              R2              R3(TX0~4=0) R4
351                 {1,  0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
352                 {2,  0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
353                 {3,  0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
354                 {4,  0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
355                 {5,  0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
356                 {6,  0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
357                 {7,  0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
358                 {8,  0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
359                 {9,  0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
360                 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
361                 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
362                 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
363                 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
364                 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
365
366                 // 802.11 UNI / HyperLan 2
367                 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
368                 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
369                 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
370                 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
371                 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
372                 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
373                 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
374                 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
375                 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
376                 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
377                 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
378                 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
379
380                 // 802.11 HyperLan 2
381                 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
382
383                 // 2008.04.30 modified
384                 // The system team has AN to improve the EVM value
385                 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
386                 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
387                 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
388                 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
389
390                 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
391                 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
392                 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
393                 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
394                 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
395                 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
396                 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
397                 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
398                 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
399                 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
400                 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
401                 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
402
403                 // 802.11 UNII
404                 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
405                 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
406                 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
407                 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
408                 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
409                 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
410                 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
411
412                 // Japan
413                 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
414                 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
415                 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
416                 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
417                 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
418                 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
419                 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
420
421                 // still lack of MMAC(Japan) ch 34,38,42,46
422 };
423 UCHAR   NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
424
425 FREQUENCY_ITEM FreqItems3020[] =
426 {
427         /**************************************************/
428         // ISM : 2.4 to 2.483 GHz                         //
429         /**************************************************/
430         // 11g
431         /**************************************************/
432         //-CH---N-------R---K-----------
433         {1,    241,  2,  2},
434         {2,    241,      2,  7},
435         {3,    242,      2,  2},
436         {4,    242,      2,  7},
437         {5,    243,      2,  2},
438         {6,    243,      2,  7},
439         {7,    244,      2,  2},
440         {8,    244,      2,  7},
441         {9,    245,      2,  2},
442         {10,   245,      2,  7},
443         {11,   246,      2,  2},
444         {12,   246,      2,  7},
445         {13,   247,      2,  2},
446         {14,   248,      2,  4},
447 };
448 UCHAR   NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
449
450 /*
451         ==========================================================================
452         Description:
453                 initialize the MLME task and its data structure (queue, spinlock,
454                 timer, state machines).
455
456         IRQL = PASSIVE_LEVEL
457
458         Return:
459                 always return NDIS_STATUS_SUCCESS
460
461         ==========================================================================
462 */
463 NDIS_STATUS MlmeInit(
464         IN PRTMP_ADAPTER pAd)
465 {
466         NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
467
468         DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
469
470         do
471         {
472                 Status = MlmeQueueInit(&pAd->Mlme.Queue);
473                 if(Status != NDIS_STATUS_SUCCESS)
474                         break;
475
476                 pAd->Mlme.bRunning = FALSE;
477                 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
478
479                 {
480                         BssTableInit(&pAd->ScanTab);
481
482                         // init STA state machines
483                         AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
484                         AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
485                         AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
486                         SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
487                         WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
488                         AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
489
490                         // Since we are using switch/case to implement it, the init is different from the above
491                         // state machine init
492                         MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
493                 }
494
495                 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
496
497                 // Init mlme periodic timer
498                 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
499
500                 // Set mlme periodic timer
501                 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
502
503                 // software-based RX Antenna diversity
504                 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
505
506 #ifdef RT2860
507                 {
508                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
509                 {
510                     // only PCIe cards need these two timers
511                         RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
512                         RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
513                 }
514                 }
515 #endif
516         } while (FALSE);
517
518         DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
519
520         return Status;
521 }
522
523 /*
524         ==========================================================================
525         Description:
526                 main loop of the MLME
527         Pre:
528                 Mlme has to be initialized, and there are something inside the queue
529         Note:
530                 This function is invoked from MPSetInformation and MPReceive;
531                 This task guarantee only one MlmeHandler will run.
532
533         IRQL = DISPATCH_LEVEL
534
535         ==========================================================================
536  */
537 VOID MlmeHandler(
538         IN PRTMP_ADAPTER pAd)
539 {
540         MLME_QUEUE_ELEM            *Elem = NULL;
541
542         // Only accept MLME and Frame from peer side, no other (control/data) frame should
543         // get into this state machine
544
545         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
546         if(pAd->Mlme.bRunning)
547         {
548                 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
549                 return;
550         }
551         else
552         {
553                 pAd->Mlme.bRunning = TRUE;
554         }
555         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
556
557         while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
558         {
559                 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
560                         RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
561                         RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
562                 {
563                         DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
564                         break;
565                 }
566
567                 //From message type, determine which state machine I should drive
568                 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
569                 {
570 #ifdef RT2870
571                         if (Elem->MsgType == MT2_RESET_CONF)
572                         {
573                                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
574                                 MlmeRestartStateMachine(pAd);
575                                 Elem->Occupied = FALSE;
576                                 Elem->MsgLen = 0;
577                                 continue;
578                         }
579 #endif // RT2870 //
580
581                         // if dequeue success
582                         switch (Elem->Machine)
583                         {
584                                 // STA state machines
585                                 case ASSOC_STATE_MACHINE:
586                                         StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
587                                         break;
588                                 case AUTH_STATE_MACHINE:
589                                         StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
590                                         break;
591                                 case AUTH_RSP_STATE_MACHINE:
592                                         StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
593                                         break;
594                                 case SYNC_STATE_MACHINE:
595                                         StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
596                                         break;
597                                 case MLME_CNTL_STATE_MACHINE:
598                                         MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
599                                         break;
600                                 case WPA_PSK_STATE_MACHINE:
601                                         StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
602                                         break;
603                                 case AIRONET_STATE_MACHINE:
604                                         StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
605                                         break;
606                                 case ACTION_STATE_MACHINE:
607                                         StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
608                                         break;
609
610
611
612
613                                 default:
614                                         DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
615                                         break;
616                         } // end of switch
617
618                         // free MLME element
619                         Elem->Occupied = FALSE;
620                         Elem->MsgLen = 0;
621
622                 }
623                 else {
624                         DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
625                 }
626         }
627
628         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
629         pAd->Mlme.bRunning = FALSE;
630         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
631 }
632
633 /*
634         ==========================================================================
635         Description:
636                 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
637         Parameters:
638                 Adapter - NIC Adapter pointer
639         Post:
640                 The MLME task will no longer work properly
641
642         IRQL = PASSIVE_LEVEL
643
644         ==========================================================================
645  */
646 VOID MlmeHalt(
647         IN PRTMP_ADAPTER pAd)
648 {
649         BOOLEAN           Cancelled;
650 #ifdef RT3070
651         UINT32          TxPinCfg = 0x00050F0F;
652 #endif // RT3070 //
653
654         DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
655
656         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
657         {
658                 // disable BEACON generation and other BEACON related hardware timers
659                 AsicDisableSync(pAd);
660         }
661
662         {
663                 // Cancel pending timers
664                 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,               &Cancelled);
665                 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,             &Cancelled);
666                 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,    &Cancelled);
667                 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,                &Cancelled);
668                 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,              &Cancelled);
669                 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,                &Cancelled);
670 #ifdef RT2860
671             if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
672             {
673                     RTMPCancelTimer(&pAd->Mlme.PsPollTimer,             &Cancelled);
674                     RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,         &Cancelled);
675                 }
676 #endif
677         }
678
679         RTMPCancelTimer(&pAd->Mlme.PeriodicTimer,               &Cancelled);
680         RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer,              &Cancelled);
681
682
683
684         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
685         {
686                 // Set LED
687                 RTMPSetLED(pAd, LED_HALT);
688         RTMPSetSignalLED(pAd, -100);    // Force signal strength Led to be turned off, firmware is not done it.
689 #ifdef RT2870
690         {
691             LED_CFG_STRUC LedCfg;
692             RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
693             LedCfg.field.LedPolar = 0;
694             LedCfg.field.RLedMode = 0;
695             LedCfg.field.GLedMode = 0;
696             LedCfg.field.YLedMode = 0;
697             RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
698         }
699 #endif // RT2870 //
700 #ifdef RT3070
701                 //
702                 // Turn off LNA_PE
703                 //
704                 if (IS_RT3070(pAd) || IS_RT3071(pAd))
705                 {
706                         TxPinCfg &= 0xFFFFF0F0;
707                         RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
708                 }
709 #endif // RT3070 //
710         }
711
712         RTMPusecDelay(5000);    //  5 msec to gurantee Ant Diversity timer canceled
713
714         MlmeQueueDestroy(&pAd->Mlme.Queue);
715         NdisFreeSpinLock(&pAd->Mlme.TaskLock);
716
717         DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
718 }
719
720 VOID MlmeResetRalinkCounters(
721         IN  PRTMP_ADAPTER   pAd)
722 {
723         pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
724         // clear all OneSecxxx counters.
725         pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
726         pAd->RalinkCounters.OneSecFalseCCACnt = 0;
727         pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
728         pAd->RalinkCounters.OneSecRxOkCnt = 0;
729         pAd->RalinkCounters.OneSecTxFailCount = 0;
730         pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
731         pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
732         pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
733
734         // TODO: for debug only. to be removed
735         pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
736         pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
737         pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
738         pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
739         pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
740         pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
741         pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
742         pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
743         pAd->RalinkCounters.OneSecTxDoneCount = 0;
744         pAd->RalinkCounters.OneSecRxCount = 0;
745         pAd->RalinkCounters.OneSecTxAggregationCount = 0;
746         pAd->RalinkCounters.OneSecRxAggregationCount = 0;
747
748         return;
749 }
750
751 unsigned long rx_AMSDU;
752 unsigned long rx_Total;
753
754 /*
755         ==========================================================================
756         Description:
757                 This routine is executed periodically to -
758                 1. Decide if it's a right time to turn on PwrMgmt bit of all
759                    outgoiing frames
760                 2. Calculate ChannelQuality based on statistics of the last
761                    period, so that TX rate won't toggling very frequently between a
762                    successful TX and a failed TX.
763                 3. If the calculated ChannelQuality indicated current connection not
764                    healthy, then a ROAMing attempt is tried here.
765
766         IRQL = DISPATCH_LEVEL
767
768         ==========================================================================
769  */
770 #define ADHOC_BEACON_LOST_TIME          (8*OS_HZ)  // 8 sec
771 VOID MlmePeriodicExec(
772         IN PVOID SystemSpecific1,
773         IN PVOID FunctionContext,
774         IN PVOID SystemSpecific2,
775         IN PVOID SystemSpecific3)
776 {
777         ULONG                   TxTotalCnt;
778         PRTMP_ADAPTER   pAd = (RTMP_ADAPTER *)FunctionContext;
779
780 #ifdef RT2860
781         //Baron 2008/07/10
782         //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
783         //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
784         //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
785         if(pAd->StaCfg.WepStatus<2)
786         {
787                 pAd->StaCfg.WpaSupplicantUP = 0;
788         }
789         else
790         {
791                 pAd->StaCfg.WpaSupplicantUP = 1;
792         }
793
794         {
795             // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
796                 // Move code to here, because following code will return when radio is off
797                 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
798                         (pAd->StaCfg.bHardwareRadio == TRUE) &&
799                         (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
800                         (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
801                         (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
802                 {
803                         UINT32                          data = 0;
804
805                         // Read GPIO pin2 as Hardware controlled radio state
806                         RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
807                         if (data & 0x04)
808                         {
809                                 pAd->StaCfg.bHwRadio = TRUE;
810                         }
811                         else
812                         {
813                                 pAd->StaCfg.bHwRadio = FALSE;
814                         }
815                         if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
816                         {
817                                 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
818                                 if (pAd->StaCfg.bRadio == TRUE)
819                                 {
820                                         MlmeRadioOn(pAd);
821                                         // Update extra information
822                                         pAd->ExtraInfo = EXTRA_INFO_CLEAR;
823                                 }
824                                 else
825                                 {
826                                         MlmeRadioOff(pAd);
827                                         // Update extra information
828                                         pAd->ExtraInfo = HW_RADIO_OFF;
829                                 }
830                         }
831                 }
832         }
833 #endif /* RT2860 */
834
835         // Do nothing if the driver is starting halt state.
836         // This might happen when timer already been fired before cancel timer with mlmehalt
837         if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
838                                                                 fRTMP_ADAPTER_RADIO_OFF |
839                                                                 fRTMP_ADAPTER_RADIO_MEASUREMENT |
840                                                                 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
841                 return;
842
843 #ifdef RT2860
844         {
845                 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
846                 {
847                         // If ReceiveByteCount doesn't change,  increase SameRxByteCount by 1.
848                         pAd->SameRxByteCount++;
849                 }
850                 else
851                         pAd->SameRxByteCount = 0;
852
853                 // If after BBP, still not work...need to check to reset PBF&MAC.
854                 if (pAd->SameRxByteCount == 702)
855                 {
856                         pAd->SameRxByteCount = 0;
857                         AsicResetPBF(pAd);
858                         AsicResetMAC(pAd);
859                 }
860
861                 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
862                 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
863                 {
864                         if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
865                         {
866                                 DBGPRINT(RT_DEBUG_TRACE, ("--->  SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
867                                 pAd->SameRxByteCount = 700;
868                                 AsicResetBBP(pAd);
869                         }
870                 }
871
872                 // Update lastReceiveByteCount.
873                 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
874
875                 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
876                 {
877                         pAd->CheckDmaBusyCount = 0;
878                         AsicResetFromDMABusy(pAd);
879                 }
880         }
881 #endif /* RT2860 */
882         RT28XX_MLME_PRE_SANITY_CHECK(pAd);
883
884         {
885                 // Do nothing if monitor mode is on
886                 if (MONITOR_ON(pAd))
887                         return;
888
889                 if (pAd->Mlme.PeriodicRound & 0x1)
890                 {
891                         // This is the fix for wifi 11n extension channel overlapping test case.  for 2860D
892                         if (((pAd->MACVersion & 0xffff) == 0x0101) &&
893                                 (STA_TGN_WIFI_ON(pAd)) &&
894                                 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
895
896                                 {
897                                         RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
898                                         pAd->CommonCfg.IOTestParm.bToggle = TRUE;
899                                 }
900                                 else if ((STA_TGN_WIFI_ON(pAd)) &&
901                                                 ((pAd->MACVersion & 0xffff) == 0x0101))
902                                 {
903                                         RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
904                                         pAd->CommonCfg.IOTestParm.bToggle = FALSE;
905                                 }
906                 }
907         }
908
909         pAd->bUpdateBcnCntDone = FALSE;
910
911 //      RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
912         pAd->Mlme.PeriodicRound ++;
913
914 #ifdef RT3070
915         // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
916         NICUpdateFifoStaCounters(pAd);
917 #endif // RT3070 //
918         // execute every 500ms
919         if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
920         {
921                 // perform dynamic tx rate switching based on past TX history
922                 {
923                         if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
924                                         )
925                                 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
926                                 MlmeDynamicTxRateSwitching(pAd);
927                 }
928         }
929
930         // Normal 1 second Mlme PeriodicExec.
931         if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
932         {
933                 pAd->Mlme.OneSecPeriodicRound ++;
934
935                 if (rx_Total)
936                 {
937
938                         // reset counters
939                         rx_AMSDU = 0;
940                         rx_Total = 0;
941                 }
942
943                 // Media status changed, report to NDIS
944                 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
945                 {
946                         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
947                         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
948                         {
949                                 pAd->IndicateMediaState = NdisMediaStateConnected;
950                                 RTMP_IndicateMediaState(pAd);
951
952                         }
953                         else
954                         {
955                                 pAd->IndicateMediaState = NdisMediaStateDisconnected;
956                                 RTMP_IndicateMediaState(pAd);
957                         }
958                 }
959
960                 NdisGetSystemUpTime(&pAd->Mlme.Now32);
961
962                 // add the most up-to-date h/w raw counters into software variable, so that
963                 // the dynamic tuning mechanism below are based on most up-to-date information
964                 NICUpdateRawCounters(pAd);
965
966 #ifdef RT2870
967                 RT2870_WatchDog(pAd);
968 #endif // RT2870 //
969
970                 // Need statistics after read counter. So put after NICUpdateRawCounters
971                 ORIBATimerTimeout(pAd);
972
973                 // The time period for checking antenna is according to traffic
974                 if (pAd->Mlme.bEnableAutoAntennaCheck)
975                 {
976                         TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
977                                                          pAd->RalinkCounters.OneSecTxRetryOkCount +
978                                                          pAd->RalinkCounters.OneSecTxFailCount;
979
980                         // dynamic adjust antenna evaluation period according to the traffic
981                         if (TxTotalCnt > 50)
982                         {
983                                 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
984                                 {
985                                         AsicEvaluateRxAnt(pAd);
986                                 }
987                         }
988                         else
989                         {
990                                 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
991                                 {
992                                         AsicEvaluateRxAnt(pAd);
993                                 }
994                         }
995                 }
996
997                 STAMlmePeriodicExec(pAd);
998
999                 MlmeResetRalinkCounters(pAd);
1000
1001                 {
1002 #ifdef RT2860
1003                         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1004 #endif
1005                         {
1006                                 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1007                                 // and sending CTS-to-self over and over.
1008                                 // Software Patch Solution:
1009                                 // 1. Polling debug state register 0x10F4 every one second.
1010                                 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1011                                 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1012
1013                                 UINT32  MacReg = 0;
1014
1015                                 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1016                                 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1017                                 {
1018                                         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1019                                         RTMPusecDelay(1);
1020                                         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1021
1022                                         DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1023                                 }
1024                         }
1025                 }
1026
1027                 RT28XX_MLME_HANDLER(pAd);
1028         }
1029
1030         pAd->bUpdateBcnCntDone = FALSE;
1031 }
1032
1033 VOID STAMlmePeriodicExec(
1034         PRTMP_ADAPTER pAd)
1035 {
1036 #ifdef RT2860
1037         ULONG                       TxTotalCnt;
1038 #endif
1039 #ifdef RT2870
1040         ULONG   TxTotalCnt;
1041         int     i;
1042 #endif
1043
1044     if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1045     {
1046         // WPA MIC error should block association attempt for 60 seconds
1047         if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1048                 pAd->StaCfg.bBlockAssoc = FALSE;
1049     }
1050
1051 #ifdef RT2860
1052         //Baron 2008/07/10
1053         //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1054         //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1055         //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1056         if(pAd->StaCfg.WepStatus<2)
1057         {
1058                 pAd->StaCfg.WpaSupplicantUP = 0;
1059         }
1060         else
1061         {
1062                 pAd->StaCfg.WpaSupplicantUP = 1;
1063         }
1064 #endif
1065
1066     if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1067         {
1068                 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1069                 {
1070                         RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1071                 }
1072                 pAd->PreMediaState = pAd->IndicateMediaState;
1073         }
1074
1075 #ifdef RT2860
1076         if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1077         (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1078                 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1079                 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1080                 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1081                 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1082         {
1083                 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1084         }
1085 #endif
1086
1087
1088
1089         AsicStaBbpTuning(pAd);
1090
1091         TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1092                                          pAd->RalinkCounters.OneSecTxRetryOkCount +
1093                                          pAd->RalinkCounters.OneSecTxFailCount;
1094
1095         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1096         {
1097                 // update channel quality for Roaming and UI LinkQuality display
1098                 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1099         }
1100
1101         // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1102         // Radio is currently in noisy environment
1103         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1104                 AsicAdjustTxPower(pAd);
1105
1106         if (INFRA_ON(pAd))
1107         {
1108                 // Is PSM bit consistent with user power management policy?
1109                 // This is the only place that will set PSM bit ON.
1110                 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1111                 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1112
1113                 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1114
1115                 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1116                         (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1117                         ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1118                 {
1119                         RTMPSetAGCInitValue(pAd, BW_20);
1120                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1121                 }
1122
1123         {
1124                 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1125                 {
1126                     // When APSD is enabled, the period changes as 20 sec
1127                         if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1128                                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1129                 }
1130                 else
1131                 {
1132                     // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1133                         if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1134                 {
1135                     if (pAd->CommonCfg.bWmmCapable)
1136                                         RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1137                     else
1138                                                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1139                 }
1140                 }
1141         }
1142
1143                 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1144                         {
1145                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1146                         pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1147                         pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1148
1149                         // Lost AP, send disconnect & link down event
1150                         LinkDown(pAd, FALSE);
1151
1152             {
1153                 union iwreq_data    wrqu;
1154                 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1155                 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1156             }
1157
1158                         MlmeAutoReconnectLastSSID(pAd);
1159                 }
1160                 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1161                 {
1162                         pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1163                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1164                         MlmeAutoReconnectLastSSID(pAd);
1165                 }
1166
1167                 // Add auto seamless roaming
1168                 if (pAd->StaCfg.bFastRoaming)
1169                 {
1170                         SHORT   dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1171
1172                         DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
1173
1174                         if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1175                         {
1176                                 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1177                         }
1178                 }
1179         }
1180         else if (ADHOC_ON(pAd))
1181         {
1182 #ifdef RT2860
1183                 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1184                 // the "TX BEACON competition" for the entire past 1 sec.
1185                 // So that even when ASIC's BEACONgen engine been blocked
1186                 // by peer's BEACON due to slower system clock, this STA still can send out
1187                 // minimum BEACON to tell the peer I'm alive.
1188                 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1189                 // EnqueueBeaconFrame(pAd);                       // software send BEACON
1190
1191                 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1192                 // restore outgoing BEACON to support B/G-mixed mode
1193                 if ((pAd->CommonCfg.Channel <= 14)                         &&
1194                         (pAd->CommonCfg.MaxTxRate <= RATE_11)      &&
1195                         (pAd->CommonCfg.MaxDesiredRate > RATE_11)  &&
1196                         ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1197                 {
1198                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1199                         NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1200                         pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1201                         MlmeUpdateTxRates(pAd, FALSE, 0);
1202                         MakeIbssBeacon(pAd);            // re-build BEACON frame
1203                         AsicEnableIbssSync(pAd);        // copy to on-chip memory
1204                         pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1205                 }
1206
1207                 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1208                 {
1209                         if ((pAd->StaCfg.AdhocBGJoined) &&
1210                                 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1211                         {
1212                                 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1213                                 pAd->StaCfg.AdhocBGJoined = FALSE;
1214                         }
1215
1216                         if ((pAd->StaCfg.Adhoc20NJoined) &&
1217                                 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1218                         {
1219                                 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1220                                 pAd->StaCfg.Adhoc20NJoined = FALSE;
1221                         }
1222                 }
1223 #endif /* RT2860 */
1224
1225                 //radar detect
1226                 if ((pAd->CommonCfg.Channel > 14)
1227                         && (pAd->CommonCfg.bIEEE80211H == 1)
1228                         && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1229                 {
1230                         RadarDetectPeriodic(pAd);
1231                 }
1232
1233                 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1234                 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1235                 // join later.
1236                 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1237                         OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1238                 {
1239                         MLME_START_REQ_STRUCT     StartReq;
1240
1241                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1242                         LinkDown(pAd, FALSE);
1243
1244                         StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1245                         MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1246                         pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1247                 }
1248
1249 #ifdef RT2870
1250                 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1251                 {
1252                         MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1253
1254                         if (pEntry->ValidAsCLI == FALSE)
1255                                 continue;
1256
1257                         if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1258                                 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1259                 }
1260 #endif
1261         }
1262         else // no INFRA nor ADHOC connection
1263         {
1264
1265                 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1266             ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1267                         goto SKIP_AUTO_SCAN_CONN;
1268         else
1269             pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1270
1271                 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1272                         && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1273                         && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1274                 {
1275                         if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1276                         {
1277                                 MLME_SCAN_REQ_STRUCT       ScanReq;
1278
1279                                 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1280                                 {
1281                                         DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1282                                         ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1283                                         MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1284                                         pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1285                                         // Reset Missed scan number
1286                                         pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1287                                 }
1288                                 else if (pAd->StaCfg.BssType == BSS_ADHOC)      // Quit the forever scan when in a very clean room
1289                                         MlmeAutoReconnectLastSSID(pAd);
1290                         }
1291                         else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1292                         {
1293                                 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1294                                 {
1295                                         MlmeAutoScan(pAd);
1296                                         pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1297                                 }
1298                                 else
1299                                 {
1300                                                 MlmeAutoReconnectLastSSID(pAd);
1301                                 }
1302                         }
1303                 }
1304         }
1305
1306 SKIP_AUTO_SCAN_CONN:
1307
1308     if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1309         {
1310                 pAd->MacTab.fAnyBASession = TRUE;
1311                 AsicUpdateProtect(pAd, HT_FORCERTSCTS,  ALLN_SETPROTECT, FALSE, FALSE);
1312         }
1313         else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1314         {
1315                 pAd->MacTab.fAnyBASession = FALSE;
1316                 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode,  ALLN_SETPROTECT, FALSE, FALSE);
1317         }
1318
1319         return;
1320 }
1321
1322 // Link down report
1323 VOID LinkDownExec(
1324         IN PVOID SystemSpecific1,
1325         IN PVOID FunctionContext,
1326         IN PVOID SystemSpecific2,
1327         IN PVOID SystemSpecific3)
1328 {
1329
1330         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1331
1332         pAd->IndicateMediaState = NdisMediaStateDisconnected;
1333         RTMP_IndicateMediaState(pAd);
1334     pAd->ExtraInfo = GENERAL_LINK_DOWN;
1335 }
1336
1337 // IRQL = DISPATCH_LEVEL
1338 VOID MlmeAutoScan(
1339         IN PRTMP_ADAPTER pAd)
1340 {
1341         // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1342         if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1343         {
1344                 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1345                 MlmeEnqueue(pAd,
1346                                         MLME_CNTL_STATE_MACHINE,
1347                                         OID_802_11_BSSID_LIST_SCAN,
1348                                         0,
1349                                         NULL);
1350                 RT28XX_MLME_HANDLER(pAd);
1351         }
1352 }
1353
1354 // IRQL = DISPATCH_LEVEL
1355 VOID MlmeAutoReconnectLastSSID(
1356         IN PRTMP_ADAPTER pAd)
1357 {
1358
1359
1360         // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1361         if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1362                 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1363         {
1364                 NDIS_802_11_SSID OidSsid;
1365                 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1366                 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1367
1368                 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1369                 MlmeEnqueue(pAd,
1370                                         MLME_CNTL_STATE_MACHINE,
1371                                         OID_802_11_SSID,
1372                                         sizeof(NDIS_802_11_SSID),
1373                                         &OidSsid);
1374                 RT28XX_MLME_HANDLER(pAd);
1375         }
1376 }
1377
1378 /*
1379         ==========================================================================
1380         Validate SSID for connection try and rescan purpose
1381         Valid SSID will have visible chars only.
1382         The valid length is from 0 to 32.
1383         IRQL = DISPATCH_LEVEL
1384         ==========================================================================
1385  */
1386 BOOLEAN MlmeValidateSSID(
1387         IN PUCHAR       pSsid,
1388         IN UCHAR        SsidLen)
1389 {
1390         int     index;
1391
1392         if (SsidLen > MAX_LEN_OF_SSID)
1393                 return (FALSE);
1394
1395         // Check each character value
1396         for (index = 0; index < SsidLen; index++)
1397         {
1398                 if (pSsid[index] < 0x20)
1399                         return (FALSE);
1400         }
1401
1402         // All checked
1403         return (TRUE);
1404 }
1405
1406 VOID MlmeSelectTxRateTable(
1407         IN PRTMP_ADAPTER                pAd,
1408         IN PMAC_TABLE_ENTRY             pEntry,
1409         IN PUCHAR                               *ppTable,
1410         IN PUCHAR                               pTableSize,
1411         IN PUCHAR                               pInitTxRateIdx)
1412 {
1413         do
1414         {
1415                 // decide the rate table for tuning
1416                 if (pAd->CommonCfg.TxRateTableSize > 0)
1417                 {
1418                         *ppTable = RateSwitchTable;
1419                         *pTableSize = RateSwitchTable[0];
1420                         *pInitTxRateIdx = RateSwitchTable[1];
1421
1422                         break;
1423                 }
1424
1425                 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1426                 {
1427                         if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1428 #ifdef RT2860
1429                                 !pAd->StaCfg.AdhocBOnlyJoined &&
1430                                 !pAd->StaCfg.AdhocBGJoined &&
1431                                 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1432                                 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1433 #endif
1434 #ifdef RT2870
1435                                 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1436                                 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1437 #endif
1438                         {// 11N 1S Adhoc
1439                                 *ppTable = RateSwitchTable11N1S;
1440                                 *pTableSize = RateSwitchTable11N1S[0];
1441                                 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1442
1443                         }
1444                         else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1445 #ifdef RT2860
1446                                         !pAd->StaCfg.AdhocBOnlyJoined &&
1447                                         !pAd->StaCfg.AdhocBGJoined &&
1448                                         (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1449                                         (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1450 #endif
1451 #ifdef RT2870
1452                                         (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1453                                         (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1454 #endif
1455                                         (pAd->Antenna.field.TxPath == 2))
1456                         {// 11N 2S Adhoc
1457                                 if (pAd->LatchRfRegs.Channel <= 14)
1458                                 {
1459                                         *ppTable = RateSwitchTable11N2S;
1460                                         *pTableSize = RateSwitchTable11N2S[0];
1461                                         *pInitTxRateIdx = RateSwitchTable11N2S[1];
1462                                 }
1463                                 else
1464                                 {
1465                                         *ppTable = RateSwitchTable11N2SForABand;
1466                                         *pTableSize = RateSwitchTable11N2SForABand[0];
1467                                         *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1468                                 }
1469
1470                         }
1471                         else
1472 #ifdef RT2860
1473                                 if (pAd->CommonCfg.PhyMode == PHY_11B)
1474                         {
1475                                 *ppTable = RateSwitchTable11B;
1476                                 *pTableSize = RateSwitchTable11B[0];
1477                                 *pInitTxRateIdx = RateSwitchTable11B[1];
1478
1479                         }
1480                 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1481 #endif
1482 #ifdef RT2870
1483                                 if ((pEntry->RateLen == 4)
1484                                         && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1485                                         )
1486 #endif
1487                         {
1488                                 // USe B Table when Only b-only Station in my IBSS .
1489                                 *ppTable = RateSwitchTable11B;
1490                                 *pTableSize = RateSwitchTable11B[0];
1491                                 *pInitTxRateIdx = RateSwitchTable11B[1];
1492
1493                         }
1494                         else if (pAd->LatchRfRegs.Channel <= 14)
1495                         {
1496                                 *ppTable = RateSwitchTable11BG;
1497                                 *pTableSize = RateSwitchTable11BG[0];
1498                                 *pInitTxRateIdx = RateSwitchTable11BG[1];
1499
1500                         }
1501                         else
1502                         {
1503                                 *ppTable = RateSwitchTable11G;
1504                                 *pTableSize = RateSwitchTable11G[0];
1505                                 *pInitTxRateIdx = RateSwitchTable11G[1];
1506
1507                         }
1508                         break;
1509                 }
1510
1511                 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1512                         ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1513                 {// 11BGN 1S AP
1514                         *ppTable = RateSwitchTable11BGN1S;
1515                         *pTableSize = RateSwitchTable11BGN1S[0];
1516                         *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1517
1518                         break;
1519                 }
1520
1521                 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1522                         (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1523                 {// 11BGN 2S AP
1524                         if (pAd->LatchRfRegs.Channel <= 14)
1525                         {
1526                                 *ppTable = RateSwitchTable11BGN2S;
1527                                 *pTableSize = RateSwitchTable11BGN2S[0];
1528                                 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1529
1530                         }
1531                         else
1532                         {
1533                                 *ppTable = RateSwitchTable11BGN2SForABand;
1534                                 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1535                                 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1536
1537                         }
1538                         break;
1539                 }
1540
1541                 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1542                 {// 11N 1S AP
1543                         *ppTable = RateSwitchTable11N1S;
1544                         *pTableSize = RateSwitchTable11N1S[0];
1545                         *pInitTxRateIdx = RateSwitchTable11N1S[1];
1546
1547                         break;
1548                 }
1549
1550                 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1551                 {// 11N 2S AP
1552                         if (pAd->LatchRfRegs.Channel <= 14)
1553                         {
1554                         *ppTable = RateSwitchTable11N2S;
1555                         *pTableSize = RateSwitchTable11N2S[0];
1556                         *pInitTxRateIdx = RateSwitchTable11N2S[1];
1557             }
1558                         else
1559                         {
1560                                 *ppTable = RateSwitchTable11N2SForABand;
1561                                 *pTableSize = RateSwitchTable11N2SForABand[0];
1562                                 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1563                         }
1564
1565                         break;
1566                 }
1567
1568                 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1569                 if (pEntry->RateLen == 4)
1570                 {// B only AP
1571                         *ppTable = RateSwitchTable11B;
1572                         *pTableSize = RateSwitchTable11B[0];
1573                         *pInitTxRateIdx = RateSwitchTable11B[1];
1574
1575                         break;
1576                 }
1577
1578                 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1579                 if ((pEntry->RateLen > 8)
1580                         && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1581                         )
1582                 {// B/G  mixed AP
1583                         *ppTable = RateSwitchTable11BG;
1584                         *pTableSize = RateSwitchTable11BG[0];
1585                         *pInitTxRateIdx = RateSwitchTable11BG[1];
1586
1587                         break;
1588                 }
1589
1590                 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1591                 if ((pEntry->RateLen == 8)
1592                         && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1593                         )
1594                 {// G only AP
1595                         *ppTable = RateSwitchTable11G;
1596                         *pTableSize = RateSwitchTable11G[0];
1597                         *pInitTxRateIdx = RateSwitchTable11G[1];
1598
1599                         break;
1600                 }
1601
1602                 {
1603                         //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1604                         if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1605                         {       // Legacy mode
1606                                 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1607                                 {
1608                                         *ppTable = RateSwitchTable11B;
1609                                         *pTableSize = RateSwitchTable11B[0];
1610                                         *pInitTxRateIdx = RateSwitchTable11B[1];
1611                                 }
1612                                 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1613                                 {
1614                                         *ppTable = RateSwitchTable11G;
1615                                         *pTableSize = RateSwitchTable11G[0];
1616                                         *pInitTxRateIdx = RateSwitchTable11G[1];
1617
1618                                 }
1619                                 else
1620                                 {
1621                                         *ppTable = RateSwitchTable11BG;
1622                                         *pTableSize = RateSwitchTable11BG[0];
1623                                         *pInitTxRateIdx = RateSwitchTable11BG[1];
1624                                 }
1625                                 break;
1626                         }
1627
1628                         if (pAd->LatchRfRegs.Channel <= 14)
1629                         {
1630                                 if (pAd->CommonCfg.TxStream == 1)
1631                                 {
1632                                         *ppTable = RateSwitchTable11N1S;
1633                                         *pTableSize = RateSwitchTable11N1S[0];
1634                                         *pInitTxRateIdx = RateSwitchTable11N1S[1];
1635                                         DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1636                                 }
1637                                 else
1638                                 {
1639                                         *ppTable = RateSwitchTable11N2S;
1640                                         *pTableSize = RateSwitchTable11N2S[0];
1641                                         *pInitTxRateIdx = RateSwitchTable11N2S[1];
1642                                         DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1643                                 }
1644                         }
1645                         else
1646                         {
1647                                 if (pAd->CommonCfg.TxStream == 1)
1648                                 {
1649                                         *ppTable = RateSwitchTable11N1S;
1650                                         *pTableSize = RateSwitchTable11N1S[0];
1651                                         *pInitTxRateIdx = RateSwitchTable11N1S[1];
1652                                         DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1653                                 }
1654                                 else
1655                                 {
1656                                         *ppTable = RateSwitchTable11N2SForABand;
1657                                         *pTableSize = RateSwitchTable11N2SForABand[0];
1658                                         *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1659                                         DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1660                                 }
1661                         }
1662
1663                         DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1664                                 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1665                 }
1666         } while(FALSE);
1667 }
1668
1669 /*
1670         ==========================================================================
1671         Description:
1672                 This routine checks if there're other APs out there capable for
1673                 roaming. Caller should call this routine only when Link up in INFRA mode
1674                 and channel quality is below CQI_GOOD_THRESHOLD.
1675
1676         IRQL = DISPATCH_LEVEL
1677
1678         Output:
1679         ==========================================================================
1680  */
1681 VOID MlmeCheckForRoaming(
1682         IN PRTMP_ADAPTER pAd,
1683         IN ULONG        Now32)
1684 {
1685         USHORT     i;
1686         BSS_TABLE  *pRoamTab = &pAd->MlmeAux.RoamTab;
1687         BSS_ENTRY  *pBss;
1688
1689         DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1690         // put all roaming candidates into RoamTab, and sort in RSSI order
1691         BssTableInit(pRoamTab);
1692         for (i = 0; i < pAd->ScanTab.BssNr; i++)
1693         {
1694                 pBss = &pAd->ScanTab.BssEntry[i];
1695
1696                 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1697                         continue;        // AP disappear
1698                 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1699                         continue;        // RSSI too weak. forget it.
1700                 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1701                         continue;        // skip current AP
1702                 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1703                         continue;        // only AP with stronger RSSI is eligible for roaming
1704
1705                 // AP passing all above rules is put into roaming candidate table
1706                 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1707                 pRoamTab->BssNr += 1;
1708         }
1709
1710         if (pRoamTab->BssNr > 0)
1711         {
1712                 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1713                 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1714                 {
1715                         pAd->RalinkCounters.PoorCQIRoamingCount ++;
1716                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1717                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1718                         RT28XX_MLME_HANDLER(pAd);
1719                 }
1720         }
1721         DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1722 }
1723
1724 /*
1725         ==========================================================================
1726         Description:
1727                 This routine checks if there're other APs out there capable for
1728                 roaming. Caller should call this routine only when link up in INFRA mode
1729                 and channel quality is below CQI_GOOD_THRESHOLD.
1730
1731         IRQL = DISPATCH_LEVEL
1732
1733         Output:
1734         ==========================================================================
1735  */
1736 VOID MlmeCheckForFastRoaming(
1737         IN      PRTMP_ADAPTER   pAd,
1738         IN      ULONG                   Now)
1739 {
1740         USHORT          i;
1741         BSS_TABLE       *pRoamTab = &pAd->MlmeAux.RoamTab;
1742         BSS_ENTRY       *pBss;
1743
1744         DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1745         // put all roaming candidates into RoamTab, and sort in RSSI order
1746         BssTableInit(pRoamTab);
1747         for (i = 0; i < pAd->ScanTab.BssNr; i++)
1748         {
1749                 pBss = &pAd->ScanTab.BssEntry[i];
1750
1751         if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1752                         continue;        // RSSI too weak. forget it.
1753                 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1754                         continue;        // skip current AP
1755                 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1756                         continue;        // skip different SSID
1757         if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1758                         continue;        // skip AP without better RSSI
1759
1760         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));
1761                 // AP passing all above rules is put into roaming candidate table
1762                 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1763                 pRoamTab->BssNr += 1;
1764         }
1765
1766         if (pRoamTab->BssNr > 0)
1767         {
1768                 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1769                 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1770                 {
1771                         pAd->RalinkCounters.PoorCQIRoamingCount ++;
1772                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1773                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1774                         RT28XX_MLME_HANDLER(pAd);
1775                 }
1776         }
1777         // Maybe site survey required
1778         else
1779         {
1780                 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1781                 {
1782                         // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1783                         DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1784                         pAd->StaCfg.ScanCnt = 2;
1785                         pAd->StaCfg.LastScanTime = Now;
1786                         MlmeAutoScan(pAd);
1787                 }
1788         }
1789
1790     DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1791 }
1792
1793 /*
1794         ==========================================================================
1795         Description:
1796                 This routine calculates TxPER, RxPER of the past N-sec period. And
1797                 according to the calculation result, ChannelQuality is calculated here
1798                 to decide if current AP is still doing the job.
1799
1800                 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1801         Output:
1802                 StaCfg.ChannelQuality - 0..100
1803
1804         IRQL = DISPATCH_LEVEL
1805
1806         NOTE: This routine decide channle quality based on RX CRC error ratio.
1807                 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1808                 is performed right before this routine, so that this routine can decide
1809                 channel quality based on the most up-to-date information
1810         ==========================================================================
1811  */
1812 VOID MlmeCalculateChannelQuality(
1813         IN PRTMP_ADAPTER pAd,
1814         IN ULONG Now32)
1815 {
1816         ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1817         ULONG RxCnt, RxPER;
1818         UCHAR NorRssi;
1819         CHAR  MaxRssi;
1820         ULONG BeaconLostTime = BEACON_LOST_TIME;
1821
1822         MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1823
1824         //
1825         // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1826         //
1827         TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1828         TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1829         if (TxCnt < 5)
1830         {
1831                 TxPER = 0;
1832                 TxPRR = 0;
1833         }
1834         else
1835         {
1836                 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1837                 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1838         }
1839
1840         //
1841         // calculate RX PER - don't take RxPER into consideration if too few sample
1842         //
1843         RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1844         if (RxCnt < 5)
1845                 RxPER = 0;
1846         else
1847                 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1848
1849         //
1850         // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1851         //
1852         if (INFRA_ON(pAd) &&
1853                 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1854                 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1855         {
1856                 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1857                 pAd->Mlme.ChannelQuality = 0;
1858         }
1859         else
1860         {
1861                 // Normalize Rssi
1862                 if (MaxRssi > -40)
1863                         NorRssi = 100;
1864                 else if (MaxRssi < -90)
1865                         NorRssi = 0;
1866                 else
1867                         NorRssi = (MaxRssi + 90) * 2;
1868
1869                 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER        (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1870                 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1871                                                                    TX_WEIGHTING * (100 - TxPRR) +
1872                                                                    RX_WEIGHTING* (100 - RxPER)) / 100;
1873                 if (pAd->Mlme.ChannelQuality >= 100)
1874                         pAd->Mlme.ChannelQuality = 100;
1875         }
1876
1877 }
1878
1879 VOID MlmeSetTxRate(
1880         IN PRTMP_ADAPTER                pAd,
1881         IN PMAC_TABLE_ENTRY             pEntry,
1882         IN PRTMP_TX_RATE_SWITCH pTxRate)
1883 {
1884         UCHAR   MaxMode = MODE_OFDM;
1885
1886         MaxMode = MODE_HTGREENFIELD;
1887
1888         if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1889                 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1890         else
1891                 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1892
1893         if (pTxRate->CurrMCS < MCS_AUTO)
1894                 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1895
1896         if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1897                 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1898
1899         if (ADHOC_ON(pAd))
1900         {
1901                 // If peer adhoc is b-only mode, we can't send 11g rate.
1902                 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1903                 pEntry->HTPhyMode.field.STBC    = STBC_NONE;
1904
1905                 //
1906                 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1907                 //
1908                 pEntry->HTPhyMode.field.MODE    = pTxRate->Mode;
1909                 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1910                 pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1911
1912                 // Patch speed error in status page
1913                 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1914         }
1915         else
1916         {
1917                 if (pTxRate->Mode <= MaxMode)
1918                         pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1919
1920                 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1921                         pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1922                 else
1923                         pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1924
1925                 // Reexam each bandwidth's SGI support.
1926                 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1927                 {
1928                         if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1929                                 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1930                         if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1931                                 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1932                 }
1933
1934                 // Turn RTS/CTS rate to 6Mbps.
1935                 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1936                 {
1937                         pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1938                         if (pAd->MacTab.fAnyBASession)
1939                         {
1940                                 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1941                         }
1942                         else
1943                         {
1944                                 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1945                         }
1946                 }
1947                 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1948                 {
1949                         pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1950                         if (pAd->MacTab.fAnyBASession)
1951                         {
1952                                 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1953                         }
1954                         else
1955                         {
1956                                 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1957                         }
1958                 }
1959                 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1960                 {
1961                         AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1962
1963                 }
1964                 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1965                 {
1966                         AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1967                 }
1968
1969                 pEntry->HTPhyMode.field.STBC    = pAd->StaCfg.HTPhyMode.field.STBC;
1970                 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1971                 pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1972                 pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
1973
1974                 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1975                     pAd->WIFItestbed.bGreenField)
1976                     pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1977         }
1978
1979         pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1980 }
1981
1982 /*
1983         ==========================================================================
1984         Description:
1985                 This routine calculates the acumulated TxPER of eaxh TxRate. And
1986                 according to the calculation result, change CommonCfg.TxRate which
1987                 is the stable TX Rate we expect the Radio situation could sustained.
1988
1989                 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1990         Output:
1991                 CommonCfg.TxRate -
1992
1993         IRQL = DISPATCH_LEVEL
1994
1995         NOTE:
1996                 call this routine every second
1997         ==========================================================================
1998  */
1999 VOID MlmeDynamicTxRateSwitching(
2000         IN PRTMP_ADAPTER pAd)
2001 {
2002         UCHAR                                   UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2003         ULONG                                   i, AccuTxTotalCnt = 0, TxTotalCnt;
2004         ULONG                                   TxErrorRatio = 0;
2005         BOOLEAN                                 bTxRateChanged, bUpgradeQuality = FALSE;
2006         PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate = NULL;
2007         PUCHAR                                  pTable;
2008         UCHAR                                   TableSize = 0;
2009         UCHAR                                   InitTxRateIdx = 0, TrainUp, TrainDown;
2010         CHAR                                    Rssi, RssiOffset = 0;
2011         TX_STA_CNT1_STRUC               StaTx1;
2012         TX_STA_CNT0_STRUC               TxStaCnt0;
2013         ULONG                                   TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2014         MAC_TABLE_ENTRY                 *pEntry;
2015
2016         //
2017         // walk through MAC table, see if need to change AP's TX rate toward each entry
2018         //
2019         for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2020         {
2021                 pEntry = &pAd->MacTab.Content[i];
2022
2023                 // check if this entry need to switch rate automatically
2024                 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2025                         continue;
2026
2027                 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2028                 {
2029 #ifdef RT2860
2030                         Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2031 #endif
2032 #ifdef RT2870
2033                         Rssi = RTMPMaxRssi(pAd,
2034                                                            pAd->StaCfg.RssiSample.AvgRssi0,
2035                                                            pAd->StaCfg.RssiSample.AvgRssi1,
2036                                                            pAd->StaCfg.RssiSample.AvgRssi2);
2037 #endif
2038
2039                         // Update statistic counter
2040                         RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2041                         RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2042                         pAd->bUpdateBcnCntDone = TRUE;
2043                         TxRetransmit = StaTx1.field.TxRetransmit;
2044                         TxSuccess = StaTx1.field.TxSuccess;
2045                         TxFailCount = TxStaCnt0.field.TxFailCount;
2046                         TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2047
2048                         pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2049                         pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2050                         pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2051                         pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2052                         pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2053                         pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2054
2055                         // if no traffic in the past 1-sec period, don't change TX rate,
2056                         // but clear all bad history. because the bad history may affect the next
2057                         // Chariot throughput test
2058                         AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2059                                                  pAd->RalinkCounters.OneSecTxRetryOkCount +
2060                                                  pAd->RalinkCounters.OneSecTxFailCount;
2061
2062                         if (TxTotalCnt)
2063                                 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2064                 }
2065                 else
2066                 {
2067 #ifdef RT2860
2068                         Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2069 #endif
2070 #ifdef RT2870
2071                         if (INFRA_ON(pAd) && (i == 1))
2072                                 Rssi = RTMPMaxRssi(pAd,
2073                                                                    pAd->StaCfg.RssiSample.AvgRssi0,
2074                                                                    pAd->StaCfg.RssiSample.AvgRssi1,
2075                                                                    pAd->StaCfg.RssiSample.AvgRssi2);
2076                         else
2077                                 Rssi = RTMPMaxRssi(pAd,
2078                                                                    pEntry->RssiSample.AvgRssi0,
2079                                                                    pEntry->RssiSample.AvgRssi1,
2080                                                                    pEntry->RssiSample.AvgRssi2);
2081 #endif
2082
2083                         TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2084                                  pEntry->OneSecTxRetryOkCount +
2085                                  pEntry->OneSecTxFailCount;
2086
2087                         if (TxTotalCnt)
2088                                 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2089                 }
2090
2091                 CurrRateIdx = pEntry->CurrTxRateIndex;
2092
2093                 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2094
2095                 if (CurrRateIdx >= TableSize)
2096                 {
2097                         CurrRateIdx = TableSize - 1;
2098                 }
2099
2100                 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2101                 // So need to sync here.
2102                 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2103                 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2104                         //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2105                         )
2106                 {
2107
2108                         // Need to sync Real Tx rate and our record.
2109                         // Then return for next DRS.
2110                         pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2111                         pEntry->CurrTxRateIndex = InitTxRateIdx;
2112                         MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2113
2114                         // reset all OneSecTx counters
2115                         RESET_ONE_SEC_TX_CNT(pEntry);
2116                         continue;
2117                 }
2118
2119                 // decide the next upgrade rate and downgrade rate, if any
2120                 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2121                 {
2122                         UpRateIdx = CurrRateIdx + 1;
2123                         DownRateIdx = CurrRateIdx -1;
2124                 }
2125                 else if (CurrRateIdx == 0)
2126                 {
2127                         UpRateIdx = CurrRateIdx + 1;
2128                         DownRateIdx = CurrRateIdx;
2129                 }
2130                 else if (CurrRateIdx == (TableSize - 1))
2131                 {
2132                         UpRateIdx = CurrRateIdx;
2133                         DownRateIdx = CurrRateIdx - 1;
2134                 }
2135
2136                 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2137
2138                 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2139                 {
2140                         TrainUp         = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2141                         TrainDown       = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2142                 }
2143                 else
2144                 {
2145                         TrainUp         = pCurrTxRate->TrainUp;
2146                         TrainDown       = pCurrTxRate->TrainDown;
2147                 }
2148
2149                 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2150
2151                 //
2152                 // Keep the last time TxRateChangeAction status.
2153                 //
2154                 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2155
2156
2157
2158                 //
2159                 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2160                 //         (criteria copied from RT2500 for Netopia case)
2161                 //
2162                 if (TxTotalCnt <= 15)
2163                 {
2164                         CHAR    idx = 0;
2165                         UCHAR   TxRateIdx;
2166                         //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2167                         UCHAR   MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0,  MCS5 =0, MCS6 = 0, MCS7 = 0;
2168                 UCHAR   MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2169                         UCHAR   MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2170
2171                         // check the existence and index of each needed MCS
2172                         while (idx < pTable[0])
2173                         {
2174                                 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2175
2176                                 if (pCurrTxRate->CurrMCS == MCS_0)
2177                                 {
2178                                         MCS0 = idx;
2179                                 }
2180                                 else if (pCurrTxRate->CurrMCS == MCS_1)
2181                                 {
2182                                         MCS1 = idx;
2183                                 }
2184                                 else if (pCurrTxRate->CurrMCS == MCS_2)
2185                                 {
2186                                         MCS2 = idx;
2187                                 }
2188                                 else if (pCurrTxRate->CurrMCS == MCS_3)
2189                                 {
2190                                         MCS3 = idx;
2191                                 }
2192                                 else if (pCurrTxRate->CurrMCS == MCS_4)
2193                                 {
2194                                         MCS4 = idx;
2195                                 }
2196                     else if (pCurrTxRate->CurrMCS == MCS_5)
2197                     {
2198                         MCS5 = idx;
2199                     }
2200                     else if (pCurrTxRate->CurrMCS == MCS_6)
2201                     {
2202                         MCS6 = idx;
2203                     }
2204                                 //else if (pCurrTxRate->CurrMCS == MCS_7)
2205                                 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800))   // prevent the highest MCS using short GI when 1T and low throughput
2206                                 {
2207                                         MCS7 = idx;
2208                                 }
2209                                 else if (pCurrTxRate->CurrMCS == MCS_12)
2210                                 {
2211                                         MCS12 = idx;
2212                                 }
2213                                 else if (pCurrTxRate->CurrMCS == MCS_13)
2214                                 {
2215                                         MCS13 = idx;
2216                                 }
2217                                 else if (pCurrTxRate->CurrMCS == MCS_14)
2218                                 {
2219                                         MCS14 = idx;
2220                                 }
2221                                 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
2222                                 {
2223                                         MCS15 = idx;
2224                                 }
2225                                 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2226                                 {
2227                                         MCS20 = idx;
2228                                 }
2229                                 else if (pCurrTxRate->CurrMCS == MCS_21)
2230                                 {
2231                                         MCS21 = idx;
2232                                 }
2233                                 else if (pCurrTxRate->CurrMCS == MCS_22)
2234                                 {
2235                                         MCS22 = idx;
2236                                 }
2237                                 else if (pCurrTxRate->CurrMCS == MCS_23)
2238                                 {
2239                                         MCS23 = idx;
2240                                 }
2241                                 idx ++;
2242                         }
2243
2244                         if (pAd->LatchRfRegs.Channel <= 14)
2245                         {
2246                                 if (pAd->NicConfig2.field.ExternalLNAForG)
2247                                 {
2248                                         RssiOffset = 2;
2249                                 }
2250                                 else
2251                                 {
2252                                         RssiOffset = 5;
2253                                 }
2254                         }
2255                         else
2256                         {
2257                                 if (pAd->NicConfig2.field.ExternalLNAForA)
2258                                 {
2259                                         RssiOffset = 5;
2260                                 }
2261                                 else
2262                                 {
2263                                         RssiOffset = 8;
2264                                 }
2265                         }
2266
2267                         /*if (MCS15)*/
2268                         if ((pTable == RateSwitchTable11BGN3S) ||
2269                                 (pTable == RateSwitchTable11N3S) ||
2270                                 (pTable == RateSwitchTable))
2271                         {// N mode with 3 stream // 3*3
2272                                 if (MCS23 && (Rssi >= -70))
2273                                         TxRateIdx = MCS15;
2274                                 else if (MCS22 && (Rssi >= -72))
2275                                         TxRateIdx = MCS14;
2276                     else if (MCS21 && (Rssi >= -76))
2277                                         TxRateIdx = MCS13;
2278                                 else if (MCS20 && (Rssi >= -78))
2279                                         TxRateIdx = MCS12;
2280                         else if (MCS4 && (Rssi >= -82))
2281                                 TxRateIdx = MCS4;
2282                         else if (MCS3 && (Rssi >= -84))
2283                                 TxRateIdx = MCS3;
2284                         else if (MCS2 && (Rssi >= -86))
2285                                 TxRateIdx = MCS2;
2286                         else if (MCS1 && (Rssi >= -88))
2287                                 TxRateIdx = MCS1;
2288                         else
2289                                 TxRateIdx = MCS0;
2290                 }
2291                 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2292                         {// N mode with 2 stream
2293                                 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2294                                         TxRateIdx = MCS15;
2295                                 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2296                                         TxRateIdx = MCS14;
2297                                 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2298                                         TxRateIdx = MCS13;
2299                                 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2300                                         TxRateIdx = MCS12;
2301                                 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2302                                         TxRateIdx = MCS4;
2303                                 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2304                                         TxRateIdx = MCS3;
2305                                 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2306                                         TxRateIdx = MCS2;
2307                                 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2308                                         TxRateIdx = MCS1;
2309                                 else
2310                                         TxRateIdx = MCS0;
2311                         }
2312                         else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2313                         {// N mode with 1 stream
2314                                 if (MCS7 && (Rssi > (-72+RssiOffset)))
2315                                         TxRateIdx = MCS7;
2316                                 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2317                                         TxRateIdx = MCS6;
2318                                 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2319                                         TxRateIdx = MCS5;
2320                                 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2321                                         TxRateIdx = MCS4;
2322                                 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2323                                         TxRateIdx = MCS3;
2324                                 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2325                                         TxRateIdx = MCS2;
2326                                 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2327                                         TxRateIdx = MCS1;
2328                                 else
2329                                         TxRateIdx = MCS0;
2330                         }
2331                         else
2332                         {// Legacy mode
2333                                 if (MCS7 && (Rssi > -70))
2334                                         TxRateIdx = MCS7;
2335                                 else if (MCS6 && (Rssi > -74))
2336                                         TxRateIdx = MCS6;
2337                                 else if (MCS5 && (Rssi > -78))
2338                                         TxRateIdx = MCS5;
2339                                 else if (MCS4 && (Rssi > -82))
2340                                         TxRateIdx = MCS4;
2341                                 else if (MCS4 == 0)     // for B-only mode
2342                                         TxRateIdx = MCS3;
2343                                 else if (MCS3 && (Rssi > -85))
2344                                         TxRateIdx = MCS3;
2345                                 else if (MCS2 && (Rssi > -87))
2346                                         TxRateIdx = MCS2;
2347                                 else if (MCS1 && (Rssi > -90))
2348                                         TxRateIdx = MCS1;
2349                                 else
2350                                         TxRateIdx = MCS0;
2351                         }
2352
2353                         {
2354                                 pEntry->CurrTxRateIndex = TxRateIdx;
2355                                 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2356                                 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2357                         }
2358
2359                         NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2360                         NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2361                         pEntry->fLastSecAccordingRSSI = TRUE;
2362                         // reset all OneSecTx counters
2363                         RESET_ONE_SEC_TX_CNT(pEntry);
2364
2365                         continue;
2366                 }
2367
2368                 if (pEntry->fLastSecAccordingRSSI == TRUE)
2369                 {
2370                         pEntry->fLastSecAccordingRSSI = FALSE;
2371                         pEntry->LastSecTxRateChangeAction = 0;
2372                         // reset all OneSecTx counters
2373                         RESET_ONE_SEC_TX_CNT(pEntry);
2374
2375                         continue;
2376                 }
2377
2378                 do
2379                 {
2380                         BOOLEAN bTrainUpDown = FALSE;
2381
2382                         pEntry->CurrTxRateStableTime ++;
2383
2384                         // downgrade TX quality if PER >= Rate-Down threshold
2385                         if (TxErrorRatio >= TrainDown)
2386                         {
2387                                 bTrainUpDown = TRUE;
2388                                 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2389                         }
2390                         // upgrade TX quality if PER <= Rate-Up threshold
2391                         else if (TxErrorRatio <= TrainUp)
2392                         {
2393                                 bTrainUpDown = TRUE;
2394                                 bUpgradeQuality = TRUE;
2395                                 if (pEntry->TxQuality[CurrRateIdx])
2396                                         pEntry->TxQuality[CurrRateIdx] --;  // quality very good in CurrRate
2397
2398                                 if (pEntry->TxRateUpPenalty)
2399                                         pEntry->TxRateUpPenalty --;
2400                                 else if (pEntry->TxQuality[UpRateIdx])
2401                                         pEntry->TxQuality[UpRateIdx] --;    // may improve next UP rate's quality
2402                         }
2403
2404                         pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2405
2406                         if (bTrainUpDown)
2407                         {
2408                                 // perform DRS - consider TxRate Down first, then rate up.
2409                                 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2410                                 {
2411                                         pEntry->CurrTxRateIndex = DownRateIdx;
2412                                 }
2413                                 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2414                                 {
2415                                         pEntry->CurrTxRateIndex = UpRateIdx;
2416                                 }
2417                         }
2418                 } while (FALSE);
2419
2420                 // if rate-up happen, clear all bad history of all TX rates
2421                 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2422                 {
2423                         pEntry->CurrTxRateStableTime = 0;
2424                         pEntry->TxRateUpPenalty = 0;
2425                         pEntry->LastSecTxRateChangeAction = 1; // rate UP
2426                         NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2427                         NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2428
2429                         //
2430                         // For TxRate fast train up
2431                         //
2432                         if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2433                         {
2434                                 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2435
2436                                 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2437                         }
2438                         bTxRateChanged = TRUE;
2439                 }
2440                 // if rate-down happen, only clear DownRate's bad history
2441                 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2442                 {
2443                         pEntry->CurrTxRateStableTime = 0;
2444                         pEntry->TxRateUpPenalty = 0;           // no penalty
2445                         pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2446                         pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2447                         pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2448
2449                         //
2450                         // For TxRate fast train down
2451                         //
2452                         if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2453                         {
2454                                 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2455
2456                                 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2457                         }
2458                         bTxRateChanged = TRUE;
2459                 }
2460                 else
2461                 {
2462                         pEntry->LastSecTxRateChangeAction = 0; // rate no change
2463                         bTxRateChanged = FALSE;
2464                 }
2465
2466                 pEntry->LastTxOkCount = TxSuccess;
2467
2468                 // reset all OneSecTx counters
2469                 RESET_ONE_SEC_TX_CNT(pEntry);
2470
2471                 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2472                 if (bTxRateChanged && pNextTxRate)
2473                 {
2474                         MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2475                 }
2476         }
2477 }
2478
2479 /*
2480         ========================================================================
2481         Routine Description:
2482                 Station side, Auto TxRate faster train up timer call back function.
2483
2484         Arguments:
2485                 SystemSpecific1                 - Not used.
2486                 FunctionContext                 - Pointer to our Adapter context.
2487                 SystemSpecific2                 - Not used.
2488                 SystemSpecific3                 - Not used.
2489
2490         Return Value:
2491                 None
2492
2493         ========================================================================
2494 */
2495 VOID StaQuickResponeForRateUpExec(
2496         IN PVOID SystemSpecific1,
2497         IN PVOID FunctionContext,
2498         IN PVOID SystemSpecific2,
2499         IN PVOID SystemSpecific3)
2500 {
2501         PRTMP_ADAPTER                   pAd = (PRTMP_ADAPTER)FunctionContext;
2502         UCHAR                                   UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2503         ULONG                                   TxTotalCnt;
2504         ULONG                                   TxErrorRatio = 0;
2505 #ifdef RT2860
2506         BOOLEAN                                 bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2507 #endif
2508 #ifdef RT2870
2509         BOOLEAN                                 bTxRateChanged; //, bUpgradeQuality = FALSE;
2510 #endif
2511         PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate = NULL;
2512         PUCHAR                                  pTable;
2513         UCHAR                                   TableSize = 0;
2514         UCHAR                                   InitTxRateIdx = 0, TrainUp, TrainDown;
2515         TX_STA_CNT1_STRUC               StaTx1;
2516         TX_STA_CNT0_STRUC               TxStaCnt0;
2517         CHAR                                    Rssi, ratio;
2518         ULONG                                   TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2519         MAC_TABLE_ENTRY                 *pEntry;
2520         ULONG                                   i;
2521
2522         pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2523
2524     //
2525     // walk through MAC table, see if need to change AP's TX rate toward each entry
2526     //
2527         for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2528         {
2529                 pEntry = &pAd->MacTab.Content[i];
2530
2531                 // check if this entry need to switch rate automatically
2532                 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2533                         continue;
2534
2535 #ifdef RT2860
2536                 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2537             if (pAd->Antenna.field.TxPath > 1)
2538                         Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2539                 else
2540                         Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2541 #endif
2542 #ifdef RT2870
2543                 if (INFRA_ON(pAd) && (i == 1))
2544                         Rssi = RTMPMaxRssi(pAd,
2545                                                            pAd->StaCfg.RssiSample.AvgRssi0,
2546                                                            pAd->StaCfg.RssiSample.AvgRssi1,
2547                                                            pAd->StaCfg.RssiSample.AvgRssi2);
2548                 else
2549                         Rssi = RTMPMaxRssi(pAd,
2550                                                            pEntry->RssiSample.AvgRssi0,
2551                                                            pEntry->RssiSample.AvgRssi1,
2552                                                            pEntry->RssiSample.AvgRssi2);
2553 #endif
2554
2555                 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2556
2557                         MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2558
2559                 // decide the next upgrade rate and downgrade rate, if any
2560                 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2561                 {
2562                         UpRateIdx = CurrRateIdx + 1;
2563                         DownRateIdx = CurrRateIdx -1;
2564                 }
2565                 else if (CurrRateIdx == 0)
2566                 {
2567                         UpRateIdx = CurrRateIdx + 1;
2568                         DownRateIdx = CurrRateIdx;
2569                 }
2570                 else if (CurrRateIdx == (TableSize - 1))
2571                 {
2572                         UpRateIdx = CurrRateIdx;
2573                         DownRateIdx = CurrRateIdx - 1;
2574                 }
2575
2576                 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2577
2578                 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2579                 {
2580                         TrainUp         = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2581                         TrainDown       = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2582                 }
2583                 else
2584                 {
2585                         TrainUp         = pCurrTxRate->TrainUp;
2586                         TrainDown       = pCurrTxRate->TrainDown;
2587                 }
2588
2589                 if (pAd->MacTab.Size == 1)
2590                 {
2591                         // Update statistic counter
2592                         RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2593                         RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2594
2595                         TxRetransmit = StaTx1.field.TxRetransmit;
2596                         TxSuccess = StaTx1.field.TxSuccess;
2597                         TxFailCount = TxStaCnt0.field.TxFailCount;
2598                         TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2599
2600                         pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2601                         pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2602                         pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2603                         pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2604                         pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2605                         pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2606
2607                         if (TxTotalCnt)
2608                                 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2609                 }
2610                 else
2611                 {
2612                         TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2613                                  pEntry->OneSecTxRetryOkCount +
2614                                  pEntry->OneSecTxFailCount;
2615
2616                         if (TxTotalCnt)
2617                                 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2618                 }
2619
2620
2621                 //
2622                 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2623                 //         (criteria copied from RT2500 for Netopia case)
2624                 //
2625                 if (TxTotalCnt <= 12)
2626                 {
2627                         NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2628                         NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2629
2630                         if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2631                         {
2632                                 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2633                                 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2634                         }
2635                         else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2636                         {
2637                                 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2638                         }
2639
2640                         DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2641                         return;
2642                 }
2643
2644                 do
2645                 {
2646                         ULONG OneSecTxNoRetryOKRationCount;
2647
2648                         if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2649                                 ratio = 5;
2650                         else
2651                                 ratio = 4;
2652
2653                         // downgrade TX quality if PER >= Rate-Down threshold
2654                         if (TxErrorRatio >= TrainDown)
2655                         {
2656                                 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2657                         }
2658
2659                         pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2660
2661                         OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2662
2663                         // perform DRS - consider TxRate Down first, then rate up.
2664                         if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2665                         {
2666                                 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2667                                 {
2668                                         pAd->CommonCfg.TxRateIndex = DownRateIdx;
2669                                         pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2670
2671                                 }
2672
2673                         }
2674                         else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2675                         {
2676                                 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2677                                 {
2678
2679                                 }
2680                                 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2681                                 {
2682                                         pAd->CommonCfg.TxRateIndex = UpRateIdx;
2683                                 }
2684                         }
2685                 }while (FALSE);
2686
2687                 // if rate-up happen, clear all bad history of all TX rates
2688                 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2689                 {
2690                         pAd->DrsCounters.TxRateUpPenalty = 0;
2691                         NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2692                         NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2693 #ifdef RT2870
2694                         bTxRateChanged = TRUE;
2695 #endif
2696                 }
2697                 // if rate-down happen, only clear DownRate's bad history
2698                 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2699                 {
2700                         DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2701
2702                         pAd->DrsCounters.TxRateUpPenalty = 0;           // no penalty
2703                         pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2704                         pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2705 #ifdef RT2870
2706                         bTxRateChanged = TRUE;
2707 #endif
2708                 }
2709                 else
2710                 {
2711                         bTxRateChanged = FALSE;
2712                 }
2713
2714                 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2715                 if (bTxRateChanged && pNextTxRate)
2716                 {
2717                         MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2718                 }
2719         }
2720 }
2721
2722 /*
2723         ==========================================================================
2724         Description:
2725                 This routine is executed periodically inside MlmePeriodicExec() after
2726                 association with an AP.
2727                 It checks if StaCfg.Psm is consistent with user policy (recorded in
2728                 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2729                 there're some conditions to consider:
2730                 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2731                    the time when Mibss==TRUE
2732                 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2733                    if outgoing traffic available in TxRing or MgmtRing.
2734         Output:
2735                 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2736
2737         IRQL = DISPATCH_LEVEL
2738
2739         ==========================================================================
2740  */
2741 VOID MlmeCheckPsmChange(
2742         IN PRTMP_ADAPTER pAd,
2743         IN ULONG        Now32)
2744 {
2745         ULONG   PowerMode;
2746
2747         // condition -
2748         // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2749         // 2. user wants either MAX_PSP or FAST_PSP
2750         // 3. but current psm is not in PWR_SAVE
2751         // 4. CNTL state machine is not doing SCANning
2752         // 5. no TX SUCCESS event for the past 1-sec period
2753 #ifdef NDIS51_MINIPORT
2754         if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2755                 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2756         else
2757 #endif
2758                 PowerMode = pAd->StaCfg.WindowsPowerMode;
2759
2760         if (INFRA_ON(pAd) &&
2761                 (PowerMode != Ndis802_11PowerModeCAM) &&
2762                 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2763 #ifdef RT2860
2764                 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2765 #else
2766                 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2767 #endif
2768         {
2769                 // add by johnli, use Rx OK data count per second to calculate throughput
2770                 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2771                 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2772                 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2773                                 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2774                         ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2775                         (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2776                 {
2777                                 // Get this time
2778                         NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2779                         pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2780                         MlmeSetPsmBit(pAd, PWR_SAVE);
2781                         if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2782                         {
2783                                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2784                         }
2785                         else
2786                         {
2787                                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2788                         }
2789                 }
2790         }
2791 }
2792
2793 // IRQL = PASSIVE_LEVEL
2794 // IRQL = DISPATCH_LEVEL
2795 VOID MlmeSetPsmBit(
2796         IN PRTMP_ADAPTER pAd,
2797         IN USHORT psm)
2798 {
2799         AUTO_RSP_CFG_STRUC csr4;
2800
2801         pAd->StaCfg.Psm = psm;
2802         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2803         csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2804         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2805
2806         DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2807 }
2808
2809 // IRQL = DISPATCH_LEVEL
2810 VOID MlmeSetTxPreamble(
2811         IN PRTMP_ADAPTER pAd,
2812         IN USHORT TxPreamble)
2813 {
2814         AUTO_RSP_CFG_STRUC csr4;
2815
2816         //
2817         // Always use Long preamble before verifiation short preamble functionality works well.
2818         // Todo: remove the following line if short preamble functionality works
2819         //
2820         //TxPreamble = Rt802_11PreambleLong;
2821
2822         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2823         if (TxPreamble == Rt802_11PreambleLong)
2824         {
2825                 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2826                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2827                 csr4.field.AutoResponderPreamble = 0;
2828         }
2829         else
2830         {
2831                 // NOTE: 1Mbps should always use long preamble
2832                 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2833                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2834                 csr4.field.AutoResponderPreamble = 1;
2835         }
2836
2837         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2838 }
2839
2840 /*
2841     ==========================================================================
2842     Description:
2843         Update basic rate bitmap
2844     ==========================================================================
2845  */
2846
2847 VOID UpdateBasicRateBitmap(
2848     IN  PRTMP_ADAPTER   pAdapter)
2849 {
2850     INT  i, j;
2851                   /* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
2852     UCHAR rate[] = { 2, 4,  11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2853     UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2854     UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2855     ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2856
2857
2858     /* if A mode, always use fix BasicRateBitMap */
2859     //if (pAdapter->CommonCfg.Channel == PHY_11A)
2860         if (pAdapter->CommonCfg.Channel > 14)
2861         pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2862     /* End of if */
2863
2864     if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2865     {
2866         /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2867         return;
2868     } /* End of if */
2869
2870     for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2871     {
2872         sup_p[i] &= 0x7f;
2873         ext_p[i] &= 0x7f;
2874     } /* End of for */
2875
2876     for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2877     {
2878         if (bitmap & (1 << i))
2879         {
2880             for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2881             {
2882                 if (sup_p[j] == rate[i])
2883                     sup_p[j] |= 0x80;
2884                 /* End of if */
2885             } /* End of for */
2886
2887             for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2888             {
2889                 if (ext_p[j] == rate[i])
2890                     ext_p[j] |= 0x80;
2891                 /* End of if */
2892             } /* End of for */
2893         } /* End of if */
2894     } /* End of for */
2895 } /* End of UpdateBasicRateBitmap */
2896
2897 // IRQL = PASSIVE_LEVEL
2898 // IRQL = DISPATCH_LEVEL
2899 // bLinkUp is to identify the inital link speed.
2900 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2901 VOID MlmeUpdateTxRates(
2902         IN PRTMP_ADAPTER                pAd,
2903         IN      BOOLEAN                         bLinkUp,
2904         IN      UCHAR                           apidx)
2905 {
2906         int i, num;
2907         UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2908         UCHAR MinSupport = RATE_54;
2909         ULONG BasicRateBitmap = 0;
2910         UCHAR CurrBasicRate = RATE_1;
2911         UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2912         PHTTRANSMIT_SETTING             pHtPhy = NULL;
2913         PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
2914         PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
2915         BOOLEAN                                 *auto_rate_cur_p;
2916         UCHAR                                   HtMcs = MCS_AUTO;
2917
2918         // find max desired rate
2919         UpdateBasicRateBitmap(pAd);
2920
2921         num = 0;
2922         auto_rate_cur_p = NULL;
2923         for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2924         {
2925                 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2926                 {
2927                         case 2:  Rate = RATE_1;   num++;   break;
2928                         case 4:  Rate = RATE_2;   num++;   break;
2929                         case 11: Rate = RATE_5_5; num++;   break;
2930                         case 22: Rate = RATE_11;  num++;   break;
2931                         case 12: Rate = RATE_6;   num++;   break;
2932                         case 18: Rate = RATE_9;   num++;   break;
2933                         case 24: Rate = RATE_12;  num++;   break;
2934                         case 36: Rate = RATE_18;  num++;   break;
2935                         case 48: Rate = RATE_24;  num++;   break;
2936                         case 72: Rate = RATE_36;  num++;   break;
2937                         case 96: Rate = RATE_48;  num++;   break;
2938                         case 108: Rate = RATE_54; num++;   break;
2939                         //default: Rate = RATE_1;   break;
2940                 }
2941                 if (MaxDesire < Rate)  MaxDesire = Rate;
2942         }
2943
2944 //===========================================================================
2945 //===========================================================================
2946         {
2947                 pHtPhy          = &pAd->StaCfg.HTPhyMode;
2948                 pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
2949                 pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
2950
2951                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2952                 HtMcs           = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2953
2954                 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2955                         (pAd->CommonCfg.PhyMode == PHY_11B) &&
2956                         (MaxDesire > RATE_11))
2957                 {
2958                         MaxDesire = RATE_11;
2959                 }
2960         }
2961
2962         pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2963         pMinHtPhy->word = 0;
2964         pMaxHtPhy->word = 0;
2965         pHtPhy->word = 0;
2966
2967         // Auto rate switching is enabled only if more than one DESIRED RATES are
2968         // specified; otherwise disabled
2969         if (num <= 1)
2970         {
2971                 *auto_rate_cur_p = FALSE;
2972         }
2973         else
2974         {
2975                 *auto_rate_cur_p = TRUE;
2976         }
2977
2978 #if 1
2979         if (HtMcs != MCS_AUTO)
2980         {
2981                 *auto_rate_cur_p = FALSE;
2982         }
2983         else
2984         {
2985                 *auto_rate_cur_p = TRUE;
2986         }
2987 #endif
2988
2989         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2990         {
2991                 pSupRate = &pAd->StaActive.SupRate[0];
2992                 pExtRate = &pAd->StaActive.ExtRate[0];
2993                 SupRateLen = pAd->StaActive.SupRateLen;
2994                 ExtRateLen = pAd->StaActive.ExtRateLen;
2995         }
2996         else
2997         {
2998                 pSupRate = &pAd->CommonCfg.SupRate[0];
2999                 pExtRate = &pAd->CommonCfg.ExtRate[0];
3000                 SupRateLen = pAd->CommonCfg.SupRateLen;
3001                 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3002         }
3003
3004         // find max supported rate
3005         for (i=0; i<SupRateLen; i++)
3006         {
3007                 switch (pSupRate[i] & 0x7f)
3008                 {
3009                         case 2:   Rate = RATE_1;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
3010                         case 4:   Rate = RATE_2;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
3011                         case 11:  Rate = RATE_5_5;      if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
3012                         case 22:  Rate = RATE_11;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
3013                         case 12:  Rate = RATE_6;        /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
3014                         case 18:  Rate = RATE_9;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
3015                         case 24:  Rate = RATE_12;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
3016                         case 36:  Rate = RATE_18;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
3017                         case 48:  Rate = RATE_24;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
3018                         case 72:  Rate = RATE_36;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
3019                         case 96:  Rate = RATE_48;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
3020                         case 108: Rate = RATE_54;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
3021                         default:  Rate = RATE_1;        break;
3022                 }
3023                 if (MaxSupport < Rate)  MaxSupport = Rate;
3024
3025                 if (MinSupport > Rate) MinSupport = Rate;
3026         }
3027
3028         for (i=0; i<ExtRateLen; i++)
3029         {
3030                 switch (pExtRate[i] & 0x7f)
3031                 {
3032                         case 2:   Rate = RATE_1;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
3033                         case 4:   Rate = RATE_2;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
3034                         case 11:  Rate = RATE_5_5;      if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
3035                         case 22:  Rate = RATE_11;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
3036                         case 12:  Rate = RATE_6;        /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
3037                         case 18:  Rate = RATE_9;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
3038                         case 24:  Rate = RATE_12;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
3039                         case 36:  Rate = RATE_18;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
3040                         case 48:  Rate = RATE_24;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
3041                         case 72:  Rate = RATE_36;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
3042                         case 96:  Rate = RATE_48;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
3043                         case 108: Rate = RATE_54;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
3044                         default:  Rate = RATE_1;        break;
3045                 }
3046                 if (MaxSupport < Rate)  MaxSupport = Rate;
3047
3048                 if (MinSupport > Rate) MinSupport = Rate;
3049         }
3050
3051         RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3052
3053         // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3054         // the DURATION field of outgoing uniicast DATA/MGMT frame
3055         for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3056         {
3057                 if (BasicRateBitmap & (0x01 << i))
3058                         CurrBasicRate = (UCHAR)i;
3059                 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3060         }
3061
3062         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3063         // max tx rate = min {max desire rate, max supported rate}
3064         if (MaxSupport < MaxDesire)
3065                 pAd->CommonCfg.MaxTxRate = MaxSupport;
3066         else
3067                 pAd->CommonCfg.MaxTxRate = MaxDesire;
3068
3069         pAd->CommonCfg.MinTxRate = MinSupport;
3070         if (*auto_rate_cur_p)
3071         {
3072                 short dbm = 0;
3073
3074                 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3075
3076                 if (bLinkUp == TRUE)
3077                         pAd->CommonCfg.TxRate = RATE_24;
3078                 else
3079                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3080
3081                 if (dbm < -75)
3082                         pAd->CommonCfg.TxRate = RATE_11;
3083                 else if (dbm < -70)
3084                         pAd->CommonCfg.TxRate = RATE_24;
3085
3086                 // should never exceed MaxTxRate (consider 11B-only mode)
3087                 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3088                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3089
3090                 pAd->CommonCfg.TxRateIndex = 0;
3091         }
3092         else
3093         {
3094                 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3095                 pHtPhy->field.MCS       = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3096                 pHtPhy->field.MODE      = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3097
3098                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC    = pHtPhy->field.STBC;
3099                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3100                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS             = pHtPhy->field.MCS;
3101                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE    = pHtPhy->field.MODE;
3102         }
3103
3104         if (pAd->CommonCfg.TxRate <= RATE_11)
3105         {
3106                 pMaxHtPhy->field.MODE = MODE_CCK;
3107                 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3108                 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3109         }
3110         else
3111         {
3112                 pMaxHtPhy->field.MODE = MODE_OFDM;
3113                 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3114                 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3115                         {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3116                 else
3117                         {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3118         }
3119
3120         pHtPhy->word = (pMaxHtPhy->word);
3121         if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3122         {
3123                         pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3124                         pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3125                         pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3126         }
3127         else
3128         {
3129                 switch (pAd->CommonCfg.PhyMode)
3130                 {
3131                         case PHY_11BG_MIXED:
3132                         case PHY_11B:
3133                         case PHY_11BGN_MIXED:
3134                                 pAd->CommonCfg.MlmeRate = RATE_1;
3135                                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3136                                 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3137                                 pAd->CommonCfg.RtsRate = RATE_11;
3138                                 break;
3139                         case PHY_11G:
3140                         case PHY_11A:
3141                         case PHY_11AGN_MIXED:
3142                         case PHY_11GN_MIXED:
3143                         case PHY_11N_2_4G:
3144                         case PHY_11AN_MIXED:
3145                         case PHY_11N_5G:
3146                                 pAd->CommonCfg.MlmeRate = RATE_6;
3147                                 pAd->CommonCfg.RtsRate = RATE_6;
3148                                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3149                                 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3150                                 break;
3151                         case PHY_11ABG_MIXED:
3152                         case PHY_11ABGN_MIXED:
3153                                 if (pAd->CommonCfg.Channel <= 14)
3154                                 {
3155                                         pAd->CommonCfg.MlmeRate = RATE_1;
3156                                         pAd->CommonCfg.RtsRate = RATE_1;
3157                                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3158                                         pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3159                                 }
3160                                 else
3161                                 {
3162                                         pAd->CommonCfg.MlmeRate = RATE_6;
3163                                         pAd->CommonCfg.RtsRate = RATE_6;
3164                                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3165                                         pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3166                                 }
3167                                 break;
3168                         default: // error
3169                                 pAd->CommonCfg.MlmeRate = RATE_6;
3170                                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3171                                 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3172                                 pAd->CommonCfg.RtsRate = RATE_1;
3173                                 break;
3174                 }
3175                 //
3176                 // Keep Basic Mlme Rate.
3177                 //
3178                 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3179                 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3180                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3181                 else
3182                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3183                 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3184         }
3185
3186         DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3187                          RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3188                          /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3189         DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3190                          RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3191         DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3192                          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 ));
3193 }
3194
3195 /*
3196         ==========================================================================
3197         Description:
3198                 This function update HT Rate setting.
3199                 Input Wcid value is valid for 2 case :
3200                 1. it's used for Station in infra mode that copy AP rate to Mactable.
3201                 2. OR Station   in adhoc mode to copy peer's HT rate to Mactable.
3202
3203         IRQL = DISPATCH_LEVEL
3204
3205         ==========================================================================
3206  */
3207 VOID MlmeUpdateHtTxRates(
3208         IN PRTMP_ADAPTER                pAd,
3209         IN      UCHAR                           apidx)
3210 {
3211         UCHAR   StbcMcs; //j, StbcMcs, bitmask;
3212         CHAR    i; // 3*3
3213         RT_HT_CAPABILITY        *pRtHtCap = NULL;
3214         RT_HT_PHY_INFO          *pActiveHtPhy = NULL;
3215         ULONG           BasicMCS;
3216         UCHAR j, bitmask;
3217         PRT_HT_PHY_INFO                 pDesireHtPhy = NULL;
3218         PHTTRANSMIT_SETTING             pHtPhy = NULL;
3219         PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
3220         PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
3221         BOOLEAN                                 *auto_rate_cur_p;
3222
3223         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3224
3225         auto_rate_cur_p = NULL;
3226
3227         {
3228                 pDesireHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
3229                 pActiveHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
3230                 pHtPhy          = &pAd->StaCfg.HTPhyMode;
3231                 pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
3232                 pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
3233
3234                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3235         }
3236
3237         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3238         {
3239                 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3240                         return;
3241
3242                 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3243                 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3244                 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3245                 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3246                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3247                         pMaxHtPhy->field.STBC = STBC_USE;
3248                 else
3249                         pMaxHtPhy->field.STBC = STBC_NONE;
3250         }
3251         else
3252         {
3253                 if (pDesireHtPhy->bHtEnable == FALSE)
3254                         return;
3255
3256                 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3257                 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3258                 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3259                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3260                         pMaxHtPhy->field.STBC = STBC_USE;
3261                 else
3262                         pMaxHtPhy->field.STBC = STBC_NONE;
3263         }
3264
3265         // Decide MAX ht rate.
3266         if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3267                 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3268         else
3269                 pMaxHtPhy->field.MODE = MODE_HTMIX;
3270
3271     if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3272                 pMaxHtPhy->field.BW = BW_40;
3273         else
3274                 pMaxHtPhy->field.BW = BW_20;
3275
3276     if (pMaxHtPhy->field.BW == BW_20)
3277                 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3278         else
3279                 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3280
3281         for (i=23; i>=0; i--) // 3*3
3282         {
3283                 j = i/8;
3284                 bitmask = (1<<(i-(j*8)));
3285
3286                 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3287                 {
3288                         pMaxHtPhy->field.MCS = i;
3289                         break;
3290                 }
3291
3292                 if (i==0)
3293                         break;
3294         }
3295
3296         // Copy MIN ht rate.  rt2860???
3297         pMinHtPhy->field.BW = BW_20;
3298         pMinHtPhy->field.MCS = 0;
3299         pMinHtPhy->field.STBC = 0;
3300         pMinHtPhy->field.ShortGI = 0;
3301         //If STA assigns fixed rate. update to fixed here.
3302         if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3303         {
3304                 if (pDesireHtPhy->MCSSet[4] != 0)
3305                 {
3306                         pMaxHtPhy->field.MCS = 32;
3307                         pMinHtPhy->field.MCS = 32;
3308                         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3309                 }
3310
3311                 for (i=23; (CHAR)i >= 0; i--) // 3*3
3312                 {
3313                         j = i/8;
3314                         bitmask = (1<<(i-(j*8)));
3315                         if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3316                         {
3317                                 pMaxHtPhy->field.MCS = i;
3318                                 pMinHtPhy->field.MCS = i;
3319                                 break;
3320                         }
3321                         if (i==0)
3322                                 break;
3323                 }
3324         }
3325
3326         // Decide ht rate
3327         pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3328         pHtPhy->field.BW = pMaxHtPhy->field.BW;
3329         pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3330         pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3331         pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3332
3333         // use default now. rt2860
3334         if (pDesireHtPhy->MCSSet[0] != 0xff)
3335                 *auto_rate_cur_p = FALSE;
3336         else
3337                 *auto_rate_cur_p = TRUE;
3338
3339         DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3340         DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3341                 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3342         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3343 }
3344
3345 // IRQL = DISPATCH_LEVEL
3346 VOID MlmeRadioOff(
3347         IN PRTMP_ADAPTER pAd)
3348 {
3349         RT28XX_MLME_RADIO_OFF(pAd);
3350 }
3351
3352 // IRQL = DISPATCH_LEVEL
3353 VOID MlmeRadioOn(
3354         IN PRTMP_ADAPTER pAd)
3355 {
3356         RT28XX_MLME_RADIO_ON(pAd);
3357 }
3358
3359 // ===========================================================================================
3360 // bss_table.c
3361 // ===========================================================================================
3362
3363
3364 /*! \brief initialize BSS table
3365  *      \param p_tab pointer to the table
3366  *      \return none
3367  *      \pre
3368  *      \post
3369
3370  IRQL = PASSIVE_LEVEL
3371  IRQL = DISPATCH_LEVEL
3372
3373  */
3374 VOID BssTableInit(
3375         IN BSS_TABLE *Tab)
3376 {
3377         int i;
3378
3379         Tab->BssNr = 0;
3380     Tab->BssOverlapNr = 0;
3381         for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3382         {
3383                 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3384                 Tab->BssEntry[i].Rssi = -127;   // initial the rssi as a minimum value
3385         }
3386 }
3387
3388 VOID BATableInit(
3389         IN PRTMP_ADAPTER pAd,
3390     IN BA_TABLE *Tab)
3391 {
3392         int i;
3393
3394         Tab->numAsOriginator = 0;
3395         Tab->numAsRecipient = 0;
3396         NdisAllocateSpinLock(&pAd->BATabLock);
3397         for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3398         {
3399                 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3400                 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3401         }
3402         for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3403         {
3404                 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3405         }
3406 }
3407
3408 /*! \brief search the BSS table by SSID
3409  *      \param p_tab pointer to the bss table
3410  *      \param ssid SSID string
3411  *      \return index of the table, BSS_NOT_FOUND if not in the table
3412  *      \pre
3413  *      \post
3414  *      \note search by sequential search
3415
3416  IRQL = DISPATCH_LEVEL
3417
3418  */
3419 ULONG BssTableSearch(
3420         IN BSS_TABLE *Tab,
3421         IN PUCHAR        pBssid,
3422         IN UCHAR         Channel)
3423 {
3424         UCHAR i;
3425
3426         for (i = 0; i < Tab->BssNr; i++)
3427         {
3428                 //
3429                 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3430                 // We should distinguish this case.
3431                 //
3432                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3433                          ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3434                         MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3435                 {
3436                         return i;
3437                 }
3438         }
3439         return (ULONG)BSS_NOT_FOUND;
3440 }
3441
3442 ULONG BssSsidTableSearch(
3443         IN BSS_TABLE *Tab,
3444         IN PUCHAR        pBssid,
3445         IN PUCHAR        pSsid,
3446         IN UCHAR         SsidLen,
3447         IN UCHAR         Channel)
3448 {
3449         UCHAR i;
3450
3451         for (i = 0; i < Tab->BssNr; i++)
3452         {
3453                 //
3454                 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3455                 // We should distinguish this case.
3456                 //
3457                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3458                          ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3459                         MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3460                         SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3461                 {
3462                         return i;
3463                 }
3464         }
3465         return (ULONG)BSS_NOT_FOUND;
3466 }
3467
3468 ULONG BssTableSearchWithSSID(
3469         IN BSS_TABLE *Tab,
3470         IN PUCHAR        Bssid,
3471         IN PUCHAR        pSsid,
3472         IN UCHAR         SsidLen,
3473         IN UCHAR         Channel)
3474 {
3475         UCHAR i;
3476
3477         for (i = 0; i < Tab->BssNr; i++)
3478         {
3479                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3480                         ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3481                         MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3482                         (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3483                         (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3484                         (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3485                 {
3486                         return i;
3487                 }
3488         }
3489         return (ULONG)BSS_NOT_FOUND;
3490 }
3491
3492 // IRQL = DISPATCH_LEVEL
3493 VOID BssTableDeleteEntry(
3494         IN OUT  BSS_TABLE *Tab,
3495         IN              PUCHAR    pBssid,
3496         IN              UCHAR     Channel)
3497 {
3498         UCHAR i, j;
3499
3500         for (i = 0; i < Tab->BssNr; i++)
3501         {
3502                 if ((Tab->BssEntry[i].Channel == Channel) &&
3503                         (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3504                 {
3505                         for (j = i; j < Tab->BssNr - 1; j++)
3506                         {
3507                                 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3508                         }
3509                         NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3510                         Tab->BssNr -= 1;
3511                         return;
3512                 }
3513         }
3514 }
3515
3516 /*
3517         ========================================================================
3518         Routine Description:
3519                 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3520
3521         Arguments:
3522         // IRQL = DISPATCH_LEVEL
3523         ========================================================================
3524 */
3525 VOID BATableDeleteORIEntry(
3526         IN OUT  PRTMP_ADAPTER pAd,
3527         IN              BA_ORI_ENTRY    *pBAORIEntry)
3528 {
3529
3530         if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3531         {
3532                 NdisAcquireSpinLock(&pAd->BATabLock);
3533                 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3534                 {
3535                         pAd->BATable.numAsOriginator -= 1;
3536                         DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3537                         // Erase Bitmap flag.
3538                 }
3539                 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) ));       // If STA mode,  erase flag here
3540                 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;    // If STA mode,  erase flag here
3541                 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3542                 pBAORIEntry->Token = 1;
3543                 // Not clear Sequence here.
3544                 NdisReleaseSpinLock(&pAd->BATabLock);
3545         }
3546 }
3547
3548 /*! \brief
3549  *      \param
3550  *      \return
3551  *      \pre
3552  *      \post
3553
3554  IRQL = DISPATCH_LEVEL
3555
3556  */
3557 VOID BssEntrySet(
3558         IN PRTMP_ADAPTER        pAd,
3559         OUT BSS_ENTRY *pBss,
3560         IN PUCHAR pBssid,
3561         IN CHAR Ssid[],
3562         IN UCHAR SsidLen,
3563         IN UCHAR BssType,
3564         IN USHORT BeaconPeriod,
3565         IN PCF_PARM pCfParm,
3566         IN USHORT AtimWin,
3567         IN USHORT CapabilityInfo,
3568         IN UCHAR SupRate[],
3569         IN UCHAR SupRateLen,
3570         IN UCHAR ExtRate[],
3571         IN UCHAR ExtRateLen,
3572         IN HT_CAPABILITY_IE *pHtCapability,
3573         IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
3574         IN UCHAR                        HtCapabilityLen,
3575         IN UCHAR                        AddHtInfoLen,
3576         IN UCHAR                        NewExtChanOffset,
3577         IN UCHAR Channel,
3578         IN CHAR Rssi,
3579         IN LARGE_INTEGER TimeStamp,
3580         IN UCHAR CkipFlag,
3581         IN PEDCA_PARM pEdcaParm,
3582         IN PQOS_CAPABILITY_PARM pQosCapability,
3583         IN PQBSS_LOAD_PARM pQbssLoad,
3584         IN USHORT LengthVIE,
3585         IN PNDIS_802_11_VARIABLE_IEs pVIE)
3586 {
3587         COPY_MAC_ADDR(pBss->Bssid, pBssid);
3588         // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3589         pBss->Hidden = 1;
3590         if (SsidLen > 0)
3591         {
3592                 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3593                 // Or send beacon /probe response with SSID len matching real SSID length,
3594                 // but SSID is all zero. such as "00-00-00-00" with length 4.
3595                 // We have to prevent this case overwrite correct table
3596                 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3597                 {
3598                     NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3599                         NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3600                         pBss->SsidLen = SsidLen;
3601                         pBss->Hidden = 0;
3602                 }
3603         }
3604         else
3605                 pBss->SsidLen = 0;
3606         pBss->BssType = BssType;
3607         pBss->BeaconPeriod = BeaconPeriod;
3608         if (BssType == BSS_INFRA)
3609         {
3610                 if (pCfParm->bValid)
3611                 {
3612                         pBss->CfpCount = pCfParm->CfpCount;
3613                         pBss->CfpPeriod = pCfParm->CfpPeriod;
3614                         pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3615                         pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3616                 }
3617         }
3618         else
3619         {
3620                 pBss->AtimWin = AtimWin;
3621         }
3622
3623         pBss->CapabilityInfo = CapabilityInfo;
3624         // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3625         // Combine with AuthMode, they will decide the connection methods.
3626         pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3627         ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3628         if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3629                 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3630         else
3631                 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3632         pBss->SupRateLen = SupRateLen;
3633         ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3634         NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3635         NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3636         NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3637         pBss->NewExtChanOffset = NewExtChanOffset;
3638         pBss->ExtRateLen = ExtRateLen;
3639         pBss->Channel = Channel;
3640         pBss->CentralChannel = Channel;
3641         pBss->Rssi = Rssi;
3642         // Update CkipFlag. if not exists, the value is 0x0
3643         pBss->CkipFlag = CkipFlag;
3644
3645         // New for microsoft Fixed IEs
3646         NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3647         pBss->FixIEs.BeaconInterval = BeaconPeriod;
3648         pBss->FixIEs.Capabilities = CapabilityInfo;
3649
3650         // New for microsoft Variable IEs
3651         if (LengthVIE != 0)
3652         {
3653                 pBss->VarIELen = LengthVIE;
3654                 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3655         }
3656         else
3657         {
3658                 pBss->VarIELen = 0;
3659         }
3660
3661         pBss->AddHtInfoLen = 0;
3662         pBss->HtCapabilityLen = 0;
3663
3664         if (HtCapabilityLen> 0)
3665         {
3666                 pBss->HtCapabilityLen = HtCapabilityLen;
3667                 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3668                 if (AddHtInfoLen > 0)
3669                 {
3670                         pBss->AddHtInfoLen = AddHtInfoLen;
3671                         NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3672
3673                                 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3674                                 {
3675                                         pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3676                                 }
3677                                 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3678                                 {
3679                                                 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3680                                 }
3681                 }
3682         }
3683
3684         BssCipherParse(pBss);
3685
3686         // new for QOS
3687         if (pEdcaParm)
3688                 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3689         else
3690                 pBss->EdcaParm.bValid = FALSE;
3691         if (pQosCapability)
3692                 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3693         else
3694                 pBss->QosCapability.bValid = FALSE;
3695         if (pQbssLoad)
3696                 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3697         else
3698                 pBss->QbssLoad.bValid = FALSE;
3699
3700         {
3701                 PEID_STRUCT     pEid;
3702                 USHORT          Length = 0;
3703
3704
3705                 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3706                 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3707
3708                 pEid = (PEID_STRUCT) pVIE;
3709
3710                 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3711                 {
3712                         switch(pEid->Eid)
3713                         {
3714                                 case IE_WPA:
3715                                         if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3716                                         {
3717                                                 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3718                                                 {
3719                                                         pBss->WpaIE.IELen = 0;
3720                                                         break;
3721                                                 }
3722                                                 pBss->WpaIE.IELen = pEid->Len + 2;
3723                                                 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3724                                         }
3725                                         break;
3726                 case IE_RSN:
3727                     if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3728                                         {
3729                                                 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3730                                                 {
3731                                                         pBss->RsnIE.IELen = 0;
3732                                                         break;
3733                                                 }
3734                                                 pBss->RsnIE.IELen = pEid->Len + 2;
3735                                                 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3736                         }
3737                                 break;
3738             }
3739                         Length = Length + 2 + (USHORT)pEid->Len;  // Eid[1] + Len[1]+ content[Len]
3740                         pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3741                 }
3742         }
3743 }
3744
3745 /*!
3746  *      \brief insert an entry into the bss table
3747  *      \param p_tab The BSS table
3748  *      \param Bssid BSSID
3749  *      \param ssid SSID
3750  *      \param ssid_len Length of SSID
3751  *      \param bss_type
3752  *      \param beacon_period
3753  *      \param timestamp
3754  *      \param p_cf
3755  *      \param atim_win
3756  *      \param cap
3757  *      \param rates
3758  *      \param rates_len
3759  *      \param channel_idx
3760  *      \return none
3761  *      \pre
3762  *      \post
3763  *      \note If SSID is identical, the old entry will be replaced by the new one
3764
3765  IRQL = DISPATCH_LEVEL
3766
3767  */
3768 ULONG BssTableSetEntry(
3769         IN      PRTMP_ADAPTER   pAd,
3770         OUT BSS_TABLE *Tab,
3771         IN PUCHAR pBssid,
3772         IN CHAR Ssid[],
3773         IN UCHAR SsidLen,
3774         IN UCHAR BssType,
3775         IN USHORT BeaconPeriod,
3776         IN CF_PARM *CfParm,
3777         IN USHORT AtimWin,
3778         IN USHORT CapabilityInfo,
3779         IN UCHAR SupRate[],
3780         IN UCHAR SupRateLen,
3781         IN UCHAR ExtRate[],
3782         IN UCHAR ExtRateLen,
3783         IN HT_CAPABILITY_IE *pHtCapability,
3784         IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
3785         IN UCHAR                        HtCapabilityLen,
3786         IN UCHAR                        AddHtInfoLen,
3787         IN UCHAR                        NewExtChanOffset,
3788         IN UCHAR ChannelNo,
3789         IN CHAR Rssi,
3790         IN LARGE_INTEGER TimeStamp,
3791         IN UCHAR CkipFlag,
3792         IN PEDCA_PARM pEdcaParm,
3793         IN PQOS_CAPABILITY_PARM pQosCapability,
3794         IN PQBSS_LOAD_PARM pQbssLoad,
3795         IN USHORT LengthVIE,
3796         IN PNDIS_802_11_VARIABLE_IEs pVIE)
3797 {
3798         ULONG   Idx;
3799
3800         Idx = BssTableSearchWithSSID(Tab, pBssid,  Ssid, SsidLen, ChannelNo);
3801         if (Idx == BSS_NOT_FOUND)
3802         {
3803                 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3804             {
3805                         //
3806                         // It may happen when BSS Table was full.
3807                         // The desired AP will not be added into BSS Table
3808                         // In this case, if we found the desired AP then overwrite BSS Table.
3809                         //
3810                         if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3811                         {
3812                                 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3813                                         SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3814                                 {
3815                                         Idx = Tab->BssOverlapNr;
3816                                         BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3817                                                 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3818                                                 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3819                     Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3820                                 }
3821                                 return Idx;
3822                         }
3823                         else
3824                         {
3825                         return BSS_NOT_FOUND;
3826                         }
3827                 }
3828                 Idx = Tab->BssNr;
3829                 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3830                                         CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3831                                         NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3832                 Tab->BssNr++;
3833         }
3834         else
3835         {
3836                 /* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
3837                 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3838                         (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3839                 {
3840                 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3841                                         CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3842                                         NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3843                 }
3844         }
3845
3846         return Idx;
3847 }
3848
3849 // IRQL = DISPATCH_LEVEL
3850 VOID BssTableSsidSort(
3851         IN      PRTMP_ADAPTER   pAd,
3852         OUT BSS_TABLE *OutTab,
3853         IN      CHAR Ssid[],
3854         IN      UCHAR SsidLen)
3855 {
3856         INT i;
3857         BssTableInit(OutTab);
3858
3859         for (i = 0; i < pAd->ScanTab.BssNr; i++)
3860         {
3861                 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3862                 BOOLEAN bIsHiddenApIncluded = FALSE;
3863
3864                 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3865             (pAd->MlmeAux.Channel > 14) &&
3866              RadarChannelCheck(pAd, pInBss->Channel))
3867             )
3868                 {
3869                         if (pInBss->Hidden)
3870                                 bIsHiddenApIncluded = TRUE;
3871                 }
3872
3873                 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3874                         (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3875                 {
3876                         BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3877
3878                         // 2.4G/5G N only mode
3879                         if ((pInBss->HtCapabilityLen == 0) &&
3880                                 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3881                         {
3882                                 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3883                                 continue;
3884                         }
3885
3886                         // New for WPA2
3887                         // Check the Authmode first
3888                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3889                         {
3890                                 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3891                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3892                                         // None matched
3893                                         continue;
3894
3895                                 // Check cipher suite, AP must have more secured cipher than station setting
3896                                 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3897                                 {
3898                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
3899                                         if (pInBss->WPA.bMixMode == FALSE)
3900                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3901                                                         continue;
3902
3903                                         // check group cipher
3904                                         if (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3905                                             pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3906                                             pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3907                                                 continue;
3908
3909                                         // check pairwise cipher, skip if none matched
3910                                         // If profile set to AES, let it pass without question.
3911                                         // If profile set to TKIP, we must find one mateched
3912                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3913                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3914                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3915                                                 continue;
3916                                 }
3917                                 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3918                                 {
3919                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
3920                                         if (pInBss->WPA2.bMixMode == FALSE)
3921                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3922                                                         continue;
3923
3924                                         // check group cipher
3925                                         if (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3926                                             pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3927                                             pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3928                                                 continue;
3929
3930                                         // check pairwise cipher, skip if none matched
3931                                         // If profile set to AES, let it pass without question.
3932                                         // If profile set to TKIP, we must find one mateched
3933                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3934                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3935                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3936                                                 continue;
3937                                 }
3938                         }
3939                         // Bss Type matched, SSID matched.
3940                         // We will check wepstatus for qualification Bss
3941                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3942                         {
3943                                 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3944                                 //
3945                                 // For the SESv2 case, we will not qualify WepStatus.
3946                                 //
3947                                 if (!pInBss->bSES)
3948                                         continue;
3949                         }
3950
3951                         // Since the AP is using hidden SSID, and we are trying to connect to ANY
3952                         // It definitely will fail. So, skip it.
3953                         // CCX also require not even try to connect it!!
3954                         if (SsidLen == 0)
3955                                 continue;
3956
3957                         // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3958                         // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3959                         if ((pInBss->CentralChannel != pInBss->Channel) &&
3960                                 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3961                         {
3962                                 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3963                                 {
3964                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3965                                         SetCommonHT(pAd);
3966                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3967                                 }
3968                                 else
3969                                 {
3970                                         if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3971                                         {
3972                                                 SetCommonHT(pAd);
3973                                         }
3974                                 }
3975                         }
3976
3977                         // copy matching BSS from InTab to OutTab
3978                         NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3979
3980                         OutTab->BssNr++;
3981                 }
3982                 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3983                 {
3984                         BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3985
3986                         // 2.4G/5G N only mode
3987                         if ((pInBss->HtCapabilityLen == 0) &&
3988                                 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3989                         {
3990                                 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3991                                 continue;
3992                         }
3993
3994                         // New for WPA2
3995                         // Check the Authmode first
3996                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3997                         {
3998                                 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3999                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4000                                         // None matched
4001                                         continue;
4002
4003                                 // Check cipher suite, AP must have more secured cipher than station setting
4004                                 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4005                                 {
4006                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
4007                                         if (pInBss->WPA.bMixMode == FALSE)
4008                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4009                                                         continue;
4010
4011                                         // check group cipher
4012                                         if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4013                                                 continue;
4014
4015                                         // check pairwise cipher, skip if none matched
4016                                         // If profile set to AES, let it pass without question.
4017                                         // If profile set to TKIP, we must find one mateched
4018                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4019                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4020                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4021                                                 continue;
4022                                 }
4023                                 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4024                                 {
4025                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
4026                                         if (pInBss->WPA2.bMixMode == FALSE)
4027                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4028                                                         continue;
4029
4030                                         // check group cipher
4031                                         if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4032                                                 continue;
4033
4034                                         // check pairwise cipher, skip if none matched
4035                                         // If profile set to AES, let it pass without question.
4036                                         // If profile set to TKIP, we must find one mateched
4037                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4038                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4039                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4040                                                 continue;
4041                                 }
4042                         }
4043                         // Bss Type matched, SSID matched.
4044                         // We will check wepstatus for qualification Bss
4045                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4046                                         continue;
4047
4048                         // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4049                         // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4050                         if ((pInBss->CentralChannel != pInBss->Channel) &&
4051                                 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4052                         {
4053                                 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4054                                 {
4055                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4056                                         SetCommonHT(pAd);
4057                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4058                                 }
4059                         }
4060
4061                         // copy matching BSS from InTab to OutTab
4062                         NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4063
4064                         OutTab->BssNr++;
4065                 }
4066
4067                 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4068                         break;
4069         }
4070
4071         BssTableSortByRssi(OutTab);
4072 }
4073
4074
4075 // IRQL = DISPATCH_LEVEL
4076 VOID BssTableSortByRssi(
4077         IN OUT BSS_TABLE *OutTab)
4078 {
4079         INT       i, j;
4080         BSS_ENTRY TmpBss;
4081
4082         for (i = 0; i < OutTab->BssNr - 1; i++)
4083         {
4084                 for (j = i+1; j < OutTab->BssNr; j++)
4085                 {
4086                         if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4087                         {
4088                                 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4089                                 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4090                                 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4091                         }
4092                 }
4093         }
4094 }
4095
4096 VOID BssCipherParse(
4097         IN OUT  PBSS_ENTRY      pBss)
4098 {
4099         PEID_STRUCT              pEid;
4100         PUCHAR                          pTmp;
4101         PRSN_IE_HEADER_STRUCT                   pRsnHeader;
4102         PCIPHER_SUITE_STRUCT                    pCipher;
4103         PAKM_SUITE_STRUCT                               pAKM;
4104         USHORT                                                  Count;
4105         INT                                                             Length;
4106         NDIS_802_11_ENCRYPTION_STATUS   TmpCipher;
4107
4108         //
4109         // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4110         //
4111         if (pBss->Privacy)
4112         {
4113                 pBss->WepStatus         = Ndis802_11WEPEnabled;
4114         }
4115         else
4116         {
4117                 pBss->WepStatus         = Ndis802_11WEPDisabled;
4118         }
4119         // Set default to disable & open authentication before parsing variable IE
4120         pBss->AuthMode          = Ndis802_11AuthModeOpen;
4121         pBss->AuthModeAux       = Ndis802_11AuthModeOpen;
4122
4123         // Init WPA setting
4124         pBss->WPA.PairCipher    = Ndis802_11WEPDisabled;
4125         pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4126         pBss->WPA.GroupCipher   = Ndis802_11WEPDisabled;
4127         pBss->WPA.RsnCapability = 0;
4128         pBss->WPA.bMixMode              = FALSE;
4129
4130         // Init WPA2 setting
4131         pBss->WPA2.PairCipher    = Ndis802_11WEPDisabled;
4132         pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4133         pBss->WPA2.GroupCipher   = Ndis802_11WEPDisabled;
4134         pBss->WPA2.RsnCapability = 0;
4135         pBss->WPA2.bMixMode      = FALSE;
4136
4137
4138         Length = (INT) pBss->VarIELen;
4139
4140         while (Length > 0)
4141         {
4142                 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4143                 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4144                 pEid = (PEID_STRUCT) pTmp;
4145                 switch (pEid->Eid)
4146                 {
4147                         case IE_WPA:
4148                                 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4149                                 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4150                                 {
4151                                         pTmp   += 11;
4152                                         switch (*pTmp)
4153                                         {
4154                                                 case 1:
4155                                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4156                                                         pBss->WepStatus = Ndis802_11Encryption1Enabled;
4157                                                         pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4158                                                         pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4159                                                         break;
4160                                                 case 2:
4161                                                         pBss->WepStatus = Ndis802_11Encryption2Enabled;
4162                                                         pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4163                                                         pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4164                                                         break;
4165                                                 case 4:
4166                                                         pBss->WepStatus = Ndis802_11Encryption3Enabled;
4167                                                         pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4168                                                         pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4169                                                         break;
4170                                                 default:
4171                                                         break;
4172                                         }
4173
4174                                         // if Cisco IE_WPA, break
4175                                         break;
4176                                 }
4177                                 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4178                                 {
4179                                         pBss->bSES = TRUE;
4180                                         break;
4181                                 }
4182                                 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4183                                 {
4184                                         // if unsupported vendor specific IE
4185                                         break;
4186                                 }
4187                                 // Skip OUI, version, and multicast suite
4188                                 // This part should be improved in the future when AP supported multiple cipher suite.
4189                                 // For now, it's OK since almost all APs have fixed cipher suite supported.
4190                                 // pTmp = (PUCHAR) pEid->Octet;
4191                                 pTmp   += 11;
4192
4193                                 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4194                                 //      Value      Meaning
4195                                 //      0                       None
4196                                 //      1                       WEP-40
4197                                 //      2                       Tkip
4198                                 //      3                       WRAP
4199                                 //      4                       AES
4200                                 //      5                       WEP-104
4201                                 // Parse group cipher
4202                                 switch (*pTmp)
4203                                 {
4204                                         case 1:
4205                                                 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4206                                                 break;
4207                                         case 5:
4208                                                 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4209                                                 break;
4210                                         case 2:
4211                                                 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4212                                                 break;
4213                                         case 4:
4214                                                 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4215                                                 break;
4216                                         default:
4217                                                 break;
4218                                 }
4219                                 // number of unicast suite
4220                                 pTmp   += 1;
4221
4222                                 // skip all unicast cipher suites
4223                                 //Count = *(PUSHORT) pTmp;
4224                                 Count = (pTmp[1]<<8) + pTmp[0];
4225                                 pTmp   += sizeof(USHORT);
4226
4227                                 // Parsing all unicast cipher suite
4228                                 while (Count > 0)
4229                                 {
4230                                         // Skip OUI
4231                                         pTmp += 3;
4232                                         TmpCipher = Ndis802_11WEPDisabled;
4233                                         switch (*pTmp)
4234                                         {
4235                                                 case 1:
4236                                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4237                                                         TmpCipher = Ndis802_11Encryption1Enabled;
4238                                                         break;
4239                                                 case 2:
4240                                                         TmpCipher = Ndis802_11Encryption2Enabled;
4241                                                         break;
4242                                                 case 4:
4243                                                         TmpCipher = Ndis802_11Encryption3Enabled;
4244                                                         break;
4245                                                 default:
4246                                                         break;
4247                                         }
4248                                         if (TmpCipher > pBss->WPA.PairCipher)
4249                                         {
4250                                                 // Move the lower cipher suite to PairCipherAux
4251                                                 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4252                                                 pBss->WPA.PairCipher    = TmpCipher;
4253                                         }
4254                                         else
4255                                         {
4256                                                 pBss->WPA.PairCipherAux = TmpCipher;
4257                                         }
4258                                         pTmp++;
4259                                         Count--;
4260                                 }
4261
4262                                 // 4. get AKM suite counts
4263                                 //Count = *(PUSHORT) pTmp;
4264                                 Count = (pTmp[1]<<8) + pTmp[0];
4265                                 pTmp   += sizeof(USHORT);
4266                                 pTmp   += 3;
4267
4268                                 switch (*pTmp)
4269                                 {
4270                                         case 1:
4271                                                 // Set AP support WPA mode
4272                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4273                                                         pBss->AuthMode = Ndis802_11AuthModeWPA;
4274                                                 else
4275                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4276                                                 break;
4277                                         case 2:
4278                                                 // Set AP support WPA mode
4279                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4280                                                         pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4281                                                 else
4282                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4283                                                 break;
4284                                         default:
4285                                                 break;
4286                                 }
4287                                 pTmp   += 1;
4288
4289                                 // Fixed for WPA-None
4290                                 if (pBss->BssType == BSS_ADHOC)
4291                                 {
4292                                         pBss->AuthMode    = Ndis802_11AuthModeWPANone;
4293                                         pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4294                                         pBss->WepStatus   = pBss->WPA.GroupCipher;
4295                                         if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4296                                                 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4297                                 }
4298                                 else
4299                                         pBss->WepStatus   = pBss->WPA.PairCipher;
4300
4301                                 // Check the Pair & Group, if different, turn on mixed mode flag
4302                                 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4303                                         pBss->WPA.bMixMode = TRUE;
4304
4305                                 break;
4306
4307                         case IE_RSN:
4308                                 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4309
4310                                 // 0. Version must be 1
4311                                 if (le2cpu16(pRsnHeader->Version) != 1)
4312                                         break;
4313                                 pTmp   += sizeof(RSN_IE_HEADER_STRUCT);
4314
4315                                 // 1. Check group cipher
4316                                 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4317                                 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4318                                         break;
4319
4320                                 // Parse group cipher
4321                                 switch (pCipher->Type)
4322                                 {
4323                                         case 1:
4324                                                 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4325                                                 break;
4326                                         case 5:
4327                                                 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4328                                                 break;
4329                                         case 2:
4330                                                 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4331                                                 break;
4332                                         case 4:
4333                                                 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4334                                                 break;
4335                                         default:
4336                                                 break;
4337                                 }
4338                                 // set to correct offset for next parsing
4339                                 pTmp   += sizeof(CIPHER_SUITE_STRUCT);
4340
4341                                 // 2. Get pairwise cipher counts
4342                                 //Count = *(PUSHORT) pTmp;
4343                                 Count = (pTmp[1]<<8) + pTmp[0];
4344                                 pTmp   += sizeof(USHORT);
4345
4346                                 // 3. Get pairwise cipher
4347                                 // Parsing all unicast cipher suite
4348                                 while (Count > 0)
4349                                 {
4350                                         // Skip OUI
4351                                         pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4352                                         TmpCipher = Ndis802_11WEPDisabled;
4353                                         switch (pCipher->Type)
4354                                         {
4355                                                 case 1:
4356                                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4357                                                         TmpCipher = Ndis802_11Encryption1Enabled;
4358                                                         break;
4359                                                 case 2:
4360                                                         TmpCipher = Ndis802_11Encryption2Enabled;
4361                                                         break;
4362                                                 case 4:
4363                                                         TmpCipher = Ndis802_11Encryption3Enabled;
4364                                                         break;
4365                                                 default:
4366                                                         break;
4367                                         }
4368                                         if (TmpCipher > pBss->WPA2.PairCipher)
4369                                         {
4370                                                 // Move the lower cipher suite to PairCipherAux
4371                                                 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4372                                                 pBss->WPA2.PairCipher    = TmpCipher;
4373                                         }
4374                                         else
4375                                         {
4376                                                 pBss->WPA2.PairCipherAux = TmpCipher;
4377                                         }
4378                                         pTmp += sizeof(CIPHER_SUITE_STRUCT);
4379                                         Count--;
4380                                 }
4381
4382                                 // 4. get AKM suite counts
4383                                 //Count = *(PUSHORT) pTmp;
4384                                 Count = (pTmp[1]<<8) + pTmp[0];
4385                                 pTmp   += sizeof(USHORT);
4386
4387                                 // 5. Get AKM ciphers
4388                                 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4389                                 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4390                                         break;
4391
4392                                 switch (pAKM->Type)
4393                                 {
4394                                         case 1:
4395                                                 // Set AP support WPA mode
4396                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4397                                                         pBss->AuthMode = Ndis802_11AuthModeWPA2;
4398                                                 else
4399                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4400                                                 break;
4401                                         case 2:
4402                                                 // Set AP support WPA mode
4403                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4404                                                         pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4405                                                 else
4406                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4407                                                 break;
4408                                         default:
4409                                                 break;
4410                                 }
4411                                 pTmp   += (Count * sizeof(AKM_SUITE_STRUCT));
4412
4413                                 // Fixed for WPA-None
4414                                 if (pBss->BssType == BSS_ADHOC)
4415                                 {
4416                                         pBss->AuthMode = Ndis802_11AuthModeWPANone;
4417                                         pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4418                                         pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4419                                         pBss->WPA.GroupCipher   = pBss->WPA2.GroupCipher;
4420                                         pBss->WepStatus                 = pBss->WPA.GroupCipher;
4421                                         if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4422                                                 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4423                                 }
4424                                 pBss->WepStatus   = pBss->WPA2.PairCipher;
4425
4426                                 // 6. Get RSN capability
4427                                 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4428                                 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4429                                 pTmp += sizeof(USHORT);
4430
4431                                 // Check the Pair & Group, if different, turn on mixed mode flag
4432                                 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4433                                         pBss->WPA2.bMixMode = TRUE;
4434
4435                                 break;
4436                         default:
4437                                 break;
4438                 }
4439                 Length -= (pEid->Len + 2);
4440         }
4441 }
4442
4443 // ===========================================================================================
4444 // mac_table.c
4445 // ===========================================================================================
4446
4447 /*! \brief generates a random mac address value for IBSS BSSID
4448  *      \param Addr the bssid location
4449  *      \return none
4450  *      \pre
4451  *      \post
4452  */
4453 VOID MacAddrRandomBssid(
4454         IN PRTMP_ADAPTER pAd,
4455         OUT PUCHAR pAddr)
4456 {
4457         INT i;
4458
4459         for (i = 0; i < MAC_ADDR_LEN; i++)
4460         {
4461                 pAddr[i] = RandomByte(pAd);
4462         }
4463
4464         pAddr[0] = (pAddr[0] & 0xfe) | 0x02;  // the first 2 bits must be 01xxxxxxxx
4465 }
4466
4467 /*! \brief init the management mac frame header
4468  *      \param p_hdr mac header
4469  *      \param subtype subtype of the frame
4470  *      \param p_ds destination address, don't care if it is a broadcast address
4471  *      \return none
4472  *      \pre the station has the following information in the pAd->StaCfg
4473  *       - bssid
4474  *       - station address
4475  *      \post
4476  *      \note this function initializes the following field
4477
4478  IRQL = PASSIVE_LEVEL
4479  IRQL = DISPATCH_LEVEL
4480
4481  */
4482 VOID MgtMacHeaderInit(
4483         IN      PRTMP_ADAPTER   pAd,
4484         IN OUT PHEADER_802_11 pHdr80211,
4485         IN UCHAR SubType,
4486         IN UCHAR ToDs,
4487         IN PUCHAR pDA,
4488         IN PUCHAR pBssid)
4489 {
4490         NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4491
4492         pHdr80211->FC.Type = BTYPE_MGMT;
4493         pHdr80211->FC.SubType = SubType;
4494         pHdr80211->FC.ToDs = ToDs;
4495         COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4496
4497         COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4498
4499         COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4500 }
4501
4502 // ===========================================================================================
4503 // mem_mgmt.c
4504 // ===========================================================================================
4505
4506 /*!***************************************************************************
4507  * This routine build an outgoing frame, and fill all information specified
4508  * in argument list to the frame body. The actual frame size is the summation
4509  * of all arguments.
4510  * input params:
4511  *              Buffer - pointer to a pre-allocated memory segment
4512  *              args - a list of <int arg_size, arg> pairs.
4513  *              NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4514  *                                                 function will FAIL!!!
4515  * return:
4516  *              Size of the buffer
4517  * usage:
4518  *              MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4519
4520  IRQL = PASSIVE_LEVEL
4521  IRQL = DISPATCH_LEVEL
4522
4523  ****************************************************************************/
4524 ULONG MakeOutgoingFrame(
4525         OUT CHAR *Buffer,
4526         OUT ULONG *FrameLen, ...)
4527 {
4528         CHAR   *p;
4529         int     leng;
4530         ULONG   TotLeng;
4531         va_list Args;
4532
4533         // calculates the total length
4534         TotLeng = 0;
4535         va_start(Args, FrameLen);
4536         do
4537         {
4538                 leng = va_arg(Args, int);
4539                 if (leng == END_OF_ARGS)
4540                 {
4541                         break;
4542                 }
4543                 p = va_arg(Args, PVOID);
4544                 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4545                 TotLeng = TotLeng + leng;
4546         } while(TRUE);
4547
4548         va_end(Args); /* clean up */
4549         *FrameLen = TotLeng;
4550         return TotLeng;
4551 }
4552
4553 // ===========================================================================================
4554 // mlme_queue.c
4555 // ===========================================================================================
4556
4557 /*! \brief      Initialize The MLME Queue, used by MLME Functions
4558  *      \param  *Queue     The MLME Queue
4559  *      \return Always     Return NDIS_STATE_SUCCESS in this implementation
4560  *      \pre
4561  *      \post
4562  *      \note   Because this is done only once (at the init stage), no need to be locked
4563
4564  IRQL = PASSIVE_LEVEL
4565
4566  */
4567 NDIS_STATUS MlmeQueueInit(
4568         IN MLME_QUEUE *Queue)
4569 {
4570         INT i;
4571
4572         NdisAllocateSpinLock(&Queue->Lock);
4573
4574         Queue->Num      = 0;
4575         Queue->Head = 0;
4576         Queue->Tail = 0;
4577
4578         for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4579         {
4580                 Queue->Entry[i].Occupied = FALSE;
4581                 Queue->Entry[i].MsgLen = 0;
4582                 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4583         }
4584
4585         return NDIS_STATUS_SUCCESS;
4586 }
4587
4588 /*! \brief       Enqueue a message for other threads, if they want to send messages to MLME thread
4589  *      \param  *Queue    The MLME Queue
4590  *      \param   Machine  The State Machine Id
4591  *      \param   MsgType  The Message Type
4592  *      \param   MsgLen   The Message length
4593  *      \param  *Msg      The message pointer
4594  *      \return  TRUE if enqueue is successful, FALSE if the queue is full
4595  *      \pre
4596  *      \post
4597  *      \note    The message has to be initialized
4598
4599  IRQL = PASSIVE_LEVEL
4600  IRQL = DISPATCH_LEVEL
4601
4602  */
4603 BOOLEAN MlmeEnqueue(
4604         IN      PRTMP_ADAPTER   pAd,
4605         IN ULONG Machine,
4606         IN ULONG MsgType,
4607         IN ULONG MsgLen,
4608         IN VOID *Msg)
4609 {
4610         INT Tail;
4611         MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4612
4613         // Do nothing if the driver is starting halt state.
4614         // This might happen when timer already been fired before cancel timer with mlmehalt
4615         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4616                 return FALSE;
4617
4618         // First check the size, it MUST not exceed the mlme queue size
4619         if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4620         {
4621                 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4622                 return FALSE;
4623         }
4624
4625         if (MlmeQueueFull(Queue))
4626         {
4627                 return FALSE;
4628         }
4629
4630         NdisAcquireSpinLock(&(Queue->Lock));
4631         Tail = Queue->Tail;
4632         Queue->Tail++;
4633         Queue->Num++;
4634         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4635         {
4636                 Queue->Tail = 0;
4637         }
4638
4639         Queue->Entry[Tail].Wcid = RESERVED_WCID;
4640         Queue->Entry[Tail].Occupied = TRUE;
4641         Queue->Entry[Tail].Machine = Machine;
4642         Queue->Entry[Tail].MsgType = MsgType;
4643         Queue->Entry[Tail].MsgLen  = MsgLen;
4644
4645         if (Msg != NULL)
4646         {
4647                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4648         }
4649
4650         NdisReleaseSpinLock(&(Queue->Lock));
4651         return TRUE;
4652 }
4653
4654 /*! \brief       This function is used when Recv gets a MLME message
4655  *      \param  *Queue                   The MLME Queue
4656  *      \param   TimeStampHigh   The upper 32 bit of timestamp
4657  *      \param   TimeStampLow    The lower 32 bit of timestamp
4658  *      \param   Rssi                    The receiving RSSI strength
4659  *      \param   MsgLen                  The length of the message
4660  *      \param  *Msg                     The message pointer
4661  *      \return  TRUE if everything ok, FALSE otherwise (like Queue Full)
4662  *      \pre
4663  *      \post
4664
4665  IRQL = DISPATCH_LEVEL
4666
4667  */
4668 BOOLEAN MlmeEnqueueForRecv(
4669         IN      PRTMP_ADAPTER   pAd,
4670         IN ULONG Wcid,
4671         IN ULONG TimeStampHigh,
4672         IN ULONG TimeStampLow,
4673         IN UCHAR Rssi0,
4674         IN UCHAR Rssi1,
4675         IN UCHAR Rssi2,
4676         IN ULONG MsgLen,
4677         IN VOID *Msg,
4678         IN UCHAR Signal)
4679 {
4680         INT              Tail, Machine;
4681         PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4682         INT              MsgType;
4683         MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4684
4685         // Do nothing if the driver is starting halt state.
4686         // This might happen when timer already been fired before cancel timer with mlmehalt
4687         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4688         {
4689                 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4690                 return FALSE;
4691         }
4692
4693         // First check the size, it MUST not exceed the mlme queue size
4694         if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4695         {
4696                 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4697                 return FALSE;
4698         }
4699
4700         if (MlmeQueueFull(Queue))
4701         {
4702                 return FALSE;
4703         }
4704
4705         {
4706                 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4707                 {
4708                         DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4709                         return FALSE;
4710                 }
4711         }
4712
4713         // OK, we got all the informations, it is time to put things into queue
4714         NdisAcquireSpinLock(&(Queue->Lock));
4715         Tail = Queue->Tail;
4716         Queue->Tail++;
4717         Queue->Num++;
4718         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4719         {
4720                 Queue->Tail = 0;
4721         }
4722         Queue->Entry[Tail].Occupied = TRUE;
4723         Queue->Entry[Tail].Machine = Machine;
4724         Queue->Entry[Tail].MsgType = MsgType;
4725         Queue->Entry[Tail].MsgLen  = MsgLen;
4726         Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4727         Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4728         Queue->Entry[Tail].Rssi0 = Rssi0;
4729         Queue->Entry[Tail].Rssi1 = Rssi1;
4730         Queue->Entry[Tail].Rssi2 = Rssi2;
4731         Queue->Entry[Tail].Signal = Signal;
4732         Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4733
4734         Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4735
4736         if (Msg != NULL)
4737         {
4738                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4739         }
4740
4741         NdisReleaseSpinLock(&(Queue->Lock));
4742
4743         RT28XX_MLME_HANDLER(pAd);
4744
4745         return TRUE;
4746 }
4747
4748
4749 /*! \brief       Dequeue a message from the MLME Queue
4750  *      \param  *Queue    The MLME Queue
4751  *      \param  *Elem     The message dequeued from MLME Queue
4752  *      \return  TRUE if the Elem contains something, FALSE otherwise
4753  *      \pre
4754  *      \post
4755
4756  IRQL = DISPATCH_LEVEL
4757
4758  */
4759 BOOLEAN MlmeDequeue(
4760         IN MLME_QUEUE *Queue,
4761         OUT MLME_QUEUE_ELEM **Elem)
4762 {
4763         NdisAcquireSpinLock(&(Queue->Lock));
4764         *Elem = &(Queue->Entry[Queue->Head]);
4765         Queue->Num--;
4766         Queue->Head++;
4767         if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4768         {
4769                 Queue->Head = 0;
4770         }
4771         NdisReleaseSpinLock(&(Queue->Lock));
4772         return TRUE;
4773 }
4774
4775 // IRQL = DISPATCH_LEVEL
4776 VOID    MlmeRestartStateMachine(
4777         IN      PRTMP_ADAPTER   pAd)
4778 {
4779 #ifdef RT2860
4780         MLME_QUEUE_ELEM         *Elem = NULL;
4781 #endif
4782         BOOLEAN                         Cancelled;
4783
4784         DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4785
4786 #ifdef RT2860
4787         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4788         if(pAd->Mlme.bRunning)
4789         {
4790                 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4791                 return;
4792         }
4793         else
4794         {
4795                 pAd->Mlme.bRunning = TRUE;
4796         }
4797         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4798
4799         // Remove all Mlme queues elements
4800         while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4801         {
4802                 //From message type, determine which state machine I should drive
4803                 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4804                 {
4805                         // free MLME element
4806                         Elem->Occupied = FALSE;
4807                         Elem->MsgLen = 0;
4808
4809                 }
4810                 else {
4811                         DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4812                 }
4813         }
4814 #endif /* RT2860 */
4815
4816         {
4817                 // Cancel all timer events
4818                 // Be careful to cancel new added timer
4819                 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,         &Cancelled);
4820                 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,   &Cancelled);
4821                 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,  &Cancelled);
4822                 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,           &Cancelled);
4823                 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,         &Cancelled);
4824                 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,           &Cancelled);
4825         }
4826
4827         // Change back to original channel in case of doing scan
4828         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4829         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4830
4831         // Resume MSDU which is turned off durning scan
4832         RTMPResumeMsduTransmission(pAd);
4833
4834         {
4835                 // Set all state machines back IDLE
4836                 pAd->Mlme.CntlMachine.CurrState    = CNTL_IDLE;
4837                 pAd->Mlme.AssocMachine.CurrState   = ASSOC_IDLE;
4838                 pAd->Mlme.AuthMachine.CurrState    = AUTH_REQ_IDLE;
4839                 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4840                 pAd->Mlme.SyncMachine.CurrState    = SYNC_IDLE;
4841                 pAd->Mlme.ActMachine.CurrState    = ACT_IDLE;
4842         }
4843
4844 #ifdef RT2860
4845         // Remove running state
4846         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4847         pAd->Mlme.bRunning = FALSE;
4848         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4849 #endif
4850 }
4851
4852 /*! \brief      test if the MLME Queue is empty
4853  *      \param  *Queue    The MLME Queue
4854  *      \return TRUE if the Queue is empty, FALSE otherwise
4855  *      \pre
4856  *      \post
4857
4858  IRQL = DISPATCH_LEVEL
4859
4860  */
4861 BOOLEAN MlmeQueueEmpty(
4862         IN MLME_QUEUE *Queue)
4863 {
4864         BOOLEAN Ans;
4865
4866         NdisAcquireSpinLock(&(Queue->Lock));
4867         Ans = (Queue->Num == 0);
4868         NdisReleaseSpinLock(&(Queue->Lock));
4869
4870         return Ans;
4871 }
4872
4873 /*! \brief       test if the MLME Queue is full
4874  *      \param   *Queue          The MLME Queue
4875  *      \return  TRUE if the Queue is empty, FALSE otherwise
4876  *      \pre
4877  *      \post
4878
4879  IRQL = PASSIVE_LEVEL
4880  IRQL = DISPATCH_LEVEL
4881
4882  */
4883 BOOLEAN MlmeQueueFull(
4884         IN MLME_QUEUE *Queue)
4885 {
4886         BOOLEAN Ans;
4887
4888         NdisAcquireSpinLock(&(Queue->Lock));
4889         Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4890         NdisReleaseSpinLock(&(Queue->Lock));
4891
4892         return Ans;
4893 }
4894
4895 /*! \brief       The destructor of MLME Queue
4896  *      \param
4897  *      \return
4898  *      \pre
4899  *      \post
4900  *      \note   Clear Mlme Queue, Set Queue->Num to Zero.
4901
4902  IRQL = PASSIVE_LEVEL
4903
4904  */
4905 VOID MlmeQueueDestroy(
4906         IN MLME_QUEUE *pQueue)
4907 {
4908         NdisAcquireSpinLock(&(pQueue->Lock));
4909         pQueue->Num  = 0;
4910         pQueue->Head = 0;
4911         pQueue->Tail = 0;
4912         NdisReleaseSpinLock(&(pQueue->Lock));
4913         NdisFreeSpinLock(&(pQueue->Lock));
4914 }
4915
4916 /*! \brief       To substitute the message type if the message is coming from external
4917  *      \param  pFrame             The frame received
4918  *      \param  *Machine           The state machine
4919  *      \param  *MsgType           the message type for the state machine
4920  *      \return TRUE if the substitution is successful, FALSE otherwise
4921  *      \pre
4922  *      \post
4923
4924  IRQL = DISPATCH_LEVEL
4925
4926  */
4927 BOOLEAN MsgTypeSubst(
4928         IN PRTMP_ADAPTER  pAd,
4929         IN PFRAME_802_11 pFrame,
4930         OUT INT *Machine,
4931         OUT INT *MsgType)
4932 {
4933         USHORT  Seq;
4934         UCHAR   EAPType;
4935         PUCHAR  pData;
4936
4937         // Pointer to start of data frames including SNAP header
4938         pData = (PUCHAR) pFrame + LENGTH_802_11;
4939
4940         // The only data type will pass to this function is EAPOL frame
4941         if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4942         {
4943                 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4944                 {
4945                         // Cisco Aironet SNAP header
4946                         *Machine = AIRONET_STATE_MACHINE;
4947                         *MsgType = MT2_AIRONET_MSG;
4948                         return (TRUE);
4949                 }
4950                 {
4951                         *Machine = WPA_PSK_STATE_MACHINE;
4952                         EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4953                         return(WpaMsgTypeSubst(EAPType, MsgType));
4954                 }
4955         }
4956
4957         switch (pFrame->Hdr.FC.SubType)
4958         {
4959                 case SUBTYPE_ASSOC_REQ:
4960                         *Machine = ASSOC_STATE_MACHINE;
4961                         *MsgType = MT2_PEER_ASSOC_REQ;
4962                         break;
4963                 case SUBTYPE_ASSOC_RSP:
4964                         *Machine = ASSOC_STATE_MACHINE;
4965                         *MsgType = MT2_PEER_ASSOC_RSP;
4966                         break;
4967                 case SUBTYPE_REASSOC_REQ:
4968                         *Machine = ASSOC_STATE_MACHINE;
4969                         *MsgType = MT2_PEER_REASSOC_REQ;
4970                         break;
4971                 case SUBTYPE_REASSOC_RSP:
4972                         *Machine = ASSOC_STATE_MACHINE;
4973                         *MsgType = MT2_PEER_REASSOC_RSP;
4974                         break;
4975                 case SUBTYPE_PROBE_REQ:
4976                         *Machine = SYNC_STATE_MACHINE;
4977                         *MsgType = MT2_PEER_PROBE_REQ;
4978                         break;
4979                 case SUBTYPE_PROBE_RSP:
4980                         *Machine = SYNC_STATE_MACHINE;
4981                         *MsgType = MT2_PEER_PROBE_RSP;
4982                         break;
4983                 case SUBTYPE_BEACON:
4984                         *Machine = SYNC_STATE_MACHINE;
4985                         *MsgType = MT2_PEER_BEACON;
4986                         break;
4987                 case SUBTYPE_ATIM:
4988                         *Machine = SYNC_STATE_MACHINE;
4989                         *MsgType = MT2_PEER_ATIM;
4990                         break;
4991                 case SUBTYPE_DISASSOC:
4992                         *Machine = ASSOC_STATE_MACHINE;
4993                         *MsgType = MT2_PEER_DISASSOC_REQ;
4994                         break;
4995                 case SUBTYPE_AUTH:
4996                         // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4997                         NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4998                         if (Seq == 1 || Seq == 3)
4999                         {
5000                                 *Machine = AUTH_RSP_STATE_MACHINE;
5001                                 *MsgType = MT2_PEER_AUTH_ODD;
5002                         }
5003                         else if (Seq == 2 || Seq == 4)
5004                         {
5005                                 *Machine = AUTH_STATE_MACHINE;
5006                                 *MsgType = MT2_PEER_AUTH_EVEN;
5007                         }
5008                         else
5009                         {
5010                                 return FALSE;
5011                         }
5012                         break;
5013                 case SUBTYPE_DEAUTH:
5014                         *Machine = AUTH_RSP_STATE_MACHINE;
5015                         *MsgType = MT2_PEER_DEAUTH;
5016                         break;
5017                 case SUBTYPE_ACTION:
5018                         *Machine = ACTION_STATE_MACHINE;
5019                         //  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5020                         if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5021                         {
5022                                 *MsgType = MT2_ACT_INVALID;
5023                         }
5024                         else
5025                         {
5026                                 *MsgType = (pFrame->Octet[0]&0x7F);
5027                         }
5028                         break;
5029                 default:
5030                         return FALSE;
5031                         break;
5032         }
5033
5034         return TRUE;
5035 }
5036
5037 // ===========================================================================================
5038 // state_machine.c
5039 // ===========================================================================================
5040
5041 /*! \brief Initialize the state machine.
5042  *      \param *S                       pointer to the state machine
5043  *      \param  Trans           State machine transition function
5044  *      \param  StNr            number of states
5045  *      \param  MsgNr           number of messages
5046  *      \param  DefFunc         default function, when there is invalid state/message combination
5047  *      \param  InitState       initial state of the state machine
5048  *      \param  Base            StateMachine base, internal use only
5049  *      \pre p_sm should be a legal pointer
5050  *      \post
5051
5052  IRQL = PASSIVE_LEVEL
5053
5054  */
5055 VOID StateMachineInit(
5056         IN STATE_MACHINE *S,
5057         IN STATE_MACHINE_FUNC Trans[],
5058         IN ULONG StNr,
5059         IN ULONG MsgNr,
5060         IN STATE_MACHINE_FUNC DefFunc,
5061         IN ULONG InitState,
5062         IN ULONG Base)
5063 {
5064         ULONG i, j;
5065
5066         // set number of states and messages
5067         S->NrState = StNr;
5068         S->NrMsg   = MsgNr;
5069         S->Base    = Base;
5070
5071         S->TransFunc  = Trans;
5072
5073         // init all state transition to default function
5074         for (i = 0; i < StNr; i++)
5075         {
5076                 for (j = 0; j < MsgNr; j++)
5077                 {
5078                         S->TransFunc[i * MsgNr + j] = DefFunc;
5079                 }
5080         }
5081
5082         // set the starting state
5083         S->CurrState = InitState;
5084 }
5085
5086 /*! \brief This function fills in the function pointer into the cell in the state machine
5087  *      \param *S       pointer to the state machine
5088  *      \param St       state
5089  *      \param Msg      incoming message
5090  *      \param f        the function to be executed when (state, message) combination occurs at the state machine
5091  *      \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
5092  *      \post
5093
5094  IRQL = PASSIVE_LEVEL
5095
5096  */
5097 VOID StateMachineSetAction(
5098         IN STATE_MACHINE *S,
5099         IN ULONG St,
5100         IN ULONG Msg,
5101         IN STATE_MACHINE_FUNC Func)
5102 {
5103         ULONG MsgIdx;
5104
5105         MsgIdx = Msg - S->Base;
5106
5107         if (St < S->NrState && MsgIdx < S->NrMsg)
5108         {
5109                 // boundary checking before setting the action
5110                 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5111         }
5112 }
5113
5114 /*! \brief       This function does the state transition
5115  *      \param   *Adapter the NIC adapter pointer
5116  *      \param   *S       the state machine
5117  *      \param   *Elem    the message to be executed
5118  *      \return   None
5119
5120  IRQL = DISPATCH_LEVEL
5121
5122  */
5123 VOID StateMachinePerformAction(
5124         IN      PRTMP_ADAPTER   pAd,
5125         IN STATE_MACHINE *S,
5126         IN MLME_QUEUE_ELEM *Elem)
5127 {
5128         (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5129 }
5130
5131 /*
5132         ==========================================================================
5133         Description:
5134                 The drop function, when machine executes this, the message is simply
5135                 ignored. This function does nothing, the message is freed in
5136                 StateMachinePerformAction()
5137         ==========================================================================
5138  */
5139 VOID Drop(
5140         IN PRTMP_ADAPTER pAd,
5141         IN MLME_QUEUE_ELEM *Elem)
5142 {
5143 }
5144
5145 // ===========================================================================================
5146 // lfsr.c
5147 // ===========================================================================================
5148
5149 /*
5150         ==========================================================================
5151         Description:
5152
5153         IRQL = PASSIVE_LEVEL
5154
5155         ==========================================================================
5156  */
5157 VOID LfsrInit(
5158         IN PRTMP_ADAPTER pAd,
5159         IN ULONG Seed)
5160 {
5161         if (Seed == 0)
5162                 pAd->Mlme.ShiftReg = 1;
5163         else
5164                 pAd->Mlme.ShiftReg = Seed;
5165 }
5166
5167 /*
5168         ==========================================================================
5169         Description:
5170         ==========================================================================
5171  */
5172 UCHAR RandomByte(
5173         IN PRTMP_ADAPTER pAd)
5174 {
5175         ULONG i;
5176         UCHAR R, Result;
5177
5178         R = 0;
5179
5180         if (pAd->Mlme.ShiftReg == 0)
5181         NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5182
5183         for (i = 0; i < 8; i++)
5184         {
5185                 if (pAd->Mlme.ShiftReg & 0x00000001)
5186                 {
5187                         pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5188                         Result = 1;
5189                 }
5190                 else
5191                 {
5192                         pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5193                         Result = 0;
5194                 }
5195                 R = (R << 1) | Result;
5196         }
5197
5198         return R;
5199 }
5200
5201 VOID AsicUpdateAutoFallBackTable(
5202         IN      PRTMP_ADAPTER   pAd,
5203         IN      PUCHAR                  pRateTable)
5204 {
5205         UCHAR                                   i;
5206         HT_FBK_CFG0_STRUC               HtCfg0;
5207         HT_FBK_CFG1_STRUC               HtCfg1;
5208         LG_FBK_CFG0_STRUC               LgCfg0;
5209         LG_FBK_CFG1_STRUC               LgCfg1;
5210         PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate;
5211
5212         // set to initial value
5213         HtCfg0.word = 0x65432100;
5214         HtCfg1.word = 0xedcba988;
5215         LgCfg0.word = 0xedcba988;
5216         LgCfg1.word = 0x00002100;
5217
5218         pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5219         for (i = 1; i < *((PUCHAR) pRateTable); i++)
5220         {
5221                 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5222                 switch (pCurrTxRate->Mode)
5223                 {
5224                         case 0:         //CCK
5225                                 break;
5226                         case 1:         //OFDM
5227                                 {
5228                                         switch(pCurrTxRate->CurrMCS)
5229                                         {
5230                                                 case 0:
5231                                                         LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5232                                                         break;
5233                                                 case 1:
5234                                                         LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5235                                                         break;
5236                                                 case 2:
5237                                                         LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5238                                                         break;
5239                                                 case 3:
5240                                                         LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5241                                                         break;
5242                                                 case 4:
5243                                                         LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5244                                                         break;
5245                                                 case 5:
5246                                                         LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5247                                                         break;
5248                                                 case 6:
5249                                                         LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5250                                                         break;
5251                                                 case 7:
5252                                                         LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5253                                                         break;
5254                                         }
5255                                 }
5256                                 break;
5257                         case 2:         //HT-MIX
5258                         case 3:         //HT-GF
5259                                 {
5260                                         if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5261                                         {
5262                                                 switch(pCurrTxRate->CurrMCS)
5263                                                 {
5264                                                         case 0:
5265                                                                 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5266                                                                 break;
5267                                                         case 1:
5268                                                                 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5269                                                                 break;
5270                                                         case 2:
5271                                                                 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5272                                                                 break;
5273                                                         case 3:
5274                                                                 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5275                                                                 break;
5276                                                         case 4:
5277                                                                 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5278                                                                 break;
5279                                                         case 5:
5280                                                                 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5281                                                                 break;
5282                                                         case 6:
5283                                                                 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5284                                                                 break;
5285                                                         case 7:
5286                                                                 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5287                                                                 break;
5288                                                         case 8:
5289                                                                 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5290                                                                 break;
5291                                                         case 9:
5292                                                                 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5293                                                                 break;
5294                                                         case 10:
5295                                                                 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5296                                                                 break;
5297                                                         case 11:
5298                                                                 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5299                                                                 break;
5300                                                         case 12:
5301                                                                 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5302                                                                 break;
5303                                                         case 13:
5304                                                                 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5305                                                                 break;
5306                                                         case 14:
5307                                                                 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5308                                                                 break;
5309                                                         case 15:
5310                                                                 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5311                                                                 break;
5312                                                         default:
5313                                                                 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5314                                                 }
5315                                         }
5316                                 }
5317                                 break;
5318                 }
5319
5320                 pNextTxRate = pCurrTxRate;
5321         }
5322
5323         RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5324         RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5325         RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5326         RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5327 }
5328
5329 /*
5330         ========================================================================
5331
5332         Routine Description:
5333                 Set MAC register value according operation mode.
5334                 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5335                 If MM or GF mask is not set, those passing argument doesn't not take effect.
5336
5337                 Operation mode meaning:
5338                 = 0 : Pure HT, no preotection.
5339                 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5340                 = 0x10: No Transmission in 40M is protected.
5341                 = 0x11: Transmission in both 40M and 20M shall be protected
5342                 if (bNonGFExist)
5343                         we should choose not to use GF. But still set correct ASIC registers.
5344         ========================================================================
5345 */
5346 VOID    AsicUpdateProtect(
5347         IN              PRTMP_ADAPTER   pAd,
5348         IN              USHORT                  OperationMode,
5349         IN              UCHAR                   SetMask,
5350         IN              BOOLEAN                 bDisableBGProtect,
5351         IN              BOOLEAN                 bNonGFExist)
5352 {
5353         PROT_CFG_STRUC  ProtCfg, ProtCfg4;
5354         UINT32 Protect[6];
5355         USHORT                  offset;
5356         UCHAR                   i;
5357         UINT32 MacReg = 0;
5358
5359         if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5360         {
5361                 return;
5362         }
5363
5364         if (pAd->BATable.numAsOriginator)
5365         {
5366                 //
5367                 // enable the RTS/CTS to avoid channel collision
5368                 //
5369                 SetMask = ALLN_SETPROTECT;
5370                 OperationMode = 8;
5371         }
5372
5373         // Config ASIC RTS threshold register
5374         RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5375         MacReg &= 0xFF0000FF;
5376
5377         // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5378         if ((
5379                         (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5380                         (pAd->CommonCfg.bAggregationCapable == TRUE))
5381             && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5382         {
5383                         MacReg |= (0x1000 << 8);
5384         }
5385         else
5386         {
5387                         MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5388         }
5389
5390         RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5391
5392         // Initial common protection settings
5393         RTMPZeroMemory(Protect, sizeof(Protect));
5394         ProtCfg4.word = 0;
5395         ProtCfg.word = 0;
5396         ProtCfg.field.TxopAllowGF40 = 1;
5397         ProtCfg.field.TxopAllowGF20 = 1;
5398         ProtCfg.field.TxopAllowMM40 = 1;
5399         ProtCfg.field.TxopAllowMM20 = 1;
5400         ProtCfg.field.TxopAllowOfdm = 1;
5401         ProtCfg.field.TxopAllowCck = 1;
5402         ProtCfg.field.RTSThEn = 1;
5403         ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5404
5405         // update PHY mode and rate
5406         if (pAd->CommonCfg.Channel > 14)
5407                 ProtCfg.field.ProtectRate = 0x4000;
5408         ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5409
5410         // Handle legacy(B/G) protection
5411         if (bDisableBGProtect)
5412         {
5413                 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5414                 ProtCfg.field.ProtectCtrl = 0;
5415                 Protect[0] = ProtCfg.word;
5416                 Protect[1] = ProtCfg.word;
5417         }
5418         else
5419         {
5420                 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5421                 ProtCfg.field.ProtectCtrl = 0;                  // CCK do not need to be protected
5422                 Protect[0] = ProtCfg.word;
5423                 ProtCfg.field.ProtectCtrl = ASIC_CTS;   // OFDM needs using CCK to protect
5424                 Protect[1] = ProtCfg.word;
5425         }
5426
5427         // Decide HT frame protection.
5428         if ((SetMask & ALLN_SETPROTECT) != 0)
5429         {
5430                 switch(OperationMode)
5431                 {
5432                         case 0x0:
5433                                 // NO PROTECT
5434                                 // 1.All STAs in the BSS are 20/40 MHz HT
5435                                 // 2. in ai 20/40MHz BSS
5436                                 // 3. all STAs are 20MHz in a 20MHz BSS
5437                                 // Pure HT. no protection.
5438
5439                                 // MM20_PROT_CFG
5440                                 //      Reserved (31:27)
5441                                 //      PROT_TXOP(25:20) -- 010111
5442                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5443                                 //  PROT_CTRL(17:16) -- 00 (None)
5444                                 //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
5445                                 Protect[2] = 0x01744004;
5446
5447                                 // MM40_PROT_CFG
5448                                 //      Reserved (31:27)
5449                                 //      PROT_TXOP(25:20) -- 111111
5450                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5451                                 //  PROT_CTRL(17:16) -- 00 (None)
5452                                 //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
5453                                 Protect[3] = 0x03f44084;
5454
5455                                 // CF20_PROT_CFG
5456                                 //      Reserved (31:27)
5457                                 //      PROT_TXOP(25:20) -- 010111
5458                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5459                                 //  PROT_CTRL(17:16) -- 00 (None)
5460                                 //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
5461                                 Protect[4] = 0x01744004;
5462
5463                                 // CF40_PROT_CFG
5464                                 //      Reserved (31:27)
5465                                 //      PROT_TXOP(25:20) -- 111111
5466                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5467                                 //  PROT_CTRL(17:16) -- 00 (None)
5468                                 //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
5469                                 Protect[5] = 0x03f44084;
5470
5471                                 if (bNonGFExist)
5472                                 {
5473                                         // PROT_NAV(19:18)  -- 01 (Short NAV protectiion)
5474                                         // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5475                                         Protect[4] = 0x01754004;
5476                                         Protect[5] = 0x03f54084;
5477                                 }
5478                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5479                                 break;
5480
5481                         case 1:
5482                                 // This is "HT non-member protection mode."
5483                                 // If there may be non-HT STAs my BSS
5484                                 ProtCfg.word = 0x01744004;      // PROT_CTRL(17:16) : 0 (None)
5485                                 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5486                                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5487                                 {
5488                                         ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
5489                                         ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5490                                 }
5491                                 //Assign Protection method for 20&40 MHz packets
5492                                 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5493                                 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5494                                 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5495                                 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5496                                 Protect[2] = ProtCfg.word;
5497                                 Protect[3] = ProtCfg4.word;
5498                                 Protect[4] = ProtCfg.word;
5499                                 Protect[5] = ProtCfg4.word;
5500                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5501                                 break;
5502
5503                         case 2:
5504                                 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5505                                 ProtCfg.word = 0x01744004;  // PROT_CTRL(17:16) : 0 (None)
5506                                 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5507
5508                                 //Assign Protection method for 40MHz packets
5509                                 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5510                                 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5511                                 Protect[2] = ProtCfg.word;
5512                                 Protect[3] = ProtCfg4.word;
5513                                 if (bNonGFExist)
5514                                 {
5515                                         ProtCfg.field.ProtectCtrl = ASIC_RTS;
5516                                         ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5517                                 }
5518                                 Protect[4] = ProtCfg.word;
5519                                 Protect[5] = ProtCfg4.word;
5520
5521                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5522                                 break;
5523
5524                         case 3:
5525                                 // HT mixed mode.        PROTECT ALL!
5526                                 // Assign Rate
5527                                 ProtCfg.word = 0x01744004;      //duplicaet legacy 24M. BW set 1.
5528                                 ProtCfg4.word = 0x03f44084;
5529                                 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5530                                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5531                                 {
5532                                         ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
5533                                         ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5534                                 }
5535                                 //Assign Protection method for 20&40 MHz packets
5536                                 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5537                                 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5538                                 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5539                                 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5540                                 Protect[2] = ProtCfg.word;
5541                                 Protect[3] = ProtCfg4.word;
5542                                 Protect[4] = ProtCfg.word;
5543                                 Protect[5] = ProtCfg4.word;
5544                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5545                                 break;
5546
5547                         case 8:
5548                                 // Special on for Atheros problem n chip.
5549                                 Protect[2] = 0x01754004;
5550                                 Protect[3] = 0x03f54084;
5551                                 Protect[4] = 0x01754004;
5552                                 Protect[5] = 0x03f54084;
5553                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5554                                 break;
5555                 }
5556         }
5557
5558         offset = CCK_PROT_CFG;
5559         for (i = 0;i < 6;i++)
5560         {
5561                 if ((SetMask & (1<< i)))
5562                 {
5563                         RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5564                 }
5565         }
5566 }
5567
5568 #ifdef RT30xx
5569 // add by johnli, RF power sequence setup
5570 /*
5571         ==========================================================================
5572         Description:
5573
5574         Load RF normal operation-mode setup
5575
5576         ==========================================================================
5577  */
5578 VOID RT30xxLoadRFNormalModeSetup(
5579         IN PRTMP_ADAPTER        pAd)
5580 {
5581         UCHAR RFValue;
5582
5583         // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5584         RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5585         RFValue = (RFValue & (~0x0C)) | 0x31;
5586         RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5587
5588         // TX_LO2_en, RF R15 register Bit 3 to 0
5589         RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5590         RFValue &= (~0x08);
5591         RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5592
5593         // TX_LO1_en, RF R17 register Bit 3 to 0
5594         RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5595         RFValue &= (~0x08);
5596         // to fix rx long range issue
5597         if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5598         {
5599                 RFValue |= 0x20;
5600         }
5601         RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5602
5603         // RX_LO1_en, RF R20 register Bit 3 to 0
5604         RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5605         RFValue &= (~0x08);
5606         RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5607
5608         // RX_LO2_en, RF R21 register Bit 3 to 0
5609         RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5610         RFValue &= (~0x08);
5611         RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5612
5613         // LDORF_VC, RF R27 register Bit 2 to 0
5614         RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5615         if ((pAd->MACVersion & 0xffff) < 0x0211)
5616                 RFValue = (RFValue & (~0x77)) | 0x3;
5617         else
5618                 RFValue = (RFValue & (~0x77));
5619         RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5620         /* end johnli */
5621 }
5622
5623 /*
5624         ==========================================================================
5625         Description:
5626
5627         Load RF sleep-mode setup
5628
5629         ==========================================================================
5630  */
5631 VOID RT30xxLoadRFSleepModeSetup(
5632         IN PRTMP_ADAPTER        pAd)
5633 {
5634         UCHAR RFValue;
5635         UINT32 MACValue;
5636
5637         // RF_BLOCK_en. RF R1 register Bit 0 to 0
5638         RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5639         RFValue &= (~0x01);
5640         RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5641
5642         // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5643         RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5644         RFValue &= (~0x30);
5645         RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5646
5647         // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5648         RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5649         RFValue &= (~0x0E);
5650         RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5651
5652         // RX_CTB_en, RF R21 register Bit 7 to 0
5653         RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5654         RFValue &= (~0x80);
5655         RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5656
5657         // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5658         RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5659         RFValue |= 0x77;
5660         RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5661
5662         RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5663         MACValue |= 0x1D000000;
5664         RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5665 }
5666
5667 /*
5668         ==========================================================================
5669         Description:
5670
5671         Reverse RF sleep-mode setup
5672
5673         ==========================================================================
5674  */
5675 VOID RT30xxReverseRFSleepModeSetup(
5676         IN PRTMP_ADAPTER        pAd)
5677 {
5678         UCHAR RFValue;
5679         UINT32 MACValue;
5680
5681         // RF_BLOCK_en, RF R1 register Bit 0 to 1
5682         RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5683         RFValue |= 0x01;
5684         RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5685
5686         // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5687         RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5688         RFValue |= 0x30;
5689         RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5690
5691         // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5692         RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5693         RFValue |= 0x0E;
5694         RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5695
5696         // RX_CTB_en, RF R21 register Bit 7 to 1
5697         RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5698         RFValue |= 0x80;
5699         RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5700
5701         // LDORF_VC, RF R27 register Bit 2 to 0
5702         RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5703         if ((pAd->MACVersion & 0xffff) < 0x0211)
5704                 RFValue = (RFValue & (~0x77)) | 0x3;
5705         else
5706                 RFValue = (RFValue & (~0x77));
5707         RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5708
5709         // RT3071 version E has fixed this issue
5710         if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5711         {
5712                 // patch tx EVM issue temporarily
5713                 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5714                 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5715                 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5716         }
5717         else
5718         {
5719                 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5720                 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5721                 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5722         }
5723 }
5724 // end johnli
5725 #endif // RT30xx //
5726
5727 /*
5728         ==========================================================================
5729         Description:
5730
5731         IRQL = PASSIVE_LEVEL
5732         IRQL = DISPATCH_LEVEL
5733
5734         ==========================================================================
5735  */
5736 VOID AsicSwitchChannel(
5737                                           IN PRTMP_ADAPTER pAd,
5738         IN      UCHAR                   Channel,
5739         IN      BOOLEAN                 bScan)
5740 {
5741         ULONG                   R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5742         CHAR    TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5743         UCHAR   index;
5744         UINT32  Value = 0; //BbpReg, Value;
5745         RTMP_RF_REGS *RFRegTable;
5746
5747         // Search Tx power value
5748         // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5749         // in ChannelList, so use TxPower array instead.
5750         //
5751         for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5752         {
5753                 if (Channel == pAd->TxPower[index].Channel)
5754         {
5755                         TxPwer = pAd->TxPower[index].Power;
5756                         TxPwer2 = pAd->TxPower[index].Power2;
5757                         break;
5758                 }
5759         }
5760
5761         if (index == MAX_NUM_OF_CHANNELS)
5762                 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5763
5764 #ifdef RT2870
5765         // The RF programming sequence is difference between 3xxx and 2xxx
5766         if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && (
5767 #ifdef RT30xx
5768              (pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) ||
5769 #endif
5770              (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5771         {
5772                 /* modify by WY for Read RF Reg. error */
5773                 UCHAR RFValue;
5774
5775                 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5776                 {
5777                         if (Channel == FreqItems3020[index].Channel)
5778                         {
5779                                 // Programming channel parameters
5780                                 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5781                                 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5782
5783                                 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5784                                 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5785                                 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5786
5787                                 // Set Tx0 Power
5788                                 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5789                                 RFValue = (RFValue & 0xE0) | TxPwer;
5790                                 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5791
5792 #ifdef RT30xx
5793                                 // Set Tx1 Power
5794                                 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5795                                 RFValue = (RFValue & 0xE0) | TxPwer2;
5796                                 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5797
5798                                 // Tx/Rx Stream setting
5799                                 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5800                                 //if (IS_RT3090(pAd))
5801                                 //      RFValue |= 0x01; // Enable RF block.
5802                                 RFValue &= 0x03;        //clear bit[7~2]
5803                                 if (pAd->Antenna.field.TxPath == 1)
5804                                         RFValue |= 0xA0;
5805                                 else if (pAd->Antenna.field.TxPath == 2)
5806                                         RFValue |= 0x80;
5807                                 if (pAd->Antenna.field.RxPath == 1)
5808                                         RFValue |= 0x50;
5809                                 else if (pAd->Antenna.field.RxPath == 2)
5810                                         RFValue |= 0x40;
5811                                 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5812 #endif
5813
5814                                 // Set RF offset
5815                                 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5816                                 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5817                                 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5818
5819                                 // Set BW
5820                                 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5821                                 {
5822                                         RFValue = pAd->Mlme.CaliBW40RfR24;
5823                                         //DISABLE_11N_CHECK(pAd);
5824                                 }
5825                                 else
5826                                 {
5827                                         RFValue = pAd->Mlme.CaliBW20RfR24;
5828                                 }
5829                                 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5830 #ifdef RT30xx
5831                                 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5832 #endif
5833                                 // Enable RF tuning
5834                                 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5835                                 RFValue = RFValue | 0x1;
5836                                 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5837
5838                                 // latch channel for future usage.
5839                                 pAd->LatchRfRegs.Channel = Channel;
5840
5841 #ifdef RT30xx
5842                                 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5843                                         Channel,
5844                                         pAd->RfIcType,
5845                                         TxPwer,
5846                                         TxPwer2,
5847                                         pAd->Antenna.field.TxPath,
5848                                         FreqItems3020[index].N,
5849                                         FreqItems3020[index].K,
5850                                         FreqItems3020[index].R));
5851 #endif
5852
5853                                 break;
5854                         }
5855                 }
5856
5857                 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5858                         Channel,
5859                         pAd->RfIcType,
5860                         TxPwer,
5861                         TxPwer2,
5862                         pAd->Antenna.field.TxPath,
5863                         FreqItems3020[index].N,
5864                         FreqItems3020[index].K,
5865                         FreqItems3020[index].R));
5866         }
5867         else
5868 #endif // RT2870 //
5869         {
5870                 RFRegTable = RF2850RegTable;
5871
5872                 switch (pAd->RfIcType)
5873                 {
5874                         case RFIC_2820:
5875                         case RFIC_2850:
5876                         case RFIC_2720:
5877                         case RFIC_2750:
5878
5879                         for (index = 0; index < NUM_OF_2850_CHNL; index++)
5880                         {
5881                                 if (Channel == RFRegTable[index].Channel)
5882                                 {
5883                                         R2 = RFRegTable[index].R2;
5884                                         if (pAd->Antenna.field.TxPath == 1)
5885                                         {
5886                                                 R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
5887                                         }
5888
5889                                         if (pAd->Antenna.field.RxPath == 2)
5890                                         {
5891                                                 R2 |= 0x40;     // write 1 to off Rxpath.
5892                                         }
5893                                         else if (pAd->Antenna.field.RxPath == 1)
5894                                         {
5895                                                 R2 |= 0x20040;  // write 1 to off RxPath
5896                                         }
5897
5898                                         if (Channel > 14)
5899                                         {
5900                                                 // initialize R3, R4
5901                                                 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5902                                                 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5903
5904                                                 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5905                                                 // R3
5906                                                 if ((TxPwer >= -7) && (TxPwer < 0))
5907                                                 {
5908                                                         TxPwer = (7+TxPwer);
5909                                                         TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5910                                                         R3 |= (TxPwer << 10);
5911                                                         DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5912                                                 }
5913                                                 else
5914                                                 {
5915                                                         TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5916                                                         R3 |= (TxPwer << 10) | (1 << 9);
5917                                                 }
5918
5919                                                 // R4
5920                                                 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5921                                                 {
5922                                                         TxPwer2 = (7+TxPwer2);
5923                                                         TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5924                                                         R4 |= (TxPwer2 << 7);
5925                                                         DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5926                                                 }
5927                                                 else
5928                                                 {
5929                                                         TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5930                                                         R4 |= (TxPwer2 << 7) | (1 << 6);
5931                                                 }
5932                                         }
5933                                         else
5934                                         {
5935                                                 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5936                                         R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5937                                         }
5938
5939                                         // Based on BBP current mode before changing RF channel.
5940                                         if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5941                                         {
5942                                                 R4 |=0x200000;
5943                                         }
5944
5945                                         // Update variables
5946                                         pAd->LatchRfRegs.Channel = Channel;
5947                                         pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5948                                         pAd->LatchRfRegs.R2 = R2;
5949                                         pAd->LatchRfRegs.R3 = R3;
5950                                         pAd->LatchRfRegs.R4 = R4;
5951
5952                                         // Set RF value 1's set R3[bit2] = [0]
5953                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5954                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5955                                         RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5956                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5957
5958                                         RTMPusecDelay(200);
5959
5960                                         // Set RF value 2's set R3[bit2] = [1]
5961                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5962                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5963                                         RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5964                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5965
5966                                         RTMPusecDelay(200);
5967
5968                                         // Set RF value 3's set R3[bit2] = [0]
5969                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5970                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5971                                         RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5972                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5973
5974                                         break;
5975                                 }
5976                         }
5977                         break;
5978
5979                         default:
5980                         break;
5981                 }
5982         }
5983
5984         // Change BBP setting during siwtch from a->g, g->a
5985         if (Channel <= 14)
5986         {
5987             ULONG       TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5988
5989                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5990                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5991                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5992                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd)));    // According the Rory's suggestion to solve the middle range issue.
5993                 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5994
5995                 // Rx High power VGA offset for LNA select
5996             if (pAd->NicConfig2.field.ExternalLNAForG)
5997             {
5998                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5999                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6000             }
6001             else
6002             {
6003                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6004                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6005             }
6006
6007                 // 5G band selection PIN, bit1 and bit2 are complement
6008                 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6009                 Value &= (~0x6);
6010                 Value |= (0x04);
6011                 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6012
6013         // Turn off unused PA or LNA when only 1T or 1R
6014                 if (pAd->Antenna.field.TxPath == 1)
6015                 {
6016                         TxPinCfg &= 0xFFFFFFF3;
6017                 }
6018                 if (pAd->Antenna.field.RxPath == 1)
6019                 {
6020                         TxPinCfg &= 0xFFFFF3FF;
6021                 }
6022
6023                 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6024         }
6025         else
6026         {
6027             ULONG       TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6028
6029                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6030                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6031                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6032                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd)));   // According the Rory's suggestion to solve the middle range issue.
6033                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6034
6035                 // Rx High power VGA offset for LNA select
6036                 if (pAd->NicConfig2.field.ExternalLNAForA)
6037                 {
6038                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6039                 }
6040                 else
6041                 {
6042                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6043                 }
6044
6045                 // 5G band selection PIN, bit1 and bit2 are complement
6046                 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6047                 Value &= (~0x6);
6048                 Value |= (0x02);
6049                 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6050
6051         // Turn off unused PA or LNA when only 1T or 1R
6052                 if (pAd->Antenna.field.TxPath == 1)
6053                 {
6054                         TxPinCfg &= 0xFFFFFFF3;
6055         }
6056                 if (pAd->Antenna.field.RxPath == 1)
6057                 {
6058                         TxPinCfg &= 0xFFFFF3FF;
6059         }
6060
6061                 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6062         }
6063
6064     // R66 should be set according to Channel and use 20MHz when scanning
6065         //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6066         if (bScan)
6067                 RTMPSetAGCInitValue(pAd, BW_20);
6068         else
6069                 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6070
6071         //
6072         // On 11A, We should delay and wait RF/BBP to be stable
6073         // and the appropriate time should be 1000 micro seconds
6074         // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6075         //
6076         RTMPusecDelay(1000);
6077
6078         DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
6079                                                           Channel,
6080                                                           pAd->RfIcType,
6081                                                           (R3 & 0x00003e00) >> 9,
6082                                                           (R4 & 0x000007c0) >> 6,
6083                                                           pAd->Antenna.field.TxPath,
6084                                                           pAd->LatchRfRegs.R1,
6085                                                           pAd->LatchRfRegs.R2,
6086                                                           pAd->LatchRfRegs.R3,
6087                                                           pAd->LatchRfRegs.R4));
6088 }
6089
6090 /*
6091         ==========================================================================
6092         Description:
6093                 This function is required for 2421 only, and should not be used during
6094                 site survey. It's only required after NIC decided to stay at a channel
6095                 for a longer period.
6096                 When this function is called, it's always after AsicSwitchChannel().
6097
6098         IRQL = PASSIVE_LEVEL
6099         IRQL = DISPATCH_LEVEL
6100
6101         ==========================================================================
6102  */
6103 VOID AsicLockChannel(
6104         IN PRTMP_ADAPTER pAd,
6105         IN UCHAR Channel)
6106 {
6107 }
6108
6109 VOID AsicRfTuningExec(
6110         IN PVOID SystemSpecific1,
6111         IN PVOID FunctionContext,
6112         IN PVOID SystemSpecific2,
6113         IN PVOID SystemSpecific3)
6114 {
6115 }
6116
6117 /*
6118         ==========================================================================
6119         Description:
6120                 Gives CCK TX rate 2 more dB TX power.
6121                 This routine works only in LINK UP in INFRASTRUCTURE mode.
6122
6123                 calculate desired Tx power in RF R3.Tx0~5,      should consider -
6124                 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6125                 1. TxPowerPercentage
6126                 2. auto calibration based on TSSI feedback
6127                 3. extra 2 db for CCK
6128                 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6129
6130         NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6131                 it should be called AFTER MlmeDynamicTxRatSwitching()
6132         ==========================================================================
6133  */
6134 VOID AsicAdjustTxPower(
6135         IN PRTMP_ADAPTER pAd)
6136 {
6137         INT                     i, j;
6138         CHAR            DeltaPwr = 0;
6139         BOOLEAN         bAutoTxAgc = FALSE;
6140         UCHAR           TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6141         UCHAR           BbpR1 = 0, BbpR49 = 0, idx;
6142         PCHAR           pTxAgcCompensate;
6143         ULONG           TxPwr[5];
6144         CHAR            Value;
6145
6146 #ifdef RT2860
6147         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6148                 || (pAd->bPCIclkOff == TRUE)
6149                 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6150                 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6151                 return;
6152 #endif
6153
6154         if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6155         {
6156                 if (pAd->CommonCfg.CentralChannel > 14)
6157                 {
6158                         TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6159                         TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6160                         TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6161                         TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6162                         TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6163                 }
6164                 else
6165                 {
6166                         TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6167                         TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6168                         TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6169                         TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6170                         TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6171                 }
6172         }
6173         else
6174         {
6175                 if (pAd->CommonCfg.Channel > 14)
6176                 {
6177                         TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6178                         TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6179                         TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6180                         TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6181                         TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6182                 }
6183                 else
6184                 {
6185                         TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6186                         TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6187                         TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6188                         TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6189                         TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6190                 }
6191         }
6192
6193         // TX power compensation for temperature variation based on TSSI. try every 4 second
6194         if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6195         {
6196                 if (pAd->CommonCfg.Channel <= 14)
6197                 {
6198                         /* bg channel */
6199                         bAutoTxAgc         = pAd->bAutoTxAgcG;
6200                         TssiRef            = pAd->TssiRefG;
6201                         pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6202                         pTssiPlusBoundary  = &pAd->TssiPlusBoundaryG[0];
6203                         TxAgcStep          = pAd->TxAgcStepG;
6204                         pTxAgcCompensate   = &pAd->TxAgcCompensateG;
6205                 }
6206                 else
6207                 {
6208                         /* a channel */
6209                         bAutoTxAgc         = pAd->bAutoTxAgcA;
6210                         TssiRef            = pAd->TssiRefA;
6211                         pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6212                         pTssiPlusBoundary  = &pAd->TssiPlusBoundaryA[0];
6213                         TxAgcStep          = pAd->TxAgcStepA;
6214                         pTxAgcCompensate   = &pAd->TxAgcCompensateA;
6215                 }
6216
6217                 if (bAutoTxAgc)
6218                 {
6219                         /* BbpR1 is unsigned char */
6220                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6221
6222                         /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6223                         /* compensate: +4     +3   +2   +1    0   -1   -2   -3   -4 * steps */
6224                         /* step value is defined in pAd->TxAgcStepG for tx power value */
6225
6226                         /* [4]+1+[4]   p4     p3   p2   p1   o1   m1   m2   m3   m4 */
6227                         /* ex:         0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6228                            above value are examined in mass factory production */
6229                         /*             [4]    [3]  [2]  [1]  [0]  [1]  [2]  [3]  [4] */
6230
6231                         /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6232                         /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6233                         /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6234
6235                         if (BbpR49 > pTssiMinusBoundary[1])
6236                         {
6237                                 // Reading is larger than the reference value
6238                                 // check for how large we need to decrease the Tx power
6239                                 for (idx = 1; idx < 5; idx++)
6240                                 {
6241                                         if (BbpR49 <= pTssiMinusBoundary[idx])  // Found the range
6242                                                 break;
6243                                 }
6244                                 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6245                                 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6246
6247                                 DeltaPwr += (*pTxAgcCompensate);
6248                                 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6249                                         BbpR49, TssiRef, TxAgcStep, idx-1));
6250                         }
6251                         else if (BbpR49 < pTssiPlusBoundary[1])
6252                         {
6253                                 // Reading is smaller than the reference value
6254                                 // check for how large we need to increase the Tx power
6255                                 for (idx = 1; idx < 5; idx++)
6256                                 {
6257                                         if (BbpR49 >= pTssiPlusBoundary[idx])   // Found the range
6258                                                 break;
6259                                 }
6260                                 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6261                                 *pTxAgcCompensate = TxAgcStep * (idx-1);
6262                                 DeltaPwr += (*pTxAgcCompensate);
6263                                 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6264                                         BbpR49, TssiRef, TxAgcStep, idx-1));
6265                         }
6266                         else
6267                         {
6268                                 *pTxAgcCompensate = 0;
6269                                 DBGPRINT(RT_DEBUG_TRACE, ("   Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6270                                         BbpR49, TssiRef, TxAgcStep, 0));
6271                         }
6272                 }
6273         }
6274         else
6275         {
6276                 if (pAd->CommonCfg.Channel <= 14)
6277                 {
6278                         bAutoTxAgc         = pAd->bAutoTxAgcG;
6279                         pTxAgcCompensate   = &pAd->TxAgcCompensateG;
6280                 }
6281                 else
6282                 {
6283                         bAutoTxAgc         = pAd->bAutoTxAgcA;
6284                         pTxAgcCompensate   = &pAd->TxAgcCompensateA;
6285                 }
6286
6287                 if (bAutoTxAgc)
6288                         DeltaPwr += (*pTxAgcCompensate);
6289         }
6290
6291         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6292         BbpR1 &= 0xFC;
6293
6294         /* calculate delta power based on the percentage specified from UI */
6295         // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6296         // We lower TX power here according to the percentage specified from UI
6297         if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff)       // AUTO TX POWER control
6298                 ;
6299         else if (pAd->CommonCfg.TxPowerPercentage > 90)  // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6300                 ;
6301         else if (pAd->CommonCfg.TxPowerPercentage > 60)  // 61 ~ 90%, treat as 75% in terms of mW               // DeltaPwr -= 1;
6302         {
6303                 DeltaPwr -= 1;
6304         }
6305         else if (pAd->CommonCfg.TxPowerPercentage > 30)  // 31 ~ 60%, treat as 50% in terms of mW               // DeltaPwr -= 3;
6306         {
6307                 DeltaPwr -= 3;
6308         }
6309         else if (pAd->CommonCfg.TxPowerPercentage > 15)  // 16 ~ 30%, treat as 25% in terms of mW               // DeltaPwr -= 6;
6310         {
6311                 BbpR1 |= 0x01;
6312         }
6313         else if (pAd->CommonCfg.TxPowerPercentage > 9)   // 10 ~ 15%, treat as 12.5% in terms of mW             // DeltaPwr -= 9;
6314         {
6315                 BbpR1 |= 0x01;
6316                 DeltaPwr -= 3;
6317         }
6318         else                                           // 0 ~ 9 %, treat as MIN(~3%) in terms of mW             // DeltaPwr -= 12;
6319         {
6320                 BbpR1 |= 0x02;
6321         }
6322
6323         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6324
6325         /* reset different new tx power for different TX rate */
6326         for(i=0; i<5; i++)
6327         {
6328                 if (TxPwr[i] != 0xffffffff)
6329                 {
6330                         for (j=0; j<8; j++)
6331                         {
6332                                 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6333
6334                                 if ((Value + DeltaPwr) < 0)
6335                                 {
6336                                         Value = 0; /* min */
6337                                 }
6338                                 else if ((Value + DeltaPwr) > 0xF)
6339                                 {
6340                                         Value = 0xF; /* max */
6341                                 }
6342                                 else
6343                                 {
6344                                         Value += DeltaPwr; /* temperature compensation */
6345                                 }
6346
6347                                 /* fill new value to CSR offset */
6348                                 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6349                         }
6350
6351                         /* write tx power value to CSR */
6352                         /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6353                                                                                         TX power for OFDM 6M/9M
6354                                                                                         TX power for CCK5.5M/11M
6355                                                                                         TX power for CCK1M/2M */
6356                         /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6357                         RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6358                 }
6359         }
6360
6361 }
6362
6363 /*
6364         ==========================================================================
6365         Description:
6366                 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6367                 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6368                 the wakeup timer timeout. Driver has to issue a separate command to wake
6369                 PHY up.
6370
6371         IRQL = DISPATCH_LEVEL
6372
6373         ==========================================================================
6374  */
6375 VOID AsicSleepThenAutoWakeup(
6376         IN PRTMP_ADAPTER pAd,
6377         IN USHORT TbttNumToNextWakeUp)
6378 {
6379     RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6380 }
6381
6382 /*
6383         ==========================================================================
6384         Description:
6385                 AsicForceWakeup() is used whenever manual wakeup is required
6386                 AsicForceSleep() should only be used when not in INFRA BSS. When
6387                 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6388         ==========================================================================
6389  */
6390 VOID AsicForceSleep(
6391         IN PRTMP_ADAPTER pAd)
6392 {
6393
6394 }
6395
6396 /*
6397         ==========================================================================
6398         Description:
6399                 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6400                 expired.
6401
6402         IRQL = PASSIVE_LEVEL
6403         IRQL = DISPATCH_LEVEL
6404         ==========================================================================
6405  */
6406 VOID AsicForceWakeup(
6407         IN PRTMP_ADAPTER pAd,
6408 #ifdef RT2860
6409         IN UCHAR         Level)
6410 #endif
6411 #ifdef RT2870
6412         IN BOOLEAN    bFromTx)
6413 #endif
6414 {
6415     DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6416 #ifdef RT2860
6417     RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6418 #endif
6419 #ifdef RT2870
6420     RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6421 #endif
6422 }
6423
6424 /*
6425         ==========================================================================
6426         Description:
6427                 Set My BSSID
6428
6429         IRQL = DISPATCH_LEVEL
6430
6431         ==========================================================================
6432  */
6433 VOID AsicSetBssid(
6434         IN PRTMP_ADAPTER pAd,
6435         IN PUCHAR pBssid)
6436 {
6437         ULONG             Addr4;
6438         DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6439                 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6440
6441         Addr4 = (ULONG)(pBssid[0])               |
6442                         (ULONG)(pBssid[1] << 8)  |
6443                         (ULONG)(pBssid[2] << 16) |
6444                         (ULONG)(pBssid[3] << 24);
6445         RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6446
6447         Addr4 = 0;
6448         // always one BSSID in STA mode
6449         Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6450
6451         RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6452 }
6453
6454 VOID AsicSetMcastWC(
6455         IN PRTMP_ADAPTER pAd)
6456 {
6457         MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6458         USHORT          offset;
6459
6460         pEntry->Sst        = SST_ASSOC;
6461         pEntry->Aid        = MCAST_WCID;        // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6462         pEntry->PsMode     = PWR_ACTIVE;
6463         pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6464         offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6465 }
6466
6467 /*
6468         ==========================================================================
6469         Description:
6470
6471         IRQL = DISPATCH_LEVEL
6472
6473         ==========================================================================
6474  */
6475 VOID AsicDelWcidTab(
6476         IN PRTMP_ADAPTER pAd,
6477         IN UCHAR        Wcid)
6478 {
6479         ULONG             Addr0 = 0x0, Addr1 = 0x0;
6480         ULONG           offset;
6481
6482         DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6483         offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6484         RTMP_IO_WRITE32(pAd, offset, Addr0);
6485         offset += 4;
6486         RTMP_IO_WRITE32(pAd, offset, Addr1);
6487 }
6488
6489 /*
6490         ==========================================================================
6491         Description:
6492
6493         IRQL = DISPATCH_LEVEL
6494
6495         ==========================================================================
6496  */
6497 VOID AsicEnableRDG(
6498         IN PRTMP_ADAPTER pAd)
6499 {
6500         TX_LINK_CFG_STRUC       TxLinkCfg;
6501         UINT32                          Data = 0;
6502
6503         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6504         TxLinkCfg.field.TxRDGEn = 1;
6505         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6506
6507         RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6508         Data  &= 0xFFFFFF00;
6509         Data  |= 0x80;
6510         RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6511
6512         //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6513 }
6514
6515 /*
6516         ==========================================================================
6517         Description:
6518
6519         IRQL = DISPATCH_LEVEL
6520
6521         ==========================================================================
6522  */
6523 VOID AsicDisableRDG(
6524         IN PRTMP_ADAPTER pAd)
6525 {
6526         TX_LINK_CFG_STRUC       TxLinkCfg;
6527         UINT32                          Data = 0;
6528
6529
6530         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6531         TxLinkCfg.field.TxRDGEn = 0;
6532         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6533
6534         RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6535
6536         Data  &= 0xFFFFFF00;
6537         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6538                 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6539         )
6540         {
6541                 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6542                 if (pAd->CommonCfg.bEnableTxBurst)
6543                         Data |= 0x20;
6544         }
6545         RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6546 }
6547
6548 /*
6549         ==========================================================================
6550         Description:
6551
6552         IRQL = PASSIVE_LEVEL
6553         IRQL = DISPATCH_LEVEL
6554
6555         ==========================================================================
6556  */
6557 VOID AsicDisableSync(
6558         IN PRTMP_ADAPTER pAd)
6559 {
6560         BCN_TIME_CFG_STRUC csr;
6561
6562         DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6563
6564         // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6565         //                        that NIC will never wakes up because TSF stops and no more
6566         //                        TBTT interrupts
6567         pAd->TbttTickCount = 0;
6568         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6569         csr.field.bBeaconGen = 0;
6570         csr.field.bTBTTEnable = 0;
6571         csr.field.TsfSyncMode = 0;
6572         csr.field.bTsfTicking = 0;
6573         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6574
6575 }
6576
6577 /*
6578         ==========================================================================
6579         Description:
6580
6581         IRQL = DISPATCH_LEVEL
6582
6583         ==========================================================================
6584  */
6585 VOID AsicEnableBssSync(
6586         IN PRTMP_ADAPTER pAd)
6587 {
6588         BCN_TIME_CFG_STRUC csr;
6589
6590         DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6591
6592         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6593
6594         {
6595                 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6596                 csr.field.bTsfTicking = 1;
6597                 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6598                 csr.field.bBeaconGen  = 0; // do NOT generate BEACON
6599                 csr.field.bTBTTEnable = 1;
6600         }
6601
6602         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6603 }
6604
6605 /*
6606         ==========================================================================
6607         Description:
6608         Note:
6609                 BEACON frame in shared memory should be built ok before this routine
6610                 can be called. Otherwise, a garbage frame maybe transmitted out every
6611                 Beacon period.
6612
6613         IRQL = DISPATCH_LEVEL
6614
6615         ==========================================================================
6616  */
6617 VOID AsicEnableIbssSync(
6618         IN PRTMP_ADAPTER pAd)
6619 {
6620         BCN_TIME_CFG_STRUC csr9;
6621         PUCHAR                  ptr;
6622         UINT i;
6623
6624         DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6625
6626         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6627         csr9.field.bBeaconGen = 0;
6628         csr9.field.bTBTTEnable = 0;
6629         csr9.field.bTsfTicking = 0;
6630         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6631
6632 #ifdef RT2860
6633         // move BEACON TXD and frame content to on-chip memory
6634         ptr = (PUCHAR)&pAd->BeaconTxWI;
6635         for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
6636         {
6637                 UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6638                 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6639                 ptr += 4;
6640         }
6641
6642         // start right after the 16-byte TXWI field
6643         ptr = pAd->BeaconBuf;
6644         for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6645         {
6646                 UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6647                 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6648                 ptr +=4;
6649         }
6650 #endif
6651 #ifdef RT2870
6652         // move BEACON TXD and frame content to on-chip memory
6653         ptr = (PUCHAR)&pAd->BeaconTxWI;
6654         for (i=0; i<TXWI_SIZE; i+=2)  // 16-byte TXWI field
6655         {
6656                 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6657                 ptr += 2;
6658         }
6659
6660         // start right after the 16-byte TXWI field
6661         ptr = pAd->BeaconBuf;
6662         for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6663         {
6664                 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6665                 ptr +=2;
6666         }
6667 #endif // RT2870 //
6668
6669         // start sending BEACON
6670         csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6671         csr9.field.bTsfTicking = 1;
6672         csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6673         csr9.field.bTBTTEnable = 1;
6674         csr9.field.bBeaconGen = 1;
6675         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6676 }
6677
6678 /*
6679         ==========================================================================
6680         Description:
6681
6682         IRQL = PASSIVE_LEVEL
6683         IRQL = DISPATCH_LEVEL
6684
6685         ==========================================================================
6686  */
6687 VOID AsicSetEdcaParm(
6688         IN PRTMP_ADAPTER pAd,
6689         IN PEDCA_PARM    pEdcaParm)
6690 {
6691         EDCA_AC_CFG_STRUC   Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6692         AC_TXOP_CSR0_STRUC csr0;
6693         AC_TXOP_CSR1_STRUC csr1;
6694         AIFSN_CSR_STRUC    AifsnCsr;
6695         CWMIN_CSR_STRUC    CwminCsr;
6696         CWMAX_CSR_STRUC    CwmaxCsr;
6697         int i;
6698
6699         Ac0Cfg.word = 0;
6700         Ac1Cfg.word = 0;
6701         Ac2Cfg.word = 0;
6702         Ac3Cfg.word = 0;
6703         if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6704         {
6705                 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6706                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6707                 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6708                 {
6709                         if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6710                                 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6711                 }
6712
6713                 //========================================================
6714                 //      MAC Register has a copy .
6715                 //========================================================
6716                 if( pAd->CommonCfg.bEnableTxBurst )
6717                 {
6718                         // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6719                         Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6720                 }
6721                 else
6722                         Ac0Cfg.field.AcTxop = 0;        // QID_AC_BE
6723                 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6724                 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6725                 Ac0Cfg.field.Aifsn = 2;
6726                 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6727
6728                 Ac1Cfg.field.AcTxop = 0;        // QID_AC_BK
6729                 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6730                 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6731                 Ac1Cfg.field.Aifsn = 2;
6732                 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6733
6734                 if (pAd->CommonCfg.PhyMode == PHY_11B)
6735                 {
6736                         Ac2Cfg.field.AcTxop = 192;      // AC_VI: 192*32us ~= 6ms
6737                         Ac3Cfg.field.AcTxop = 96;       // AC_VO: 96*32us  ~= 3ms
6738                 }
6739                 else
6740                 {
6741                         Ac2Cfg.field.AcTxop = 96;       // AC_VI: 96*32us ~= 3ms
6742                         Ac3Cfg.field.AcTxop = 48;       // AC_VO: 48*32us ~= 1.5ms
6743                 }
6744                 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6745                 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6746                 Ac2Cfg.field.Aifsn = 2;
6747                 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6748                 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6749                 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6750                 Ac3Cfg.field.Aifsn = 2;
6751                 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6752
6753                 //========================================================
6754                 //      DMA Register has a copy too.
6755                 //========================================================
6756                 csr0.field.Ac0Txop = 0;         // QID_AC_BE
6757                 csr0.field.Ac1Txop = 0;         // QID_AC_BK
6758                 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6759                 if (pAd->CommonCfg.PhyMode == PHY_11B)
6760                 {
6761                         csr1.field.Ac2Txop = 192;               // AC_VI: 192*32us ~= 6ms
6762                         csr1.field.Ac3Txop = 96;                // AC_VO: 96*32us  ~= 3ms
6763                 }
6764                 else
6765                 {
6766                         csr1.field.Ac2Txop = 96;                // AC_VI: 96*32us ~= 3ms
6767                         csr1.field.Ac3Txop = 48;                // AC_VO: 48*32us ~= 1.5ms
6768                 }
6769                 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6770
6771                 CwminCsr.word = 0;
6772                 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6773                 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6774                 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6775                 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6776                 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6777
6778                 CwmaxCsr.word = 0;
6779                 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6780                 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6781                 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6782                 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6783                 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6784
6785                 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6786
6787                 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6788         }
6789         else
6790         {
6791                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6792                 //========================================================
6793                 //      MAC Register has a copy.
6794                 //========================================================
6795                 //
6796                 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6797                 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6798                 //
6799                 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6800
6801                 Ac0Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BE];
6802                 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6803                 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6804                 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6805
6806                 Ac1Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BK];
6807                 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6808                 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6809                 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6810
6811                 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6812                 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6813                 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6814                 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6815
6816                 {
6817                         // Tuning for Wi-Fi WMM S06
6818                         if (pAd->CommonCfg.bWiFiTest &&
6819                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6820                                 Ac2Cfg.field.Aifsn -= 1;
6821
6822                         // Tuning for TGn Wi-Fi 5.2.32
6823                         // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6824                         if (STA_TGN_WIFI_ON(pAd) &&
6825                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6826                         {
6827                                 Ac0Cfg.field.Aifsn = 3;
6828                                 Ac2Cfg.field.AcTxop = 5;
6829                         }
6830
6831 #ifdef RT30xx
6832                         if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6833                         {
6834                                 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6835                                 Ac2Cfg.field.Aifsn = 5;
6836                         }
6837 #endif // RT30xx //
6838                 }
6839
6840                 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6841                 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6842                 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6843                 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6844
6845 //#ifdef WIFI_TEST
6846                 if (pAd->CommonCfg.bWiFiTest)
6847                 {
6848                         if (Ac3Cfg.field.AcTxop == 102)
6849                         {
6850                         Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6851                                 Ac0Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6852                         Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6853                                 Ac1Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BK];
6854                         Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6855                         } /* End of if */
6856                 }
6857 //#endif // WIFI_TEST //
6858
6859                 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6860                 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6861                 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6862                 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6863
6864
6865                 //========================================================
6866                 //      DMA Register has a copy too.
6867                 //========================================================
6868                 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6869                 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6870                 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6871
6872                 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6873                 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6874                 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6875
6876                 CwminCsr.word = 0;
6877                 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6878                 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6879                 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6880
6881                 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6882
6883                 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6884
6885                 CwmaxCsr.word = 0;
6886                 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6887                 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6888                 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6889                 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6890                 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6891
6892                 AifsnCsr.word = 0;
6893                 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6894                 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6895                 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6896
6897                 {
6898                         // Tuning for Wi-Fi WMM S06
6899                         if (pAd->CommonCfg.bWiFiTest &&
6900                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6901                                 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6902
6903                         // Tuning for TGn Wi-Fi 5.2.32
6904                         // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6905                         if (STA_TGN_WIFI_ON(pAd) &&
6906                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6907                         {
6908                                 AifsnCsr.field.Aifsn0 = 3;
6909                                 AifsnCsr.field.Aifsn2 = 7;
6910                         }
6911 #ifdef RT2870
6912                         if (INFRA_ON(pAd))
6913                                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6914 #endif
6915                 }
6916
6917                 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6918 #ifdef RT30xx
6919                 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6920                         AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
6921 #endif // RT30xx //
6922
6923                 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6924
6925                 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6926                 if (!ADHOC_ON(pAd))
6927                 {
6928                         DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax  TXOP(us)  ACM\n", pEdcaParm->EdcaUpdateCount));
6929                         DBGPRINT(RT_DEBUG_TRACE,("     AC_BE      %2d     %2d     %2d      %4d     %d\n",
6930                                                                          pEdcaParm->Aifsn[0],
6931                                                                          pEdcaParm->Cwmin[0],
6932                                                                          pEdcaParm->Cwmax[0],
6933                                                                          pEdcaParm->Txop[0]<<5,
6934                                                                          pEdcaParm->bACM[0]));
6935                         DBGPRINT(RT_DEBUG_TRACE,("     AC_BK      %2d     %2d     %2d      %4d     %d\n",
6936                                                                          pEdcaParm->Aifsn[1],
6937                                                                          pEdcaParm->Cwmin[1],
6938                                                                          pEdcaParm->Cwmax[1],
6939                                                                          pEdcaParm->Txop[1]<<5,
6940                                                                          pEdcaParm->bACM[1]));
6941                         DBGPRINT(RT_DEBUG_TRACE,("     AC_VI      %2d     %2d     %2d      %4d     %d\n",
6942                                                                          pEdcaParm->Aifsn[2],
6943                                                                          pEdcaParm->Cwmin[2],
6944                                                                          pEdcaParm->Cwmax[2],
6945                                                                          pEdcaParm->Txop[2]<<5,
6946                                                                          pEdcaParm->bACM[2]));
6947                         DBGPRINT(RT_DEBUG_TRACE,("     AC_VO      %2d     %2d     %2d      %4d     %d\n",
6948                                                                          pEdcaParm->Aifsn[3],
6949                                                                          pEdcaParm->Cwmin[3],
6950                                                                          pEdcaParm->Cwmax[3],
6951                                                                          pEdcaParm->Txop[3]<<5,
6952                                                                          pEdcaParm->bACM[3]));
6953                 }
6954         }
6955 }
6956
6957 /*
6958         ==========================================================================
6959         Description:
6960
6961         IRQL = PASSIVE_LEVEL
6962         IRQL = DISPATCH_LEVEL
6963
6964         ==========================================================================
6965  */
6966 VOID    AsicSetSlotTime(
6967         IN PRTMP_ADAPTER pAd,
6968         IN BOOLEAN bUseShortSlotTime)
6969 {
6970         ULONG   SlotTime;
6971         UINT32  RegValue = 0;
6972
6973         if (pAd->CommonCfg.Channel > 14)
6974                 bUseShortSlotTime = TRUE;
6975
6976         if (bUseShortSlotTime)
6977                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6978         else
6979                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6980
6981         SlotTime = (bUseShortSlotTime)? 9 : 20;
6982
6983         {
6984                 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6985                 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6986                         || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6987                         )
6988                 {
6989                         // In this case, we will think it is doing Wi-Fi test
6990                         // And we will not set to short slot when bEnableTxBurst is TRUE.
6991                 }
6992                 else if (pAd->CommonCfg.bEnableTxBurst)
6993                         SlotTime = 9;
6994         }
6995
6996         //
6997         // For some reasons, always set it to short slot time.
6998         //
6999         // ToDo: Should consider capability with 11B
7000         //
7001         if (pAd->StaCfg.BssType == BSS_ADHOC)
7002                 SlotTime = 20;
7003
7004         RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7005         RegValue = RegValue & 0xFFFFFF00;
7006
7007         RegValue |= SlotTime;
7008
7009         RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7010 }
7011
7012 /*
7013         ========================================================================
7014         Description:
7015                 Add Shared key information into ASIC.
7016                 Update shared key, TxMic and RxMic to Asic Shared key table
7017                 Update its cipherAlg to Asic Shared key Mode.
7018
7019     Return:
7020         ========================================================================
7021 */
7022 VOID AsicAddSharedKeyEntry(
7023         IN PRTMP_ADAPTER pAd,
7024         IN UCHAR                 BssIndex,
7025         IN UCHAR                 KeyIdx,
7026         IN UCHAR                 CipherAlg,
7027         IN PUCHAR                pKey,
7028         IN PUCHAR                pTxMic,
7029         IN PUCHAR                pRxMic)
7030 {
7031         ULONG offset; //, csr0;
7032         SHAREDKEY_MODE_STRUC csr1;
7033 #ifdef RT2860
7034         INT   i;
7035 #endif
7036
7037         DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7038 //============================================================================================
7039
7040         DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7041         DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7042                 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7043         if (pRxMic)
7044         {
7045                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7046                         pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7047         }
7048         if (pTxMic)
7049         {
7050                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7051                         pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7052         }
7053 //============================================================================================
7054         //
7055         // fill key material - key + TX MIC + RX MIC
7056         //
7057
7058         offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7059 #ifdef RT2860
7060         for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7061         {
7062                 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7063         }
7064 #endif
7065 #ifdef RT2870
7066         RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7067 #endif
7068         offset += MAX_LEN_OF_SHARE_KEY;
7069         if (pTxMic)
7070         {
7071 #ifdef RT2860
7072                 for (i=0; i<8; i++)
7073                 {
7074                         RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7075                 }
7076 #endif
7077 #ifdef RT2870
7078                 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7079 #endif
7080         }
7081
7082         offset += 8;
7083         if (pRxMic)
7084         {
7085 #ifdef RT2860
7086                 for (i=0; i<8; i++)
7087                 {
7088                         RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7089                 }
7090 #endif
7091 #ifdef RT2870
7092                 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7093 #endif
7094         }
7095
7096
7097         //
7098         // Update cipher algorithm. WSTA always use BSS0
7099         //
7100         RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7101         DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7102         if ((BssIndex%2) == 0)
7103         {
7104                 if (KeyIdx == 0)
7105                         csr1.field.Bss0Key0CipherAlg = CipherAlg;
7106                 else if (KeyIdx == 1)
7107                         csr1.field.Bss0Key1CipherAlg = CipherAlg;
7108                 else if (KeyIdx == 2)
7109                         csr1.field.Bss0Key2CipherAlg = CipherAlg;
7110                 else
7111                         csr1.field.Bss0Key3CipherAlg = CipherAlg;
7112         }
7113         else
7114         {
7115                 if (KeyIdx == 0)
7116                         csr1.field.Bss1Key0CipherAlg = CipherAlg;
7117                 else if (KeyIdx == 1)
7118                         csr1.field.Bss1Key1CipherAlg = CipherAlg;
7119                 else if (KeyIdx == 2)
7120                         csr1.field.Bss1Key2CipherAlg = CipherAlg;
7121                 else
7122                         csr1.field.Bss1Key3CipherAlg = CipherAlg;
7123         }
7124         DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7125         RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7126
7127 }
7128
7129 //      IRQL = DISPATCH_LEVEL
7130 VOID AsicRemoveSharedKeyEntry(
7131         IN PRTMP_ADAPTER pAd,
7132         IN UCHAR                 BssIndex,
7133         IN UCHAR                 KeyIdx)
7134 {
7135         //ULONG SecCsr0;
7136         SHAREDKEY_MODE_STRUC csr1;
7137
7138         DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7139
7140         RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7141         if ((BssIndex%2) == 0)
7142         {
7143                 if (KeyIdx == 0)
7144                         csr1.field.Bss0Key0CipherAlg = 0;
7145                 else if (KeyIdx == 1)
7146                         csr1.field.Bss0Key1CipherAlg = 0;
7147                 else if (KeyIdx == 2)
7148                         csr1.field.Bss0Key2CipherAlg = 0;
7149                 else
7150                         csr1.field.Bss0Key3CipherAlg = 0;
7151         }
7152         else
7153         {
7154                 if (KeyIdx == 0)
7155                         csr1.field.Bss1Key0CipherAlg = 0;
7156                 else if (KeyIdx == 1)
7157                         csr1.field.Bss1Key1CipherAlg = 0;
7158                 else if (KeyIdx == 2)
7159                         csr1.field.Bss1Key2CipherAlg = 0;
7160                 else
7161                         csr1.field.Bss1Key3CipherAlg = 0;
7162         }
7163         DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7164         RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7165         ASSERT(BssIndex < 4);
7166         ASSERT(KeyIdx < 4);
7167
7168 }
7169
7170
7171 VOID AsicUpdateWCIDAttribute(
7172         IN PRTMP_ADAPTER pAd,
7173         IN USHORT               WCID,
7174         IN UCHAR                BssIndex,
7175         IN UCHAR        CipherAlg,
7176         IN BOOLEAN              bUsePairewiseKeyTable)
7177 {
7178         ULONG   WCIDAttri = 0, offset;
7179
7180         //
7181         // Update WCID attribute.
7182         // Only TxKey could update WCID attribute.
7183         //
7184         offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7185         WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7186         RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7187 }
7188
7189 VOID AsicUpdateWCIDIVEIV(
7190         IN PRTMP_ADAPTER pAd,
7191         IN USHORT               WCID,
7192         IN ULONG        uIV,
7193         IN ULONG        uEIV)
7194 {
7195         ULONG   offset;
7196
7197         offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7198
7199         RTMP_IO_WRITE32(pAd, offset, uIV);
7200         RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7201 }
7202
7203 VOID AsicUpdateRxWCIDTable(
7204         IN PRTMP_ADAPTER pAd,
7205         IN USHORT               WCID,
7206         IN PUCHAR        pAddr)
7207 {
7208         ULONG offset;
7209         ULONG Addr;
7210
7211         offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7212         Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7213         RTMP_IO_WRITE32(pAd, offset, Addr);
7214         Addr = pAddr[4] + (pAddr[5] << 8);
7215         RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7216 }
7217
7218
7219 /*
7220     ========================================================================
7221
7222     Routine Description:
7223         Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7224
7225     Arguments:
7226         pAd                     Pointer to our adapter
7227         WCID                    WCID Entry number.
7228         BssIndex                BSSID index, station or none multiple BSSID support
7229                                 this value should be 0.
7230         KeyIdx                  This KeyIdx will set to IV's KeyID if bTxKey enabled
7231         pCipherKey              Pointer to Cipher Key.
7232         bUsePairewiseKeyTable   TRUE means saved the key in SharedKey table,
7233                                 otherwise PairewiseKey table
7234         bTxKey                  This is the transmit key if enabled.
7235
7236     Return Value:
7237         None
7238
7239     Note:
7240         This routine will set the relative key stuff to Asic including WCID attribute,
7241         Cipher Key, Cipher algorithm and IV/EIV.
7242
7243         IV/EIV will be update if this CipherKey is the transmission key because
7244         ASIC will base on IV's KeyID value to select Cipher Key.
7245
7246         If bTxKey sets to FALSE, this is not the TX key, but it could be
7247         RX key
7248
7249         For AP mode bTxKey must be always set to TRUE.
7250     ========================================================================
7251 */
7252 VOID AsicAddKeyEntry(
7253         IN PRTMP_ADAPTER pAd,
7254         IN USHORT               WCID,
7255         IN UCHAR                BssIndex,
7256         IN UCHAR                KeyIdx,
7257         IN PCIPHER_KEY  pCipherKey,
7258         IN BOOLEAN              bUsePairewiseKeyTable,
7259         IN BOOLEAN              bTxKey)
7260 {
7261         ULONG   offset;
7262         UCHAR   IV4 = 0;
7263         PUCHAR          pKey = pCipherKey->Key;
7264         PUCHAR          pTxMic = pCipherKey->TxMic;
7265         PUCHAR          pRxMic = pCipherKey->RxMic;
7266         PUCHAR          pTxtsc = pCipherKey->TxTsc;
7267         UCHAR           CipherAlg = pCipherKey->CipherAlg;
7268         SHAREDKEY_MODE_STRUC csr1;
7269 #ifdef RT2860
7270         UCHAR           i;
7271 #endif
7272
7273         DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7274         //
7275         // 1.) decide key table offset
7276         //
7277         if (bUsePairewiseKeyTable)
7278                 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7279         else
7280                 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7281
7282         //
7283         // 2.) Set Key to Asic
7284         //
7285         //for (i = 0; i < KeyLen; i++)
7286 #ifdef RT2860
7287         for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7288         {
7289                 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7290         }
7291 #endif
7292 #ifdef RT2870
7293         RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7294 #endif
7295         offset += MAX_LEN_OF_PEER_KEY;
7296
7297         //
7298         // 3.) Set MIC key if available
7299         //
7300         if (pTxMic)
7301         {
7302 #ifdef RT2860
7303                 for (i = 0; i < 8; i++)
7304                 {
7305                         RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7306                 }
7307 #endif
7308 #ifdef RT2870
7309                 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7310 #endif
7311         }
7312         offset += LEN_TKIP_TXMICK;
7313
7314         if (pRxMic)
7315         {
7316 #ifdef RT2860
7317                 for (i = 0; i < 8; i++)
7318                 {
7319                         RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7320                 }
7321 #endif
7322 #ifdef RT2870
7323                 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7324 #endif
7325         }
7326
7327
7328         //
7329         // 4.) Modify IV/EIV if needs
7330         //     This will force Asic to use this key ID by setting IV.
7331         //
7332         if (bTxKey)
7333         {
7334 #ifdef RT2860
7335                 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7336                 //
7337                 // Write IV
7338                 //
7339                 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7340                 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7341                 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7342
7343                 IV4 = (KeyIdx << 6);
7344                 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7345                         IV4 |= 0x20;  // turn on extension bit means EIV existence
7346
7347                 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7348
7349                 //
7350                 // Write EIV
7351                 //
7352                 offset += 4;
7353                 for (i = 0; i < 4; i++)
7354                 {
7355                         RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7356                 }
7357
7358 #endif
7359 #ifdef RT2870
7360                 UINT32 tmpVal;
7361
7362                 //
7363                 // Write IV
7364                 //
7365                 IV4 = (KeyIdx << 6);
7366                 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7367                         IV4 |= 0x20;  // turn on extension bit means EIV existence
7368
7369                 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7370                 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7371
7372                 //
7373                 // Write EIV
7374                 //
7375                 offset += 4;
7376                 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7377 #endif // RT2870 //
7378                 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7379         }
7380
7381         if (!bUsePairewiseKeyTable)
7382         {
7383                 //
7384                 // Only update the shared key security mode
7385                 //
7386                 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7387                 if ((BssIndex % 2) == 0)
7388                 {
7389                         if (KeyIdx == 0)
7390                                 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7391                         else if (KeyIdx == 1)
7392                                 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7393                         else if (KeyIdx == 2)
7394                                 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7395                         else
7396                                 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7397                 }
7398                 else
7399                 {
7400                         if (KeyIdx == 0)
7401                                 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7402                         else if (KeyIdx == 1)
7403                                 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7404                         else if (KeyIdx == 2)
7405                                 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7406                         else
7407                                 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7408                 }
7409                 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7410         }
7411
7412         DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7413 }
7414
7415
7416 /*
7417         ========================================================================
7418         Description:
7419                 Add Pair-wise key material into ASIC.
7420                 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7421
7422     Return:
7423         ========================================================================
7424 */
7425 VOID AsicAddPairwiseKeyEntry(
7426         IN PRTMP_ADAPTER pAd,
7427         IN PUCHAR        pAddr,
7428         IN UCHAR                WCID,
7429         IN CIPHER_KEY            *pCipherKey)
7430 {
7431         INT i;
7432         ULONG           offset;
7433         PUCHAR           pKey = pCipherKey->Key;
7434         PUCHAR           pTxMic = pCipherKey->TxMic;
7435         PUCHAR           pRxMic = pCipherKey->RxMic;
7436 #ifdef DBG
7437         UCHAR           CipherAlg = pCipherKey->CipherAlg;
7438 #endif // DBG //
7439
7440         // EKEY
7441         offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7442 #ifdef RT2860
7443         for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7444         {
7445                 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7446         }
7447 #endif
7448 #ifdef RT2870
7449         RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7450 #endif // RT2870 //
7451         for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7452         {
7453                 UINT32 Value;
7454                 RTMP_IO_READ32(pAd, offset + i, &Value);
7455         }
7456
7457         offset += MAX_LEN_OF_PEER_KEY;
7458
7459         //  MIC KEY
7460         if (pTxMic)
7461         {
7462 #ifdef RT2860
7463                 for (i=0; i<8; i++)
7464                 {
7465                         RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7466                 }
7467 #endif
7468 #ifdef RT2870
7469                 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7470 #endif // RT2870 //
7471         }
7472         offset += 8;
7473         if (pRxMic)
7474         {
7475 #ifdef RT2860
7476                 for (i=0; i<8; i++)
7477                 {
7478                         RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7479                 }
7480 #endif
7481 #ifdef RT2870
7482                 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7483 #endif // RT2870 //
7484         }
7485
7486         DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7487         DBGPRINT(RT_DEBUG_TRACE,("      Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7488                 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7489         if (pRxMic)
7490         {
7491                 DBGPRINT(RT_DEBUG_TRACE, ("     Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7492                         pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7493         }
7494         if (pTxMic)
7495         {
7496                 DBGPRINT(RT_DEBUG_TRACE, ("     Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7497                         pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7498         }
7499 }
7500 /*
7501         ========================================================================
7502         Description:
7503                 Remove Pair-wise key material from ASIC.
7504
7505     Return:
7506         ========================================================================
7507 */
7508 VOID AsicRemovePairwiseKeyEntry(
7509         IN PRTMP_ADAPTER pAd,
7510         IN UCHAR                 BssIdx,
7511         IN UCHAR                 Wcid)
7512 {
7513         ULONG           WCIDAttri;
7514         USHORT          offset;
7515
7516         // re-set the entry's WCID attribute as OPEN-NONE.
7517         offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7518         WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7519         RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7520 }
7521
7522 BOOLEAN AsicSendCommandToMcu(
7523         IN PRTMP_ADAPTER pAd,
7524         IN UCHAR                 Command,
7525         IN UCHAR                 Token,
7526         IN UCHAR                 Arg0,
7527         IN UCHAR                 Arg1)
7528 {
7529         HOST_CMD_CSR_STRUC      H2MCmd;
7530         H2M_MAILBOX_STRUC       H2MMailbox;
7531         ULONG                           i = 0;
7532
7533         do
7534         {
7535                 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7536                 if (H2MMailbox.field.Owner == 0)
7537                         break;
7538
7539                 RTMPusecDelay(2);
7540         } while(i++ < 100);
7541
7542         if (i > 100)
7543         {
7544                 {
7545 #ifdef RT2860
7546                         UINT32 Data;
7547
7548                         // Reset DMA
7549                         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7550                         Data |= 0x2;
7551                         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7552
7553                         // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7554                         // Reset DMA/CPU ring index
7555                         RTMPRingCleanUp(pAd, QID_AC_BK);
7556                         RTMPRingCleanUp(pAd, QID_AC_BE);
7557                         RTMPRingCleanUp(pAd, QID_AC_VI);
7558                         RTMPRingCleanUp(pAd, QID_AC_VO);
7559                         RTMPRingCleanUp(pAd, QID_HCCA);
7560                         RTMPRingCleanUp(pAd, QID_MGMT);
7561                         RTMPRingCleanUp(pAd, QID_RX);
7562
7563                         // Clear Reset
7564                         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7565                         Data &= 0xfffffffd;
7566                         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7567 #endif /* RT2860 */
7568                 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7569                 }
7570                 //return FALSE;
7571 #ifdef RT2870
7572                 return FALSE;
7573 #endif
7574         }
7575
7576         H2MMailbox.field.Owner    = 1;     // pass ownership to MCU
7577         H2MMailbox.field.CmdToken = Token;
7578         H2MMailbox.field.HighByte = Arg1;
7579         H2MMailbox.field.LowByte  = Arg0;
7580         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7581
7582         H2MCmd.word                       = 0;
7583         H2MCmd.field.HostCommand  = Command;
7584         RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7585
7586         if (Command != 0x80)
7587         {
7588         }
7589
7590         return TRUE;
7591 }
7592
7593 #ifdef RT2860
7594 BOOLEAN AsicCheckCommanOk(
7595         IN PRTMP_ADAPTER pAd,
7596         IN UCHAR                 Command)
7597 {
7598         UINT32  CmdStatus = 0, CID = 0, i;
7599         UINT32  ThisCIDMask = 0;
7600
7601         i = 0;
7602         do
7603         {
7604                 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7605                 // Find where the command is. Because this is randomly specified by firmware.
7606                 if ((CID & CID0MASK) == Command)
7607                 {
7608                         ThisCIDMask = CID0MASK;
7609                         break;
7610                 }
7611                 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7612                 {
7613                         ThisCIDMask = CID1MASK;
7614                         break;
7615                 }
7616                 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7617                 {
7618                         ThisCIDMask = CID2MASK;
7619                         break;
7620                 }
7621                 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7622                 {
7623                         ThisCIDMask = CID3MASK;
7624                         break;
7625                 }
7626
7627                 RTMPusecDelay(100);
7628                 i++;
7629         }while (i < 200);
7630
7631         // Get CommandStatus Value
7632         RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7633
7634         // This command's status is at the same position as command. So AND command position's bitmask to read status.
7635         if (i < 200)
7636         {
7637                 // If Status is 1, the comamnd is success.
7638                 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7639                         || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7640                 {
7641                         DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7642                         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7643                         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7644                         return TRUE;
7645                 }
7646                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7647         }
7648         else
7649         {
7650                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7651         }
7652         // Clear Command and Status.
7653         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7654         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7655
7656         return FALSE;
7657 }
7658 #endif /* RT8260 */
7659
7660 /*
7661         ========================================================================
7662
7663         Routine Description:
7664                 Verify the support rate for different PHY type
7665
7666         Arguments:
7667                 pAd                             Pointer to our adapter
7668
7669         Return Value:
7670                 None
7671
7672         IRQL = PASSIVE_LEVEL
7673
7674         ========================================================================
7675 */
7676 VOID    RTMPCheckRates(
7677         IN              PRTMP_ADAPTER   pAd,
7678         IN OUT  UCHAR                   SupRate[],
7679         IN OUT  UCHAR                   *SupRateLen)
7680 {
7681         UCHAR   RateIdx, i, j;
7682         UCHAR   NewRate[12], NewRateLen;
7683
7684         NewRateLen = 0;
7685
7686         if (pAd->CommonCfg.PhyMode == PHY_11B)
7687                 RateIdx = 4;
7688         else
7689                 RateIdx = 12;
7690
7691         // Check for support rates exclude basic rate bit
7692         for (i = 0; i < *SupRateLen; i++)
7693                 for (j = 0; j < RateIdx; j++)
7694                         if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7695                                 NewRate[NewRateLen++] = SupRate[i];
7696
7697         *SupRateLen = NewRateLen;
7698         NdisMoveMemory(SupRate, NewRate, NewRateLen);
7699 }
7700
7701 BOOLEAN RTMPCheckChannel(
7702         IN PRTMP_ADAPTER pAd,
7703         IN UCHAR                CentralChannel,
7704         IN UCHAR                Channel)
7705 {
7706         UCHAR           k;
7707         UCHAR           UpperChannel = 0, LowerChannel = 0;
7708         UCHAR           NoEffectChannelinList = 0;
7709
7710         // Find upper and lower channel according to 40MHz current operation.
7711         if (CentralChannel < Channel)
7712         {
7713                 UpperChannel = Channel;
7714                 if (CentralChannel > 2)
7715                         LowerChannel = CentralChannel - 2;
7716                 else
7717                         return FALSE;
7718         }
7719         else if (CentralChannel > Channel)
7720         {
7721                 UpperChannel = CentralChannel + 2;
7722                 LowerChannel = Channel;
7723         }
7724
7725         for (k = 0;k < pAd->ChannelListNum;k++)
7726         {
7727                 if (pAd->ChannelList[k].Channel == UpperChannel)
7728                 {
7729                         NoEffectChannelinList ++;
7730                 }
7731                 if (pAd->ChannelList[k].Channel == LowerChannel)
7732                 {
7733                         NoEffectChannelinList ++;
7734                 }
7735         }
7736
7737         DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7738         if (NoEffectChannelinList == 2)
7739                 return TRUE;
7740         else
7741                 return FALSE;
7742 }
7743
7744 /*
7745         ========================================================================
7746
7747         Routine Description:
7748                 Verify the support rate for HT phy type
7749
7750         Arguments:
7751                 pAd                             Pointer to our adapter
7752
7753         Return Value:
7754                 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
7755
7756         IRQL = PASSIVE_LEVEL
7757
7758         ========================================================================
7759 */
7760 BOOLEAN         RTMPCheckHt(
7761         IN      PRTMP_ADAPTER                   pAd,
7762         IN      UCHAR                                   Wcid,
7763         IN      HT_CAPABILITY_IE                *pHtCapability,
7764         IN      ADD_HT_INFO_IE                  *pAddHtInfo)
7765 {
7766         if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7767                 return FALSE;
7768
7769         // If use AMSDU, set flag.
7770         if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7771                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7772         // Save Peer Capability
7773         if (pHtCapability->HtCapInfo.ShortGIfor20)
7774                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7775         if (pHtCapability->HtCapInfo.ShortGIfor40)
7776                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7777         if (pHtCapability->HtCapInfo.TxSTBC)
7778                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7779         if (pHtCapability->HtCapInfo.RxSTBC)
7780                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7781         if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7782         {
7783                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7784         }
7785
7786         if (Wcid < MAX_LEN_OF_MAC_TABLE)
7787         {
7788                 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7789         }
7790
7791         // Will check ChannelWidth for MCSSet[4] below
7792         pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7793     switch (pAd->CommonCfg.RxStream)
7794         {
7795                 case 1:
7796                         pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7797                         pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7798             pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7799             pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7800                         break;
7801                 case 2:
7802                         pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7803                         pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7804             pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7805             pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7806                         break;
7807                 case 3:
7808                         pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7809                         pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7810             pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7811             pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7812                         break;
7813         }
7814
7815         pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7816
7817     DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7818                 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7819                 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7820
7821         pAd->MlmeAux.HtCapability.HtCapInfo.GF =  pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7822
7823         // Send Assoc Req with my HT capability.
7824         pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =  pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7825         pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =  pAd->CommonCfg.DesiredHtPhy.MimoPs;
7826         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7827         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7828         pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =  (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7829         pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =  (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7830         pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7831     pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7832         pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7833         pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7834         if (pAd->CommonCfg.bRdg)
7835         {
7836                 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7837         pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7838         }
7839
7840     if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7841         pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;  // BW20 can't transmit MCS32
7842
7843         COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7844         return TRUE;
7845 }
7846
7847 /*
7848         ========================================================================
7849
7850         Routine Description:
7851                 Verify the support rate for different PHY type
7852
7853         Arguments:
7854                 pAd                             Pointer to our adapter
7855
7856         Return Value:
7857                 None
7858
7859         IRQL = PASSIVE_LEVEL
7860
7861         ========================================================================
7862 */
7863 VOID RTMPUpdateMlmeRate(
7864         IN PRTMP_ADAPTER        pAd)
7865 {
7866         UCHAR   MinimumRate;
7867         UCHAR   ProperMlmeRate; //= RATE_54;
7868         UCHAR   i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7869         BOOLEAN bMatch = FALSE;
7870
7871         switch (pAd->CommonCfg.PhyMode)
7872         {
7873                 case PHY_11B:
7874                         ProperMlmeRate = RATE_11;
7875                         MinimumRate = RATE_1;
7876                         break;
7877                 case PHY_11BG_MIXED:
7878                 case PHY_11ABGN_MIXED:
7879                 case PHY_11BGN_MIXED:
7880                         if ((pAd->MlmeAux.SupRateLen == 4) &&
7881                                 (pAd->MlmeAux.ExtRateLen == 0))
7882                                 // B only AP
7883                                 ProperMlmeRate = RATE_11;
7884                         else
7885                                 ProperMlmeRate = RATE_24;
7886
7887                         if (pAd->MlmeAux.Channel <= 14)
7888                                 MinimumRate = RATE_1;
7889                         else
7890                                 MinimumRate = RATE_6;
7891                         break;
7892                 case PHY_11A:
7893                 case PHY_11N_2_4G:      // rt2860 need to check mlmerate for 802.11n
7894                 case PHY_11GN_MIXED:
7895                 case PHY_11AGN_MIXED:
7896                 case PHY_11AN_MIXED:
7897                 case PHY_11N_5G:
7898                         ProperMlmeRate = RATE_24;
7899                         MinimumRate = RATE_6;
7900                         break;
7901                 case PHY_11ABG_MIXED:
7902                         ProperMlmeRate = RATE_24;
7903                         if (pAd->MlmeAux.Channel <= 14)
7904                            MinimumRate = RATE_1;
7905                         else
7906                                 MinimumRate = RATE_6;
7907                         break;
7908                 default: // error
7909                         ProperMlmeRate = RATE_1;
7910                         MinimumRate = RATE_1;
7911                         break;
7912         }
7913
7914         for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7915         {
7916                 for (j = 0; j < RateIdx; j++)
7917                 {
7918                         if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7919                         {
7920                                 if (j == ProperMlmeRate)
7921                                 {
7922                                         bMatch = TRUE;
7923                                         break;
7924                                 }
7925                         }
7926                 }
7927
7928                 if (bMatch)
7929                         break;
7930         }
7931
7932         if (bMatch == FALSE)
7933         {
7934                 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7935                 {
7936                         for (j = 0; j < RateIdx; j++)
7937                         {
7938                                 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7939                                 {
7940                                         if (j == ProperMlmeRate)
7941                                         {
7942                                                 bMatch = TRUE;
7943                                                 break;
7944                                         }
7945                                 }
7946                         }
7947
7948                         if (bMatch)
7949                                 break;
7950                 }
7951         }
7952
7953         if (bMatch == FALSE)
7954         {
7955                 ProperMlmeRate = MinimumRate;
7956         }
7957
7958         pAd->CommonCfg.MlmeRate = MinimumRate;
7959         pAd->CommonCfg.RtsRate = ProperMlmeRate;
7960         if (pAd->CommonCfg.MlmeRate >= RATE_6)
7961         {
7962                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7963                 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7964                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7965                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7966         }
7967         else
7968         {
7969                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7970                 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7971                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7972                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7973         }
7974
7975         DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n" , pAd->CommonCfg.MlmeTransmit.word));
7976 }
7977
7978 CHAR RTMPMaxRssi(
7979         IN PRTMP_ADAPTER        pAd,
7980         IN CHAR                         Rssi0,
7981         IN CHAR                         Rssi1,
7982         IN CHAR                         Rssi2)
7983 {
7984         CHAR    larger = -127;
7985
7986         if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7987         {
7988                 larger = Rssi0;
7989         }
7990
7991         if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7992         {
7993                 larger = max(Rssi0, Rssi1);
7994         }
7995
7996         if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7997         {
7998                 larger = max(larger, Rssi2);
7999         }
8000
8001         if (larger == -127)
8002                 larger = 0;
8003
8004         return larger;
8005 }
8006
8007 #ifdef RT30xx
8008 // Antenna divesity use GPIO3 and EESK pin for control
8009 // Antenna and EEPROM access are both using EESK pin,
8010 // Therefor we should avoid accessing EESK at the same time
8011 // Then restore antenna after EEPROM access
8012 VOID AsicSetRxAnt(
8013         IN PRTMP_ADAPTER        pAd,
8014         IN UCHAR                        Ant)
8015 {
8016         UINT32  Value;
8017         UINT32  x;
8018
8019         if ((pAd->EepromAccess)                                                                         ||
8020                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))  ||
8021                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))   ||
8022                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))                  ||
8023                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8024         {
8025                 return;
8026         }
8027
8028         // the antenna selection is through firmware and MAC register(GPIO3)
8029         if (Ant == 0)
8030         {
8031                 // Main antenna
8032                 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8033                 x |= (EESK);
8034                 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8035
8036                 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8037                 Value &= ~(0x0808);
8038                 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8039                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8040         }
8041         else
8042         {
8043                 // Aux antenna
8044                 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8045                 x &= ~(EESK);
8046                 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8047
8048                 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8049                 Value &= ~(0x0808);
8050                 Value |= 0x08;
8051                 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8052                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8053         }
8054 }
8055 #endif /* RT30xx */
8056
8057 /*
8058     ========================================================================
8059     Routine Description:
8060         Periodic evaluate antenna link status
8061
8062     Arguments:
8063         pAd         - Adapter pointer
8064
8065     Return Value:
8066         None
8067
8068     ========================================================================
8069 */
8070 VOID AsicEvaluateRxAnt(
8071         IN PRTMP_ADAPTER        pAd)
8072 {
8073         UCHAR   BBPR3 = 0;
8074
8075         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8076                                 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8077                                 fRTMP_ADAPTER_RADIO_OFF |
8078                                 fRTMP_ADAPTER_NIC_NOT_EXIST |
8079                                 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
8080                                 || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8081 #ifdef RT30xx
8082                                 || (pAd->EepromAccess)
8083 #endif
8084                                 )
8085                         return;
8086
8087 #ifdef RT30xx
8088         // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8089         // one is antenna diversity:there is only one antenna can rx and tx
8090         // the other is failed antenna remove:two physical antenna can rx and tx
8091         if (pAd->NicConfig2.field.AntDiversity)
8092         {
8093                 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8094                         pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8095
8096                 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8097
8098                 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8099                 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8100                 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8101
8102                 // a one-shot timer to end the evalution
8103                 // dynamic adjust antenna evaluation period according to the traffic
8104                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8105                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8106                 else
8107                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8108         }
8109         else
8110 #endif
8111         {
8112                 if (pAd->StaCfg.Psm == PWR_SAVE)
8113                         return;
8114
8115                 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8116                 BBPR3 &= (~0x18);
8117                 if(pAd->Antenna.field.RxPath == 3)
8118                 {
8119                         BBPR3 |= (0x10);
8120                 }
8121                 else if(pAd->Antenna.field.RxPath == 2)
8122                 {
8123                         BBPR3 |= (0x8);
8124                 }
8125                 else if(pAd->Antenna.field.RxPath == 1)
8126                 {
8127                         BBPR3 |= (0x0);
8128                 }
8129                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8130
8131 #ifdef RT2860
8132                 pAd->StaCfg.BBPR3 = BBPR3;
8133 #endif
8134         }
8135
8136         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8137                 )
8138         {
8139                 ULONG   TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8140                                                                 pAd->RalinkCounters.OneSecTxRetryOkCount +
8141                                                                 pAd->RalinkCounters.OneSecTxFailCount;
8142
8143                         // dynamic adjust antenna evaluation period according to the traffic
8144                 if (TxTotalCnt > 50)
8145                 {
8146                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8147                         pAd->Mlme.bLowThroughput = FALSE;
8148                 }
8149                 else
8150                 {
8151                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8152                         pAd->Mlme.bLowThroughput = TRUE;
8153                 }
8154         }
8155 }
8156
8157 /*
8158     ========================================================================
8159     Routine Description:
8160         After evaluation, check antenna link status
8161
8162     Arguments:
8163         pAd         - Adapter pointer
8164
8165     Return Value:
8166         None
8167
8168     ========================================================================
8169 */
8170 VOID AsicRxAntEvalTimeout(
8171         IN PVOID SystemSpecific1,
8172         IN PVOID FunctionContext,
8173         IN PVOID SystemSpecific2,
8174         IN PVOID SystemSpecific3)
8175 {
8176         RTMP_ADAPTER    *pAd = (RTMP_ADAPTER *)FunctionContext;
8177         UCHAR                   BBPR3 = 0;
8178         CHAR                    larger = -127, rssi0, rssi1, rssi2;
8179
8180         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8181                                                         fRTMP_ADAPTER_HALT_IN_PROGRESS  |
8182                                                         fRTMP_ADAPTER_RADIO_OFF                 |
8183                                                         fRTMP_ADAPTER_NIC_NOT_EXIST)
8184                                                         || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8185 #ifdef RT30xx
8186                                                         || (pAd->EepromAccess)
8187 #endif // RT30xx //
8188                                                         )
8189                 return;
8190
8191         {
8192 #ifdef RT30xx
8193                 if (pAd->NicConfig2.field.AntDiversity)
8194                 {
8195                         if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8196                         {
8197                                 UCHAR                   temp;
8198
8199                                 //
8200                                 // select PrimaryRxAntPair
8201                                 //    Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8202                                 //    Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8203                                 //
8204                                 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8205                                 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8206                                 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8207
8208                                 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8209                                 pAd->RxAnt.EvaluateStableCnt = 0;
8210                         }
8211                         else
8212                         {
8213                                 // if the evaluated antenna is not better than original, switch back to original antenna
8214                                 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8215                                 pAd->RxAnt.EvaluateStableCnt ++;
8216                         }
8217
8218                         pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8219
8220                         DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8221                                         pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8222                 }
8223                 else
8224 #endif
8225                 {
8226                         if (pAd->StaCfg.Psm == PWR_SAVE)
8227                                 return;
8228
8229                         // if the traffic is low, use average rssi as the criteria
8230                         if (pAd->Mlme.bLowThroughput == TRUE)
8231                         {
8232                                 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8233                                 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8234                                 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8235                         }
8236                         else
8237                         {
8238                                 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8239                                 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8240                                 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8241                         }
8242
8243                         if(pAd->Antenna.field.RxPath == 3)
8244                         {
8245                                 larger = max(rssi0, rssi1);
8246
8247                                 if (larger > (rssi2 + 20))
8248                                         pAd->Mlme.RealRxPath = 2;
8249                                 else
8250                                         pAd->Mlme.RealRxPath = 3;
8251                         }
8252                         else if(pAd->Antenna.field.RxPath == 2)
8253                         {
8254                                 if (rssi0 > (rssi1 + 20))
8255                                         pAd->Mlme.RealRxPath = 1;
8256                                 else
8257                                         pAd->Mlme.RealRxPath = 2;
8258                         }
8259
8260                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8261                         BBPR3 &= (~0x18);
8262                         if(pAd->Mlme.RealRxPath == 3)
8263                         {
8264                                 BBPR3 |= (0x10);
8265                         }
8266                         else if(pAd->Mlme.RealRxPath == 2)
8267                         {
8268                                 BBPR3 |= (0x8);
8269                         }
8270                         else if(pAd->Mlme.RealRxPath == 1)
8271                         {
8272                                 BBPR3 |= (0x0);
8273                         }
8274                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8275 #ifdef RT2860
8276                         pAd->StaCfg.BBPR3 = BBPR3;
8277 #endif
8278                 }
8279         }
8280 }
8281
8282 VOID APSDPeriodicExec(
8283         IN PVOID SystemSpecific1,
8284         IN PVOID FunctionContext,
8285         IN PVOID SystemSpecific2,
8286         IN PVOID SystemSpecific3)
8287 {
8288         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8289
8290         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8291                 return;
8292
8293         pAd->CommonCfg.TriggerTimerCount++;
8294
8295 }
8296
8297 /*
8298     ========================================================================
8299     Routine Description:
8300         Set/reset MAC registers according to bPiggyBack parameter
8301
8302     Arguments:
8303         pAd         - Adapter pointer
8304         bPiggyBack  - Enable / Disable Piggy-Back
8305
8306     Return Value:
8307         None
8308
8309     ========================================================================
8310 */
8311 VOID RTMPSetPiggyBack(
8312     IN PRTMP_ADAPTER    pAd,
8313     IN BOOLEAN          bPiggyBack)
8314 {
8315         TX_LINK_CFG_STRUC  TxLinkCfg;
8316
8317         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8318
8319         TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8320         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8321 }
8322
8323 /*
8324     ========================================================================
8325     Routine Description:
8326         check if this entry need to switch rate automatically
8327
8328     Arguments:
8329         pAd
8330         pEntry
8331
8332     Return Value:
8333         TURE
8334         FALSE
8335
8336     ========================================================================
8337 */
8338 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8339         IN PRTMP_ADAPTER    pAd,
8340         IN PMAC_TABLE_ENTRY     pEntry)
8341 {
8342         BOOLEAN         result = TRUE;
8343
8344         {
8345                 // only associated STA counts
8346                 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8347                 {
8348                         result = pAd->StaCfg.bAutoTxRateSwitch;
8349                 }
8350                 else
8351                         result = FALSE;
8352         }
8353
8354         return result;
8355 }
8356
8357
8358 BOOLEAN RTMPAutoRateSwitchCheck(
8359         IN PRTMP_ADAPTER    pAd)
8360 {
8361         if (pAd->StaCfg.bAutoTxRateSwitch)
8362                 return TRUE;
8363
8364         return FALSE;
8365 }
8366
8367
8368 /*
8369     ========================================================================
8370     Routine Description:
8371         check if this entry need to fix tx legacy rate
8372
8373     Arguments:
8374         pAd
8375         pEntry
8376
8377     Return Value:
8378         TURE
8379         FALSE
8380
8381     ========================================================================
8382 */
8383 UCHAR RTMPStaFixedTxMode(
8384         IN PRTMP_ADAPTER    pAd,
8385         IN PMAC_TABLE_ENTRY     pEntry)
8386 {
8387         UCHAR   tx_mode = FIXED_TXMODE_HT;
8388
8389         tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8390
8391         return tx_mode;
8392 }
8393
8394 /*
8395     ========================================================================
8396     Routine Description:
8397         Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8398
8399     Arguments:
8400         pAd
8401         pEntry
8402
8403     Return Value:
8404         TURE
8405         FALSE
8406
8407     ========================================================================
8408 */
8409 VOID RTMPUpdateLegacyTxSetting(
8410                 UCHAR                           fixed_tx_mode,
8411                 PMAC_TABLE_ENTRY        pEntry)
8412 {
8413         HTTRANSMIT_SETTING TransmitSetting;
8414
8415         if (fixed_tx_mode == FIXED_TXMODE_HT)
8416                 return;
8417
8418         TransmitSetting.word = 0;
8419
8420         TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8421         TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8422
8423         if (fixed_tx_mode == FIXED_TXMODE_CCK)
8424         {
8425                 TransmitSetting.field.MODE = MODE_CCK;
8426                 // CCK mode allow MCS 0~3
8427                 if (TransmitSetting.field.MCS > MCS_3)
8428                         TransmitSetting.field.MCS = MCS_3;
8429         }
8430         else
8431         {
8432                 TransmitSetting.field.MODE = MODE_OFDM;
8433                 // OFDM mode allow MCS 0~7
8434                 if (TransmitSetting.field.MCS > MCS_7)
8435                         TransmitSetting.field.MCS = MCS_7;
8436         }
8437
8438         if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8439         {
8440                 pEntry->HTPhyMode.word = TransmitSetting.word;
8441                 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8442                                 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8443         }
8444 }
8445
8446 /*
8447         ==========================================================================
8448         Description:
8449                 dynamic tune BBP R66 to find a balance between sensibility and
8450                 noise isolation
8451
8452         IRQL = DISPATCH_LEVEL
8453
8454         ==========================================================================
8455  */
8456 VOID AsicStaBbpTuning(
8457         IN PRTMP_ADAPTER pAd)
8458 {
8459         UCHAR   OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8460         CHAR    Rssi;
8461
8462         // 2860C did not support Fase CCA, therefore can't tune
8463         if (pAd->MACVersion == 0x28600100)
8464                 return;
8465
8466         //
8467         // work as a STA
8468         //
8469         if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)  // no R66 tuning when SCANNING
8470                 return;
8471
8472         if ((pAd->OpMode == OPMODE_STA)
8473                 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8474                         )
8475                 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8476 #ifdef RT2860
8477                 && (pAd->bPCIclkOff == FALSE))
8478 #endif
8479 #ifdef RT2870
8480                 )
8481 #endif
8482         {
8483                 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8484                 R66 = OrigR66Value;
8485
8486                 if (pAd->Antenna.field.RxPath > 1)
8487                         Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8488                 else
8489                         Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8490
8491                 if (pAd->LatchRfRegs.Channel <= 14)
8492                 {       //BG band
8493 #ifdef RT2870
8494                         // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8495                         // Otherwise, it will have some throughput side effect when low RSSI
8496 #ifndef RT30xx
8497                         if (IS_RT3070(pAd))
8498 #endif
8499 #ifdef RT30xx
8500                         if (IS_RT30xx(pAd))
8501 #endif
8502                         {
8503                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8504                                 {
8505                                         R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8506                                         if (OrigR66Value != R66)
8507                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8508                                 }
8509                                 else
8510                                 {
8511                                         R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8512                                         if (OrigR66Value != R66)
8513                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8514                                 }
8515                         }
8516                         else
8517 #endif // RT2870 //
8518                         {
8519                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8520                                 {
8521                                         R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8522                                         if (OrigR66Value != R66)
8523                                         {
8524                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8525                                         }
8526                                 }
8527                                 else
8528                                 {
8529                                         R66 = 0x2E + GET_LNA_GAIN(pAd);
8530                                         if (OrigR66Value != R66)
8531                                         {
8532                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8533                                         }
8534                                 }
8535                         }
8536                 }
8537                 else
8538                 {       //A band
8539                         if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8540                         {
8541                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8542                                 {
8543                                         R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8544                                         if (OrigR66Value != R66)
8545                                         {
8546                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8547                                         }
8548                                 }
8549                                 else
8550                                 {
8551                                         R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8552                                         if (OrigR66Value != R66)
8553                                         {
8554                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8555                                         }
8556                                 }
8557                         }
8558                         else
8559                         {
8560                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8561                                 {
8562                                         R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8563                                         if (OrigR66Value != R66)
8564                                         {
8565                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8566                                         }
8567                                 }
8568                                 else
8569                                 {
8570                                         R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8571                                         if (OrigR66Value != R66)
8572                                         {
8573                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8574                                         }
8575                                 }
8576                         }
8577                 }
8578
8579
8580         }
8581 }
8582
8583 #ifdef RT2860
8584 VOID AsicResetFromDMABusy(
8585         IN PRTMP_ADAPTER pAd)
8586 {
8587         UINT32          Data;
8588         BOOLEAN         bCtrl = FALSE;
8589
8590         DBGPRINT(RT_DEBUG_TRACE, ("--->  AsicResetFromDMABusy  !!!!!!!!!!!!!!!!!!!!!!! \n"));
8591
8592         // Be sure restore link control value so we can write register.
8593         RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8594         if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8595         {
8596                 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8597                 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8598                 RTMPusecDelay(6000);
8599                 pAd->bPCIclkOff = FALSE;
8600                 bCtrl = TRUE;
8601         }
8602         // Reset DMA
8603         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8604         Data |= 0x2;
8605         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8606
8607         // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8608         // Reset DMA/CPU ring index
8609         RTMPRingCleanUp(pAd, QID_AC_BK);
8610         RTMPRingCleanUp(pAd, QID_AC_BE);
8611         RTMPRingCleanUp(pAd, QID_AC_VI);
8612         RTMPRingCleanUp(pAd, QID_AC_VO);
8613         RTMPRingCleanUp(pAd, QID_HCCA);
8614         RTMPRingCleanUp(pAd, QID_MGMT);
8615         RTMPRingCleanUp(pAd, QID_RX);
8616
8617         // Clear Reset
8618         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8619         Data &= 0xfffffffd;
8620         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8621
8622         // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8623         if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8624                 RTMPPCIeLinkCtrlSetting(pAd, 3);
8625
8626         RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8627         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8628         DBGPRINT(RT_DEBUG_TRACE, ("<---  AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!!  \n"));
8629 }
8630
8631 VOID AsicResetBBP(
8632         IN PRTMP_ADAPTER pAd)
8633 {
8634         DBGPRINT(RT_DEBUG_TRACE, ("--->  Asic HardReset BBP  !!!!!!!!!!!!!!!!!!!!!!! \n"));
8635
8636         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8637         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8638         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8639
8640         // After hard-reset BBP, initialize all BBP values.
8641         NICRestoreBBPValue(pAd);
8642         DBGPRINT(RT_DEBUG_TRACE, ("<---  Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!!  \n"));
8643 }
8644
8645 VOID AsicResetMAC(
8646         IN PRTMP_ADAPTER pAd)
8647 {
8648         ULONG           Data;
8649
8650         DBGPRINT(RT_DEBUG_TRACE, ("--->  AsicResetMAC   !!!! \n"));
8651         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8652         Data |= 0x4;
8653         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8654         Data &= 0xfffffffb;
8655         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8656
8657         DBGPRINT(RT_DEBUG_TRACE, ("<---  AsicResetMAC   !!!! \n"));
8658 }
8659
8660 VOID AsicResetPBF(
8661         IN PRTMP_ADAPTER pAd)
8662 {
8663         ULONG           Value1, Value2;
8664         ULONG           Data;
8665
8666         RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8667         RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8668
8669         Value2 &= 0xff;
8670         // sum should be equals to 0xff, which is the total buffer size.
8671         if ((Value1 + Value2) < 0xff)
8672         {
8673                 DBGPRINT(RT_DEBUG_TRACE, ("--->  Asic HardReset PBF !!!! \n"));
8674                 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8675                 Data |= 0x8;
8676                 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8677                 Data &= 0xfffffff7;
8678                 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8679
8680                 DBGPRINT(RT_DEBUG_TRACE, ("<---  Asic HardReset PBF !!!! \n"));
8681         }
8682 }
8683 #endif /* RT2860 */
8684
8685 VOID RTMPSetAGCInitValue(
8686         IN PRTMP_ADAPTER        pAd,
8687         IN UCHAR                        BandWidth)
8688 {
8689         UCHAR   R66 = 0x30;
8690
8691         if (pAd->LatchRfRegs.Channel <= 14)
8692         {       // BG band
8693                 R66 = 0x2E + GET_LNA_GAIN(pAd);
8694                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8695         }
8696         else
8697         {       //A band
8698                 if (BandWidth == BW_20)
8699                 {
8700                         R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8701                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8702                 }
8703                 else
8704                 {
8705                         R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8706                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8707                 }
8708         }
8709
8710 }
8711
8712 VOID AsicTurnOffRFClk(
8713         IN PRTMP_ADAPTER pAd,
8714         IN      UCHAR           Channel)
8715 {
8716
8717         // RF R2 bit 18 = 0
8718         UINT32                  R1 = 0, R2 = 0, R3 = 0;
8719         UCHAR                   index;
8720         RTMP_RF_REGS    *RFRegTable;
8721
8722         // The RF programming sequence is difference between 3xxx and 2xxx
8723         if (IS_RT3090(pAd))
8724         {
8725                 RT30xxLoadRFSleepModeSetup(pAd);  // add by johnli,  RF power sequence setup, load RF sleep-mode setup
8726                 return;
8727         }
8728
8729         RFRegTable = RF2850RegTable;
8730
8731         switch (pAd->RfIcType)
8732         {
8733                 case RFIC_2820:
8734                 case RFIC_2850:
8735                 case RFIC_2720:
8736                 case RFIC_2750:
8737
8738                         for (index = 0; index < NUM_OF_2850_CHNL; index++)
8739                         {
8740                                 if (Channel == RFRegTable[index].Channel)
8741                                 {
8742                                         R1 = RFRegTable[index].R1 & 0xffffdfff;
8743                                         R2 = RFRegTable[index].R2 & 0xfffbffff;
8744                                         R3 = RFRegTable[index].R3 & 0xfff3ffff;
8745
8746                                         RTMP_RF_IO_WRITE32(pAd, R1);
8747                                         RTMP_RF_IO_WRITE32(pAd, R2);
8748
8749                                         // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8750                                         // Set RF R2 bit18=0, R3 bit[18:19]=0
8751                                         //if (pAd->StaCfg.bRadio == FALSE)
8752                                         if (1)
8753                                         {
8754                                                 RTMP_RF_IO_WRITE32(pAd, R3);
8755
8756                                                 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x,  R3 = 0x%08x \n",
8757                                                         Channel, pAd->RfIcType, R2, R3));
8758                                         }
8759                                         else
8760                                                 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8761                                                         Channel, pAd->RfIcType, R2));
8762                                         break;
8763                                 }
8764                         }
8765                         break;
8766
8767                 default:
8768                         break;
8769         }
8770 }
8771
8772
8773 VOID AsicTurnOnRFClk(
8774         IN PRTMP_ADAPTER pAd,
8775         IN      UCHAR                   Channel)
8776 {
8777
8778         // RF R2 bit 18 = 0
8779         UINT32                  R1 = 0, R2 = 0, R3 = 0;
8780         UCHAR                   index;
8781         RTMP_RF_REGS    *RFRegTable;
8782
8783         // The RF programming sequence is difference between 3xxx and 2xxx
8784         if (IS_RT3090(pAd))
8785                 return;
8786
8787         RFRegTable = RF2850RegTable;
8788
8789         switch (pAd->RfIcType)
8790         {
8791                 case RFIC_2820:
8792                 case RFIC_2850:
8793                 case RFIC_2720:
8794                 case RFIC_2750:
8795
8796                         for (index = 0; index < NUM_OF_2850_CHNL; index++)
8797                         {
8798                                 if (Channel == RFRegTable[index].Channel)
8799                                 {
8800                                         R3 = pAd->LatchRfRegs.R3;
8801                                         R3 &= 0xfff3ffff;
8802                                         R3 |= 0x00080000;
8803                                         RTMP_RF_IO_WRITE32(pAd, R3);
8804
8805                                         R1 = RFRegTable[index].R1;
8806                                         RTMP_RF_IO_WRITE32(pAd, R1);
8807
8808                                         R2 = RFRegTable[index].R2;
8809                                         if (pAd->Antenna.field.TxPath == 1)
8810                                         {
8811                                                 R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
8812                                         }
8813
8814                                         if (pAd->Antenna.field.RxPath == 2)
8815                                         {
8816                                                 R2 |= 0x40;     // write 1 to off Rxpath.
8817                                         }
8818                                         else if (pAd->Antenna.field.RxPath == 1)
8819                                         {
8820                                                 R2 |= 0x20040;  // write 1 to off RxPath
8821                                         }
8822                                         RTMP_RF_IO_WRITE32(pAd, R2);
8823
8824                                         break;
8825                                 }
8826                         }
8827                         break;
8828
8829                 default:
8830                         break;
8831         }
8832
8833         DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8834                 Channel,
8835                 pAd->RfIcType,
8836                 R2));
8837 }
8838