Staging: rt28x0: MlmeSelectTxRateTable() fix
[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 #ifdef RT30xx
2770                 // add by johnli, use Rx OK data count per second to calculate throughput
2771                 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2772                 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2773                 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2774                                 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2775                         ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2776                         (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2777 #endif
2778                 {
2779                                 // Get this time
2780                         NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2781                         pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2782                         MlmeSetPsmBit(pAd, PWR_SAVE);
2783                         if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2784                         {
2785                                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2786                         }
2787                         else
2788                         {
2789                                 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2790                         }
2791                 }
2792         }
2793 }
2794
2795 // IRQL = PASSIVE_LEVEL
2796 // IRQL = DISPATCH_LEVEL
2797 VOID MlmeSetPsmBit(
2798         IN PRTMP_ADAPTER pAd,
2799         IN USHORT psm)
2800 {
2801         AUTO_RSP_CFG_STRUC csr4;
2802
2803         pAd->StaCfg.Psm = psm;
2804         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2805         csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2806         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2807
2808         DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2809 }
2810
2811 // IRQL = DISPATCH_LEVEL
2812 VOID MlmeSetTxPreamble(
2813         IN PRTMP_ADAPTER pAd,
2814         IN USHORT TxPreamble)
2815 {
2816         AUTO_RSP_CFG_STRUC csr4;
2817
2818         //
2819         // Always use Long preamble before verifiation short preamble functionality works well.
2820         // Todo: remove the following line if short preamble functionality works
2821         //
2822         //TxPreamble = Rt802_11PreambleLong;
2823
2824         RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2825         if (TxPreamble == Rt802_11PreambleLong)
2826         {
2827                 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2828                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2829                 csr4.field.AutoResponderPreamble = 0;
2830         }
2831         else
2832         {
2833                 // NOTE: 1Mbps should always use long preamble
2834                 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2835                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2836                 csr4.field.AutoResponderPreamble = 1;
2837         }
2838
2839         RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2840 }
2841
2842 /*
2843     ==========================================================================
2844     Description:
2845         Update basic rate bitmap
2846     ==========================================================================
2847  */
2848
2849 VOID UpdateBasicRateBitmap(
2850     IN  PRTMP_ADAPTER   pAdapter)
2851 {
2852     INT  i, j;
2853                   /* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
2854     UCHAR rate[] = { 2, 4,  11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2855     UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2856     UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2857     ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2858
2859
2860     /* if A mode, always use fix BasicRateBitMap */
2861     //if (pAdapter->CommonCfg.Channel == PHY_11A)
2862         if (pAdapter->CommonCfg.Channel > 14)
2863         pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2864     /* End of if */
2865
2866     if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2867     {
2868         /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2869         return;
2870     } /* End of if */
2871
2872     for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2873     {
2874         sup_p[i] &= 0x7f;
2875         ext_p[i] &= 0x7f;
2876     } /* End of for */
2877
2878     for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2879     {
2880         if (bitmap & (1 << i))
2881         {
2882             for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2883             {
2884                 if (sup_p[j] == rate[i])
2885                     sup_p[j] |= 0x80;
2886                 /* End of if */
2887             } /* End of for */
2888
2889             for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2890             {
2891                 if (ext_p[j] == rate[i])
2892                     ext_p[j] |= 0x80;
2893                 /* End of if */
2894             } /* End of for */
2895         } /* End of if */
2896     } /* End of for */
2897 } /* End of UpdateBasicRateBitmap */
2898
2899 // IRQL = PASSIVE_LEVEL
2900 // IRQL = DISPATCH_LEVEL
2901 // bLinkUp is to identify the inital link speed.
2902 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2903 VOID MlmeUpdateTxRates(
2904         IN PRTMP_ADAPTER                pAd,
2905         IN      BOOLEAN                         bLinkUp,
2906         IN      UCHAR                           apidx)
2907 {
2908         int i, num;
2909         UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2910         UCHAR MinSupport = RATE_54;
2911         ULONG BasicRateBitmap = 0;
2912         UCHAR CurrBasicRate = RATE_1;
2913         UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2914         PHTTRANSMIT_SETTING             pHtPhy = NULL;
2915         PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
2916         PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
2917         BOOLEAN                                 *auto_rate_cur_p;
2918         UCHAR                                   HtMcs = MCS_AUTO;
2919
2920         // find max desired rate
2921         UpdateBasicRateBitmap(pAd);
2922
2923         num = 0;
2924         auto_rate_cur_p = NULL;
2925         for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2926         {
2927                 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2928                 {
2929                         case 2:  Rate = RATE_1;   num++;   break;
2930                         case 4:  Rate = RATE_2;   num++;   break;
2931                         case 11: Rate = RATE_5_5; num++;   break;
2932                         case 22: Rate = RATE_11;  num++;   break;
2933                         case 12: Rate = RATE_6;   num++;   break;
2934                         case 18: Rate = RATE_9;   num++;   break;
2935                         case 24: Rate = RATE_12;  num++;   break;
2936                         case 36: Rate = RATE_18;  num++;   break;
2937                         case 48: Rate = RATE_24;  num++;   break;
2938                         case 72: Rate = RATE_36;  num++;   break;
2939                         case 96: Rate = RATE_48;  num++;   break;
2940                         case 108: Rate = RATE_54; num++;   break;
2941                         //default: Rate = RATE_1;   break;
2942                 }
2943                 if (MaxDesire < Rate)  MaxDesire = Rate;
2944         }
2945
2946 //===========================================================================
2947 //===========================================================================
2948         {
2949                 pHtPhy          = &pAd->StaCfg.HTPhyMode;
2950                 pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
2951                 pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
2952
2953                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2954                 HtMcs           = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2955
2956                 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2957                         (pAd->CommonCfg.PhyMode == PHY_11B) &&
2958                         (MaxDesire > RATE_11))
2959                 {
2960                         MaxDesire = RATE_11;
2961                 }
2962         }
2963
2964         pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2965         pMinHtPhy->word = 0;
2966         pMaxHtPhy->word = 0;
2967         pHtPhy->word = 0;
2968
2969         // Auto rate switching is enabled only if more than one DESIRED RATES are
2970         // specified; otherwise disabled
2971         if (num <= 1)
2972         {
2973                 *auto_rate_cur_p = FALSE;
2974         }
2975         else
2976         {
2977                 *auto_rate_cur_p = TRUE;
2978         }
2979
2980 #if 1
2981         if (HtMcs != MCS_AUTO)
2982         {
2983                 *auto_rate_cur_p = FALSE;
2984         }
2985         else
2986         {
2987                 *auto_rate_cur_p = TRUE;
2988         }
2989 #endif
2990
2991         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2992         {
2993                 pSupRate = &pAd->StaActive.SupRate[0];
2994                 pExtRate = &pAd->StaActive.ExtRate[0];
2995                 SupRateLen = pAd->StaActive.SupRateLen;
2996                 ExtRateLen = pAd->StaActive.ExtRateLen;
2997         }
2998         else
2999         {
3000                 pSupRate = &pAd->CommonCfg.SupRate[0];
3001                 pExtRate = &pAd->CommonCfg.ExtRate[0];
3002                 SupRateLen = pAd->CommonCfg.SupRateLen;
3003                 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3004         }
3005
3006         // find max supported rate
3007         for (i=0; i<SupRateLen; i++)
3008         {
3009                 switch (pSupRate[i] & 0x7f)
3010                 {
3011                         case 2:   Rate = RATE_1;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
3012                         case 4:   Rate = RATE_2;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
3013                         case 11:  Rate = RATE_5_5;      if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
3014                         case 22:  Rate = RATE_11;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
3015                         case 12:  Rate = RATE_6;        /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
3016                         case 18:  Rate = RATE_9;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
3017                         case 24:  Rate = RATE_12;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
3018                         case 36:  Rate = RATE_18;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
3019                         case 48:  Rate = RATE_24;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
3020                         case 72:  Rate = RATE_36;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
3021                         case 96:  Rate = RATE_48;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
3022                         case 108: Rate = RATE_54;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
3023                         default:  Rate = RATE_1;        break;
3024                 }
3025                 if (MaxSupport < Rate)  MaxSupport = Rate;
3026
3027                 if (MinSupport > Rate) MinSupport = Rate;
3028         }
3029
3030         for (i=0; i<ExtRateLen; i++)
3031         {
3032                 switch (pExtRate[i] & 0x7f)
3033                 {
3034                         case 2:   Rate = RATE_1;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
3035                         case 4:   Rate = RATE_2;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
3036                         case 11:  Rate = RATE_5_5;      if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
3037                         case 22:  Rate = RATE_11;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
3038                         case 12:  Rate = RATE_6;        /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
3039                         case 18:  Rate = RATE_9;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
3040                         case 24:  Rate = RATE_12;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
3041                         case 36:  Rate = RATE_18;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
3042                         case 48:  Rate = RATE_24;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
3043                         case 72:  Rate = RATE_36;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
3044                         case 96:  Rate = RATE_48;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
3045                         case 108: Rate = RATE_54;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
3046                         default:  Rate = RATE_1;        break;
3047                 }
3048                 if (MaxSupport < Rate)  MaxSupport = Rate;
3049
3050                 if (MinSupport > Rate) MinSupport = Rate;
3051         }
3052
3053         RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3054
3055         // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3056         // the DURATION field of outgoing uniicast DATA/MGMT frame
3057         for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3058         {
3059                 if (BasicRateBitmap & (0x01 << i))
3060                         CurrBasicRate = (UCHAR)i;
3061                 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3062         }
3063
3064         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3065         // max tx rate = min {max desire rate, max supported rate}
3066         if (MaxSupport < MaxDesire)
3067                 pAd->CommonCfg.MaxTxRate = MaxSupport;
3068         else
3069                 pAd->CommonCfg.MaxTxRate = MaxDesire;
3070
3071         pAd->CommonCfg.MinTxRate = MinSupport;
3072         if (*auto_rate_cur_p)
3073         {
3074                 short dbm = 0;
3075
3076                 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3077
3078                 if (bLinkUp == TRUE)
3079                         pAd->CommonCfg.TxRate = RATE_24;
3080                 else
3081                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3082
3083                 if (dbm < -75)
3084                         pAd->CommonCfg.TxRate = RATE_11;
3085                 else if (dbm < -70)
3086                         pAd->CommonCfg.TxRate = RATE_24;
3087
3088                 // should never exceed MaxTxRate (consider 11B-only mode)
3089                 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3090                         pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3091
3092                 pAd->CommonCfg.TxRateIndex = 0;
3093         }
3094         else
3095         {
3096                 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3097                 pHtPhy->field.MCS       = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3098                 pHtPhy->field.MODE      = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3099
3100                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC    = pHtPhy->field.STBC;
3101                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3102                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS             = pHtPhy->field.MCS;
3103                 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE    = pHtPhy->field.MODE;
3104         }
3105
3106         if (pAd->CommonCfg.TxRate <= RATE_11)
3107         {
3108                 pMaxHtPhy->field.MODE = MODE_CCK;
3109                 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3110                 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3111         }
3112         else
3113         {
3114                 pMaxHtPhy->field.MODE = MODE_OFDM;
3115                 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3116                 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3117                         {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3118                 else
3119                         {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3120         }
3121
3122         pHtPhy->word = (pMaxHtPhy->word);
3123         if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3124         {
3125                         pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3126                         pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3127                         pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3128         }
3129         else
3130         {
3131                 switch (pAd->CommonCfg.PhyMode)
3132                 {
3133                         case PHY_11BG_MIXED:
3134                         case PHY_11B:
3135                         case PHY_11BGN_MIXED:
3136                                 pAd->CommonCfg.MlmeRate = RATE_1;
3137                                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3138                                 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3139                                 pAd->CommonCfg.RtsRate = RATE_11;
3140                                 break;
3141                         case PHY_11G:
3142                         case PHY_11A:
3143                         case PHY_11AGN_MIXED:
3144                         case PHY_11GN_MIXED:
3145                         case PHY_11N_2_4G:
3146                         case PHY_11AN_MIXED:
3147                         case PHY_11N_5G:
3148                                 pAd->CommonCfg.MlmeRate = RATE_6;
3149                                 pAd->CommonCfg.RtsRate = RATE_6;
3150                                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3151                                 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3152                                 break;
3153                         case PHY_11ABG_MIXED:
3154                         case PHY_11ABGN_MIXED:
3155                                 if (pAd->CommonCfg.Channel <= 14)
3156                                 {
3157                                         pAd->CommonCfg.MlmeRate = RATE_1;
3158                                         pAd->CommonCfg.RtsRate = RATE_1;
3159                                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3160                                         pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3161                                 }
3162                                 else
3163                                 {
3164                                         pAd->CommonCfg.MlmeRate = RATE_6;
3165                                         pAd->CommonCfg.RtsRate = RATE_6;
3166                                         pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3167                                         pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3168                                 }
3169                                 break;
3170                         default: // error
3171                                 pAd->CommonCfg.MlmeRate = RATE_6;
3172                                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3173                                 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3174                                 pAd->CommonCfg.RtsRate = RATE_1;
3175                                 break;
3176                 }
3177                 //
3178                 // Keep Basic Mlme Rate.
3179                 //
3180                 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3181                 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3182                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3183                 else
3184                         pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3185                 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3186         }
3187
3188         DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3189                          RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3190                          /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3191         DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3192                          RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3193         DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3194                          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 ));
3195 }
3196
3197 /*
3198         ==========================================================================
3199         Description:
3200                 This function update HT Rate setting.
3201                 Input Wcid value is valid for 2 case :
3202                 1. it's used for Station in infra mode that copy AP rate to Mactable.
3203                 2. OR Station   in adhoc mode to copy peer's HT rate to Mactable.
3204
3205         IRQL = DISPATCH_LEVEL
3206
3207         ==========================================================================
3208  */
3209 VOID MlmeUpdateHtTxRates(
3210         IN PRTMP_ADAPTER                pAd,
3211         IN      UCHAR                           apidx)
3212 {
3213         UCHAR   StbcMcs; //j, StbcMcs, bitmask;
3214         CHAR    i; // 3*3
3215         RT_HT_CAPABILITY        *pRtHtCap = NULL;
3216         RT_HT_PHY_INFO          *pActiveHtPhy = NULL;
3217         ULONG           BasicMCS;
3218         UCHAR j, bitmask;
3219         PRT_HT_PHY_INFO                 pDesireHtPhy = NULL;
3220         PHTTRANSMIT_SETTING             pHtPhy = NULL;
3221         PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
3222         PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
3223         BOOLEAN                                 *auto_rate_cur_p;
3224
3225         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3226
3227         auto_rate_cur_p = NULL;
3228
3229         {
3230                 pDesireHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
3231                 pActiveHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
3232                 pHtPhy          = &pAd->StaCfg.HTPhyMode;
3233                 pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
3234                 pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
3235
3236                 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3237         }
3238
3239         if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3240         {
3241                 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3242                         return;
3243
3244                 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3245                 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3246                 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3247                 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3248                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3249                         pMaxHtPhy->field.STBC = STBC_USE;
3250                 else
3251                         pMaxHtPhy->field.STBC = STBC_NONE;
3252         }
3253         else
3254         {
3255                 if (pDesireHtPhy->bHtEnable == FALSE)
3256                         return;
3257
3258                 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3259                 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3260                 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3261                 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3262                         pMaxHtPhy->field.STBC = STBC_USE;
3263                 else
3264                         pMaxHtPhy->field.STBC = STBC_NONE;
3265         }
3266
3267         // Decide MAX ht rate.
3268         if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3269                 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3270         else
3271                 pMaxHtPhy->field.MODE = MODE_HTMIX;
3272
3273     if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3274                 pMaxHtPhy->field.BW = BW_40;
3275         else
3276                 pMaxHtPhy->field.BW = BW_20;
3277
3278     if (pMaxHtPhy->field.BW == BW_20)
3279                 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3280         else
3281                 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3282
3283         for (i=23; i>=0; i--) // 3*3
3284         {
3285                 j = i/8;
3286                 bitmask = (1<<(i-(j*8)));
3287
3288                 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3289                 {
3290                         pMaxHtPhy->field.MCS = i;
3291                         break;
3292                 }
3293
3294                 if (i==0)
3295                         break;
3296         }
3297
3298         // Copy MIN ht rate.  rt2860???
3299         pMinHtPhy->field.BW = BW_20;
3300         pMinHtPhy->field.MCS = 0;
3301         pMinHtPhy->field.STBC = 0;
3302         pMinHtPhy->field.ShortGI = 0;
3303         //If STA assigns fixed rate. update to fixed here.
3304         if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3305         {
3306                 if (pDesireHtPhy->MCSSet[4] != 0)
3307                 {
3308                         pMaxHtPhy->field.MCS = 32;
3309                         pMinHtPhy->field.MCS = 32;
3310                         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3311                 }
3312
3313                 for (i=23; (CHAR)i >= 0; i--) // 3*3
3314                 {
3315                         j = i/8;
3316                         bitmask = (1<<(i-(j*8)));
3317                         if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3318                         {
3319                                 pMaxHtPhy->field.MCS = i;
3320                                 pMinHtPhy->field.MCS = i;
3321                                 break;
3322                         }
3323                         if (i==0)
3324                                 break;
3325                 }
3326         }
3327
3328         // Decide ht rate
3329         pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3330         pHtPhy->field.BW = pMaxHtPhy->field.BW;
3331         pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3332         pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3333         pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3334
3335         // use default now. rt2860
3336         if (pDesireHtPhy->MCSSet[0] != 0xff)
3337                 *auto_rate_cur_p = FALSE;
3338         else
3339                 *auto_rate_cur_p = TRUE;
3340
3341         DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3342         DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3343                 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3344         DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3345 }
3346
3347 // IRQL = DISPATCH_LEVEL
3348 VOID MlmeRadioOff(
3349         IN PRTMP_ADAPTER pAd)
3350 {
3351         RT28XX_MLME_RADIO_OFF(pAd);
3352 }
3353
3354 // IRQL = DISPATCH_LEVEL
3355 VOID MlmeRadioOn(
3356         IN PRTMP_ADAPTER pAd)
3357 {
3358         RT28XX_MLME_RADIO_ON(pAd);
3359 }
3360
3361 // ===========================================================================================
3362 // bss_table.c
3363 // ===========================================================================================
3364
3365
3366 /*! \brief initialize BSS table
3367  *      \param p_tab pointer to the table
3368  *      \return none
3369  *      \pre
3370  *      \post
3371
3372  IRQL = PASSIVE_LEVEL
3373  IRQL = DISPATCH_LEVEL
3374
3375  */
3376 VOID BssTableInit(
3377         IN BSS_TABLE *Tab)
3378 {
3379         int i;
3380
3381         Tab->BssNr = 0;
3382     Tab->BssOverlapNr = 0;
3383         for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3384         {
3385                 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3386                 Tab->BssEntry[i].Rssi = -127;   // initial the rssi as a minimum value
3387         }
3388 }
3389
3390 VOID BATableInit(
3391         IN PRTMP_ADAPTER pAd,
3392     IN BA_TABLE *Tab)
3393 {
3394         int i;
3395
3396         Tab->numAsOriginator = 0;
3397         Tab->numAsRecipient = 0;
3398         NdisAllocateSpinLock(&pAd->BATabLock);
3399         for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3400         {
3401                 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3402                 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3403         }
3404         for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3405         {
3406                 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3407         }
3408 }
3409
3410 /*! \brief search the BSS table by SSID
3411  *      \param p_tab pointer to the bss table
3412  *      \param ssid SSID string
3413  *      \return index of the table, BSS_NOT_FOUND if not in the table
3414  *      \pre
3415  *      \post
3416  *      \note search by sequential search
3417
3418  IRQL = DISPATCH_LEVEL
3419
3420  */
3421 ULONG BssTableSearch(
3422         IN BSS_TABLE *Tab,
3423         IN PUCHAR        pBssid,
3424         IN UCHAR         Channel)
3425 {
3426         UCHAR i;
3427
3428         for (i = 0; i < Tab->BssNr; i++)
3429         {
3430                 //
3431                 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3432                 // We should distinguish this case.
3433                 //
3434                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3435                          ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3436                         MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3437                 {
3438                         return i;
3439                 }
3440         }
3441         return (ULONG)BSS_NOT_FOUND;
3442 }
3443
3444 ULONG BssSsidTableSearch(
3445         IN BSS_TABLE *Tab,
3446         IN PUCHAR        pBssid,
3447         IN PUCHAR        pSsid,
3448         IN UCHAR         SsidLen,
3449         IN UCHAR         Channel)
3450 {
3451         UCHAR i;
3452
3453         for (i = 0; i < Tab->BssNr; i++)
3454         {
3455                 //
3456                 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3457                 // We should distinguish this case.
3458                 //
3459                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3460                          ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3461                         MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3462                         SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3463                 {
3464                         return i;
3465                 }
3466         }
3467         return (ULONG)BSS_NOT_FOUND;
3468 }
3469
3470 ULONG BssTableSearchWithSSID(
3471         IN BSS_TABLE *Tab,
3472         IN PUCHAR        Bssid,
3473         IN PUCHAR        pSsid,
3474         IN UCHAR         SsidLen,
3475         IN UCHAR         Channel)
3476 {
3477         UCHAR i;
3478
3479         for (i = 0; i < Tab->BssNr; i++)
3480         {
3481                 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3482                         ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3483                         MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3484                         (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3485                         (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3486                         (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3487                 {
3488                         return i;
3489                 }
3490         }
3491         return (ULONG)BSS_NOT_FOUND;
3492 }
3493
3494 // IRQL = DISPATCH_LEVEL
3495 VOID BssTableDeleteEntry(
3496         IN OUT  BSS_TABLE *Tab,
3497         IN              PUCHAR    pBssid,
3498         IN              UCHAR     Channel)
3499 {
3500         UCHAR i, j;
3501
3502         for (i = 0; i < Tab->BssNr; i++)
3503         {
3504                 if ((Tab->BssEntry[i].Channel == Channel) &&
3505                         (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3506                 {
3507                         for (j = i; j < Tab->BssNr - 1; j++)
3508                         {
3509                                 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3510                         }
3511                         NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3512                         Tab->BssNr -= 1;
3513                         return;
3514                 }
3515         }
3516 }
3517
3518 /*
3519         ========================================================================
3520         Routine Description:
3521                 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3522
3523         Arguments:
3524         // IRQL = DISPATCH_LEVEL
3525         ========================================================================
3526 */
3527 VOID BATableDeleteORIEntry(
3528         IN OUT  PRTMP_ADAPTER pAd,
3529         IN              BA_ORI_ENTRY    *pBAORIEntry)
3530 {
3531
3532         if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3533         {
3534                 NdisAcquireSpinLock(&pAd->BATabLock);
3535                 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3536                 {
3537                         pAd->BATable.numAsOriginator -= 1;
3538                         DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3539                         // Erase Bitmap flag.
3540                 }
3541                 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) ));       // If STA mode,  erase flag here
3542                 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;    // If STA mode,  erase flag here
3543                 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3544                 pBAORIEntry->Token = 1;
3545                 // Not clear Sequence here.
3546                 NdisReleaseSpinLock(&pAd->BATabLock);
3547         }
3548 }
3549
3550 /*! \brief
3551  *      \param
3552  *      \return
3553  *      \pre
3554  *      \post
3555
3556  IRQL = DISPATCH_LEVEL
3557
3558  */
3559 VOID BssEntrySet(
3560         IN PRTMP_ADAPTER        pAd,
3561         OUT BSS_ENTRY *pBss,
3562         IN PUCHAR pBssid,
3563         IN CHAR Ssid[],
3564         IN UCHAR SsidLen,
3565         IN UCHAR BssType,
3566         IN USHORT BeaconPeriod,
3567         IN PCF_PARM pCfParm,
3568         IN USHORT AtimWin,
3569         IN USHORT CapabilityInfo,
3570         IN UCHAR SupRate[],
3571         IN UCHAR SupRateLen,
3572         IN UCHAR ExtRate[],
3573         IN UCHAR ExtRateLen,
3574         IN HT_CAPABILITY_IE *pHtCapability,
3575         IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
3576         IN UCHAR                        HtCapabilityLen,
3577         IN UCHAR                        AddHtInfoLen,
3578         IN UCHAR                        NewExtChanOffset,
3579         IN UCHAR Channel,
3580         IN CHAR Rssi,
3581         IN LARGE_INTEGER TimeStamp,
3582         IN UCHAR CkipFlag,
3583         IN PEDCA_PARM pEdcaParm,
3584         IN PQOS_CAPABILITY_PARM pQosCapability,
3585         IN PQBSS_LOAD_PARM pQbssLoad,
3586         IN USHORT LengthVIE,
3587         IN PNDIS_802_11_VARIABLE_IEs pVIE)
3588 {
3589         COPY_MAC_ADDR(pBss->Bssid, pBssid);
3590         // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3591         pBss->Hidden = 1;
3592         if (SsidLen > 0)
3593         {
3594                 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3595                 // Or send beacon /probe response with SSID len matching real SSID length,
3596                 // but SSID is all zero. such as "00-00-00-00" with length 4.
3597                 // We have to prevent this case overwrite correct table
3598                 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3599                 {
3600                     NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3601                         NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3602                         pBss->SsidLen = SsidLen;
3603                         pBss->Hidden = 0;
3604                 }
3605         }
3606         else
3607                 pBss->SsidLen = 0;
3608         pBss->BssType = BssType;
3609         pBss->BeaconPeriod = BeaconPeriod;
3610         if (BssType == BSS_INFRA)
3611         {
3612                 if (pCfParm->bValid)
3613                 {
3614                         pBss->CfpCount = pCfParm->CfpCount;
3615                         pBss->CfpPeriod = pCfParm->CfpPeriod;
3616                         pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3617                         pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3618                 }
3619         }
3620         else
3621         {
3622                 pBss->AtimWin = AtimWin;
3623         }
3624
3625         pBss->CapabilityInfo = CapabilityInfo;
3626         // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3627         // Combine with AuthMode, they will decide the connection methods.
3628         pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3629         ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3630         if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3631                 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3632         else
3633                 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3634         pBss->SupRateLen = SupRateLen;
3635         ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3636         NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3637         NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3638         NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3639         pBss->NewExtChanOffset = NewExtChanOffset;
3640         pBss->ExtRateLen = ExtRateLen;
3641         pBss->Channel = Channel;
3642         pBss->CentralChannel = Channel;
3643         pBss->Rssi = Rssi;
3644         // Update CkipFlag. if not exists, the value is 0x0
3645         pBss->CkipFlag = CkipFlag;
3646
3647         // New for microsoft Fixed IEs
3648         NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3649         pBss->FixIEs.BeaconInterval = BeaconPeriod;
3650         pBss->FixIEs.Capabilities = CapabilityInfo;
3651
3652         // New for microsoft Variable IEs
3653         if (LengthVIE != 0)
3654         {
3655                 pBss->VarIELen = LengthVIE;
3656                 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3657         }
3658         else
3659         {
3660                 pBss->VarIELen = 0;
3661         }
3662
3663         pBss->AddHtInfoLen = 0;
3664         pBss->HtCapabilityLen = 0;
3665
3666         if (HtCapabilityLen> 0)
3667         {
3668                 pBss->HtCapabilityLen = HtCapabilityLen;
3669                 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3670                 if (AddHtInfoLen > 0)
3671                 {
3672                         pBss->AddHtInfoLen = AddHtInfoLen;
3673                         NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3674
3675                                 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3676                                 {
3677                                         pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3678                                 }
3679                                 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3680                                 {
3681                                                 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3682                                 }
3683                 }
3684         }
3685
3686         BssCipherParse(pBss);
3687
3688         // new for QOS
3689         if (pEdcaParm)
3690                 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3691         else
3692                 pBss->EdcaParm.bValid = FALSE;
3693         if (pQosCapability)
3694                 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3695         else
3696                 pBss->QosCapability.bValid = FALSE;
3697         if (pQbssLoad)
3698                 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3699         else
3700                 pBss->QbssLoad.bValid = FALSE;
3701
3702         {
3703                 PEID_STRUCT     pEid;
3704                 USHORT          Length = 0;
3705
3706
3707                 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3708                 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3709
3710                 pEid = (PEID_STRUCT) pVIE;
3711
3712                 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3713                 {
3714                         switch(pEid->Eid)
3715                         {
3716                                 case IE_WPA:
3717                                         if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3718                                         {
3719                                                 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3720                                                 {
3721                                                         pBss->WpaIE.IELen = 0;
3722                                                         break;
3723                                                 }
3724                                                 pBss->WpaIE.IELen = pEid->Len + 2;
3725                                                 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3726                                         }
3727                                         break;
3728                 case IE_RSN:
3729                     if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3730                                         {
3731                                                 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3732                                                 {
3733                                                         pBss->RsnIE.IELen = 0;
3734                                                         break;
3735                                                 }
3736                                                 pBss->RsnIE.IELen = pEid->Len + 2;
3737                                                 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3738                         }
3739                                 break;
3740             }
3741                         Length = Length + 2 + (USHORT)pEid->Len;  // Eid[1] + Len[1]+ content[Len]
3742                         pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3743                 }
3744         }
3745 }
3746
3747 /*!
3748  *      \brief insert an entry into the bss table
3749  *      \param p_tab The BSS table
3750  *      \param Bssid BSSID
3751  *      \param ssid SSID
3752  *      \param ssid_len Length of SSID
3753  *      \param bss_type
3754  *      \param beacon_period
3755  *      \param timestamp
3756  *      \param p_cf
3757  *      \param atim_win
3758  *      \param cap
3759  *      \param rates
3760  *      \param rates_len
3761  *      \param channel_idx
3762  *      \return none
3763  *      \pre
3764  *      \post
3765  *      \note If SSID is identical, the old entry will be replaced by the new one
3766
3767  IRQL = DISPATCH_LEVEL
3768
3769  */
3770 ULONG BssTableSetEntry(
3771         IN      PRTMP_ADAPTER   pAd,
3772         OUT BSS_TABLE *Tab,
3773         IN PUCHAR pBssid,
3774         IN CHAR Ssid[],
3775         IN UCHAR SsidLen,
3776         IN UCHAR BssType,
3777         IN USHORT BeaconPeriod,
3778         IN CF_PARM *CfParm,
3779         IN USHORT AtimWin,
3780         IN USHORT CapabilityInfo,
3781         IN UCHAR SupRate[],
3782         IN UCHAR SupRateLen,
3783         IN UCHAR ExtRate[],
3784         IN UCHAR ExtRateLen,
3785         IN HT_CAPABILITY_IE *pHtCapability,
3786         IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
3787         IN UCHAR                        HtCapabilityLen,
3788         IN UCHAR                        AddHtInfoLen,
3789         IN UCHAR                        NewExtChanOffset,
3790         IN UCHAR ChannelNo,
3791         IN CHAR Rssi,
3792         IN LARGE_INTEGER TimeStamp,
3793         IN UCHAR CkipFlag,
3794         IN PEDCA_PARM pEdcaParm,
3795         IN PQOS_CAPABILITY_PARM pQosCapability,
3796         IN PQBSS_LOAD_PARM pQbssLoad,
3797         IN USHORT LengthVIE,
3798         IN PNDIS_802_11_VARIABLE_IEs pVIE)
3799 {
3800         ULONG   Idx;
3801
3802         Idx = BssTableSearchWithSSID(Tab, pBssid,  Ssid, SsidLen, ChannelNo);
3803         if (Idx == BSS_NOT_FOUND)
3804         {
3805                 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3806             {
3807                         //
3808                         // It may happen when BSS Table was full.
3809                         // The desired AP will not be added into BSS Table
3810                         // In this case, if we found the desired AP then overwrite BSS Table.
3811                         //
3812                         if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3813                         {
3814                                 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3815                                         SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3816                                 {
3817                                         Idx = Tab->BssOverlapNr;
3818                                         BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3819                                                 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3820                                                 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3821                     Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3822                                 }
3823                                 return Idx;
3824                         }
3825                         else
3826                         {
3827                         return BSS_NOT_FOUND;
3828                         }
3829                 }
3830                 Idx = Tab->BssNr;
3831                 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3832                                         CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3833                                         NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3834                 Tab->BssNr++;
3835         }
3836         else
3837         {
3838                 /* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
3839                 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3840                         (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3841                 {
3842                 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3843                                         CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3844                                         NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3845                 }
3846         }
3847
3848         return Idx;
3849 }
3850
3851 // IRQL = DISPATCH_LEVEL
3852 VOID BssTableSsidSort(
3853         IN      PRTMP_ADAPTER   pAd,
3854         OUT BSS_TABLE *OutTab,
3855         IN      CHAR Ssid[],
3856         IN      UCHAR SsidLen)
3857 {
3858         INT i;
3859         BssTableInit(OutTab);
3860
3861         for (i = 0; i < pAd->ScanTab.BssNr; i++)
3862         {
3863                 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3864                 BOOLEAN bIsHiddenApIncluded = FALSE;
3865
3866                 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3867             (pAd->MlmeAux.Channel > 14) &&
3868              RadarChannelCheck(pAd, pInBss->Channel))
3869             )
3870                 {
3871                         if (pInBss->Hidden)
3872                                 bIsHiddenApIncluded = TRUE;
3873                 }
3874
3875                 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3876                         (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3877                 {
3878                         BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3879
3880                         // 2.4G/5G N only mode
3881                         if ((pInBss->HtCapabilityLen == 0) &&
3882                                 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3883                         {
3884                                 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3885                                 continue;
3886                         }
3887
3888                         // New for WPA2
3889                         // Check the Authmode first
3890                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3891                         {
3892                                 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3893                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3894                                         // None matched
3895                                         continue;
3896
3897                                 // Check cipher suite, AP must have more secured cipher than station setting
3898                                 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3899                                 {
3900                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
3901                                         if (pInBss->WPA.bMixMode == FALSE)
3902                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3903                                                         continue;
3904
3905                                         // check group cipher
3906                                         if (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3907                                             pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3908                                             pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3909                                                 continue;
3910
3911                                         // check pairwise cipher, skip if none matched
3912                                         // If profile set to AES, let it pass without question.
3913                                         // If profile set to TKIP, we must find one mateched
3914                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3915                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3916                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3917                                                 continue;
3918                                 }
3919                                 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3920                                 {
3921                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
3922                                         if (pInBss->WPA2.bMixMode == FALSE)
3923                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3924                                                         continue;
3925
3926                                         // check group cipher
3927                                         if (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3928                                             pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3929                                             pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3930                                                 continue;
3931
3932                                         // check pairwise cipher, skip if none matched
3933                                         // If profile set to AES, let it pass without question.
3934                                         // If profile set to TKIP, we must find one mateched
3935                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3936                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3937                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3938                                                 continue;
3939                                 }
3940                         }
3941                         // Bss Type matched, SSID matched.
3942                         // We will check wepstatus for qualification Bss
3943                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3944                         {
3945                                 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3946                                 //
3947                                 // For the SESv2 case, we will not qualify WepStatus.
3948                                 //
3949                                 if (!pInBss->bSES)
3950                                         continue;
3951                         }
3952
3953                         // Since the AP is using hidden SSID, and we are trying to connect to ANY
3954                         // It definitely will fail. So, skip it.
3955                         // CCX also require not even try to connect it!!
3956                         if (SsidLen == 0)
3957                                 continue;
3958
3959                         // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3960                         // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3961                         if ((pInBss->CentralChannel != pInBss->Channel) &&
3962                                 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3963                         {
3964                                 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3965                                 {
3966                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3967                                         SetCommonHT(pAd);
3968                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3969                                 }
3970                                 else
3971                                 {
3972                                         if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3973                                         {
3974                                                 SetCommonHT(pAd);
3975                                         }
3976                                 }
3977                         }
3978
3979                         // copy matching BSS from InTab to OutTab
3980                         NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3981
3982                         OutTab->BssNr++;
3983                 }
3984                 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3985                 {
3986                         BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3987
3988                         // 2.4G/5G N only mode
3989                         if ((pInBss->HtCapabilityLen == 0) &&
3990                                 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3991                         {
3992                                 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3993                                 continue;
3994                         }
3995
3996                         // New for WPA2
3997                         // Check the Authmode first
3998                         if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3999                         {
4000                                 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4001                                 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4002                                         // None matched
4003                                         continue;
4004
4005                                 // Check cipher suite, AP must have more secured cipher than station setting
4006                                 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4007                                 {
4008                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
4009                                         if (pInBss->WPA.bMixMode == FALSE)
4010                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4011                                                         continue;
4012
4013                                         // check group cipher
4014                                         if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4015                                                 continue;
4016
4017                                         // check pairwise cipher, skip if none matched
4018                                         // If profile set to AES, let it pass without question.
4019                                         // If profile set to TKIP, we must find one mateched
4020                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4021                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4022                                                 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4023                                                 continue;
4024                                 }
4025                                 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4026                                 {
4027                                         // If it's not mixed mode, we should only let BSS pass with the same encryption
4028                                         if (pInBss->WPA2.bMixMode == FALSE)
4029                                                 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4030                                                         continue;
4031
4032                                         // check group cipher
4033                                         if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4034                                                 continue;
4035
4036                                         // check pairwise cipher, skip if none matched
4037                                         // If profile set to AES, let it pass without question.
4038                                         // If profile set to TKIP, we must find one mateched
4039                                         if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4040                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4041                                                 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4042                                                 continue;
4043                                 }
4044                         }
4045                         // Bss Type matched, SSID matched.
4046                         // We will check wepstatus for qualification Bss
4047                         else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4048                                         continue;
4049
4050                         // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4051                         // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4052                         if ((pInBss->CentralChannel != pInBss->Channel) &&
4053                                 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4054                         {
4055                                 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4056                                 {
4057                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4058                                         SetCommonHT(pAd);
4059                                         pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4060                                 }
4061                         }
4062
4063                         // copy matching BSS from InTab to OutTab
4064                         NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4065
4066                         OutTab->BssNr++;
4067                 }
4068
4069                 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4070                         break;
4071         }
4072
4073         BssTableSortByRssi(OutTab);
4074 }
4075
4076
4077 // IRQL = DISPATCH_LEVEL
4078 VOID BssTableSortByRssi(
4079         IN OUT BSS_TABLE *OutTab)
4080 {
4081         INT       i, j;
4082         BSS_ENTRY TmpBss;
4083
4084         for (i = 0; i < OutTab->BssNr - 1; i++)
4085         {
4086                 for (j = i+1; j < OutTab->BssNr; j++)
4087                 {
4088                         if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4089                         {
4090                                 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4091                                 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4092                                 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4093                         }
4094                 }
4095         }
4096 }
4097
4098 VOID BssCipherParse(
4099         IN OUT  PBSS_ENTRY      pBss)
4100 {
4101         PEID_STRUCT              pEid;
4102         PUCHAR                          pTmp;
4103         PRSN_IE_HEADER_STRUCT                   pRsnHeader;
4104         PCIPHER_SUITE_STRUCT                    pCipher;
4105         PAKM_SUITE_STRUCT                               pAKM;
4106         USHORT                                                  Count;
4107         INT                                                             Length;
4108         NDIS_802_11_ENCRYPTION_STATUS   TmpCipher;
4109
4110         //
4111         // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4112         //
4113         if (pBss->Privacy)
4114         {
4115                 pBss->WepStatus         = Ndis802_11WEPEnabled;
4116         }
4117         else
4118         {
4119                 pBss->WepStatus         = Ndis802_11WEPDisabled;
4120         }
4121         // Set default to disable & open authentication before parsing variable IE
4122         pBss->AuthMode          = Ndis802_11AuthModeOpen;
4123         pBss->AuthModeAux       = Ndis802_11AuthModeOpen;
4124
4125         // Init WPA setting
4126         pBss->WPA.PairCipher    = Ndis802_11WEPDisabled;
4127         pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4128         pBss->WPA.GroupCipher   = Ndis802_11WEPDisabled;
4129         pBss->WPA.RsnCapability = 0;
4130         pBss->WPA.bMixMode              = FALSE;
4131
4132         // Init WPA2 setting
4133         pBss->WPA2.PairCipher    = Ndis802_11WEPDisabled;
4134         pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4135         pBss->WPA2.GroupCipher   = Ndis802_11WEPDisabled;
4136         pBss->WPA2.RsnCapability = 0;
4137         pBss->WPA2.bMixMode      = FALSE;
4138
4139
4140         Length = (INT) pBss->VarIELen;
4141
4142         while (Length > 0)
4143         {
4144                 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4145                 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4146                 pEid = (PEID_STRUCT) pTmp;
4147                 switch (pEid->Eid)
4148                 {
4149                         case IE_WPA:
4150                                 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4151                                 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4152                                 {
4153                                         pTmp   += 11;
4154                                         switch (*pTmp)
4155                                         {
4156                                                 case 1:
4157                                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4158                                                         pBss->WepStatus = Ndis802_11Encryption1Enabled;
4159                                                         pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4160                                                         pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4161                                                         break;
4162                                                 case 2:
4163                                                         pBss->WepStatus = Ndis802_11Encryption2Enabled;
4164                                                         pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4165                                                         pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4166                                                         break;
4167                                                 case 4:
4168                                                         pBss->WepStatus = Ndis802_11Encryption3Enabled;
4169                                                         pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4170                                                         pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4171                                                         break;
4172                                                 default:
4173                                                         break;
4174                                         }
4175
4176                                         // if Cisco IE_WPA, break
4177                                         break;
4178                                 }
4179                                 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4180                                 {
4181                                         pBss->bSES = TRUE;
4182                                         break;
4183                                 }
4184                                 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4185                                 {
4186                                         // if unsupported vendor specific IE
4187                                         break;
4188                                 }
4189                                 // Skip OUI, version, and multicast suite
4190                                 // This part should be improved in the future when AP supported multiple cipher suite.
4191                                 // For now, it's OK since almost all APs have fixed cipher suite supported.
4192                                 // pTmp = (PUCHAR) pEid->Octet;
4193                                 pTmp   += 11;
4194
4195                                 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4196                                 //      Value      Meaning
4197                                 //      0                       None
4198                                 //      1                       WEP-40
4199                                 //      2                       Tkip
4200                                 //      3                       WRAP
4201                                 //      4                       AES
4202                                 //      5                       WEP-104
4203                                 // Parse group cipher
4204                                 switch (*pTmp)
4205                                 {
4206                                         case 1:
4207                                                 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4208                                                 break;
4209                                         case 5:
4210                                                 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4211                                                 break;
4212                                         case 2:
4213                                                 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4214                                                 break;
4215                                         case 4:
4216                                                 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4217                                                 break;
4218                                         default:
4219                                                 break;
4220                                 }
4221                                 // number of unicast suite
4222                                 pTmp   += 1;
4223
4224                                 // skip all unicast cipher suites
4225                                 //Count = *(PUSHORT) pTmp;
4226                                 Count = (pTmp[1]<<8) + pTmp[0];
4227                                 pTmp   += sizeof(USHORT);
4228
4229                                 // Parsing all unicast cipher suite
4230                                 while (Count > 0)
4231                                 {
4232                                         // Skip OUI
4233                                         pTmp += 3;
4234                                         TmpCipher = Ndis802_11WEPDisabled;
4235                                         switch (*pTmp)
4236                                         {
4237                                                 case 1:
4238                                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4239                                                         TmpCipher = Ndis802_11Encryption1Enabled;
4240                                                         break;
4241                                                 case 2:
4242                                                         TmpCipher = Ndis802_11Encryption2Enabled;
4243                                                         break;
4244                                                 case 4:
4245                                                         TmpCipher = Ndis802_11Encryption3Enabled;
4246                                                         break;
4247                                                 default:
4248                                                         break;
4249                                         }
4250                                         if (TmpCipher > pBss->WPA.PairCipher)
4251                                         {
4252                                                 // Move the lower cipher suite to PairCipherAux
4253                                                 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4254                                                 pBss->WPA.PairCipher    = TmpCipher;
4255                                         }
4256                                         else
4257                                         {
4258                                                 pBss->WPA.PairCipherAux = TmpCipher;
4259                                         }
4260                                         pTmp++;
4261                                         Count--;
4262                                 }
4263
4264                                 // 4. get AKM suite counts
4265                                 //Count = *(PUSHORT) pTmp;
4266                                 Count = (pTmp[1]<<8) + pTmp[0];
4267                                 pTmp   += sizeof(USHORT);
4268                                 pTmp   += 3;
4269
4270                                 switch (*pTmp)
4271                                 {
4272                                         case 1:
4273                                                 // Set AP support WPA mode
4274                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4275                                                         pBss->AuthMode = Ndis802_11AuthModeWPA;
4276                                                 else
4277                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4278                                                 break;
4279                                         case 2:
4280                                                 // Set AP support WPA mode
4281                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4282                                                         pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4283                                                 else
4284                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4285                                                 break;
4286                                         default:
4287                                                 break;
4288                                 }
4289                                 pTmp   += 1;
4290
4291                                 // Fixed for WPA-None
4292                                 if (pBss->BssType == BSS_ADHOC)
4293                                 {
4294                                         pBss->AuthMode    = Ndis802_11AuthModeWPANone;
4295                                         pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4296                                         pBss->WepStatus   = pBss->WPA.GroupCipher;
4297                                         if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4298                                                 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4299                                 }
4300                                 else
4301                                         pBss->WepStatus   = pBss->WPA.PairCipher;
4302
4303                                 // Check the Pair & Group, if different, turn on mixed mode flag
4304                                 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4305                                         pBss->WPA.bMixMode = TRUE;
4306
4307                                 break;
4308
4309                         case IE_RSN:
4310                                 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4311
4312                                 // 0. Version must be 1
4313                                 if (le2cpu16(pRsnHeader->Version) != 1)
4314                                         break;
4315                                 pTmp   += sizeof(RSN_IE_HEADER_STRUCT);
4316
4317                                 // 1. Check group cipher
4318                                 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4319                                 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4320                                         break;
4321
4322                                 // Parse group cipher
4323                                 switch (pCipher->Type)
4324                                 {
4325                                         case 1:
4326                                                 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4327                                                 break;
4328                                         case 5:
4329                                                 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4330                                                 break;
4331                                         case 2:
4332                                                 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4333                                                 break;
4334                                         case 4:
4335                                                 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4336                                                 break;
4337                                         default:
4338                                                 break;
4339                                 }
4340                                 // set to correct offset for next parsing
4341                                 pTmp   += sizeof(CIPHER_SUITE_STRUCT);
4342
4343                                 // 2. Get pairwise cipher counts
4344                                 //Count = *(PUSHORT) pTmp;
4345                                 Count = (pTmp[1]<<8) + pTmp[0];
4346                                 pTmp   += sizeof(USHORT);
4347
4348                                 // 3. Get pairwise cipher
4349                                 // Parsing all unicast cipher suite
4350                                 while (Count > 0)
4351                                 {
4352                                         // Skip OUI
4353                                         pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4354                                         TmpCipher = Ndis802_11WEPDisabled;
4355                                         switch (pCipher->Type)
4356                                         {
4357                                                 case 1:
4358                                                 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4359                                                         TmpCipher = Ndis802_11Encryption1Enabled;
4360                                                         break;
4361                                                 case 2:
4362                                                         TmpCipher = Ndis802_11Encryption2Enabled;
4363                                                         break;
4364                                                 case 4:
4365                                                         TmpCipher = Ndis802_11Encryption3Enabled;
4366                                                         break;
4367                                                 default:
4368                                                         break;
4369                                         }
4370                                         if (TmpCipher > pBss->WPA2.PairCipher)
4371                                         {
4372                                                 // Move the lower cipher suite to PairCipherAux
4373                                                 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4374                                                 pBss->WPA2.PairCipher    = TmpCipher;
4375                                         }
4376                                         else
4377                                         {
4378                                                 pBss->WPA2.PairCipherAux = TmpCipher;
4379                                         }
4380                                         pTmp += sizeof(CIPHER_SUITE_STRUCT);
4381                                         Count--;
4382                                 }
4383
4384                                 // 4. get AKM suite counts
4385                                 //Count = *(PUSHORT) pTmp;
4386                                 Count = (pTmp[1]<<8) + pTmp[0];
4387                                 pTmp   += sizeof(USHORT);
4388
4389                                 // 5. Get AKM ciphers
4390                                 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4391                                 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4392                                         break;
4393
4394                                 switch (pAKM->Type)
4395                                 {
4396                                         case 1:
4397                                                 // Set AP support WPA mode
4398                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4399                                                         pBss->AuthMode = Ndis802_11AuthModeWPA2;
4400                                                 else
4401                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4402                                                 break;
4403                                         case 2:
4404                                                 // Set AP support WPA mode
4405                                                 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4406                                                         pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4407                                                 else
4408                                                         pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4409                                                 break;
4410                                         default:
4411                                                 break;
4412                                 }
4413                                 pTmp   += (Count * sizeof(AKM_SUITE_STRUCT));
4414
4415                                 // Fixed for WPA-None
4416                                 if (pBss->BssType == BSS_ADHOC)
4417                                 {
4418                                         pBss->AuthMode = Ndis802_11AuthModeWPANone;
4419                                         pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4420                                         pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4421                                         pBss->WPA.GroupCipher   = pBss->WPA2.GroupCipher;
4422                                         pBss->WepStatus                 = pBss->WPA.GroupCipher;
4423                                         if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4424                                                 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4425                                 }
4426                                 pBss->WepStatus   = pBss->WPA2.PairCipher;
4427
4428                                 // 6. Get RSN capability
4429                                 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4430                                 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4431                                 pTmp += sizeof(USHORT);
4432
4433                                 // Check the Pair & Group, if different, turn on mixed mode flag
4434                                 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4435                                         pBss->WPA2.bMixMode = TRUE;
4436
4437                                 break;
4438                         default:
4439                                 break;
4440                 }
4441                 Length -= (pEid->Len + 2);
4442         }
4443 }
4444
4445 // ===========================================================================================
4446 // mac_table.c
4447 // ===========================================================================================
4448
4449 /*! \brief generates a random mac address value for IBSS BSSID
4450  *      \param Addr the bssid location
4451  *      \return none
4452  *      \pre
4453  *      \post
4454  */
4455 VOID MacAddrRandomBssid(
4456         IN PRTMP_ADAPTER pAd,
4457         OUT PUCHAR pAddr)
4458 {
4459         INT i;
4460
4461         for (i = 0; i < MAC_ADDR_LEN; i++)
4462         {
4463                 pAddr[i] = RandomByte(pAd);
4464         }
4465
4466         pAddr[0] = (pAddr[0] & 0xfe) | 0x02;  // the first 2 bits must be 01xxxxxxxx
4467 }
4468
4469 /*! \brief init the management mac frame header
4470  *      \param p_hdr mac header
4471  *      \param subtype subtype of the frame
4472  *      \param p_ds destination address, don't care if it is a broadcast address
4473  *      \return none
4474  *      \pre the station has the following information in the pAd->StaCfg
4475  *       - bssid
4476  *       - station address
4477  *      \post
4478  *      \note this function initializes the following field
4479
4480  IRQL = PASSIVE_LEVEL
4481  IRQL = DISPATCH_LEVEL
4482
4483  */
4484 VOID MgtMacHeaderInit(
4485         IN      PRTMP_ADAPTER   pAd,
4486         IN OUT PHEADER_802_11 pHdr80211,
4487         IN UCHAR SubType,
4488         IN UCHAR ToDs,
4489         IN PUCHAR pDA,
4490         IN PUCHAR pBssid)
4491 {
4492         NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4493
4494         pHdr80211->FC.Type = BTYPE_MGMT;
4495         pHdr80211->FC.SubType = SubType;
4496         pHdr80211->FC.ToDs = ToDs;
4497         COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4498
4499         COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4500
4501         COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4502 }
4503
4504 // ===========================================================================================
4505 // mem_mgmt.c
4506 // ===========================================================================================
4507
4508 /*!***************************************************************************
4509  * This routine build an outgoing frame, and fill all information specified
4510  * in argument list to the frame body. The actual frame size is the summation
4511  * of all arguments.
4512  * input params:
4513  *              Buffer - pointer to a pre-allocated memory segment
4514  *              args - a list of <int arg_size, arg> pairs.
4515  *              NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4516  *                                                 function will FAIL!!!
4517  * return:
4518  *              Size of the buffer
4519  * usage:
4520  *              MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4521
4522  IRQL = PASSIVE_LEVEL
4523  IRQL = DISPATCH_LEVEL
4524
4525  ****************************************************************************/
4526 ULONG MakeOutgoingFrame(
4527         OUT CHAR *Buffer,
4528         OUT ULONG *FrameLen, ...)
4529 {
4530         CHAR   *p;
4531         int     leng;
4532         ULONG   TotLeng;
4533         va_list Args;
4534
4535         // calculates the total length
4536         TotLeng = 0;
4537         va_start(Args, FrameLen);
4538         do
4539         {
4540                 leng = va_arg(Args, int);
4541                 if (leng == END_OF_ARGS)
4542                 {
4543                         break;
4544                 }
4545                 p = va_arg(Args, PVOID);
4546                 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4547                 TotLeng = TotLeng + leng;
4548         } while(TRUE);
4549
4550         va_end(Args); /* clean up */
4551         *FrameLen = TotLeng;
4552         return TotLeng;
4553 }
4554
4555 // ===========================================================================================
4556 // mlme_queue.c
4557 // ===========================================================================================
4558
4559 /*! \brief      Initialize The MLME Queue, used by MLME Functions
4560  *      \param  *Queue     The MLME Queue
4561  *      \return Always     Return NDIS_STATE_SUCCESS in this implementation
4562  *      \pre
4563  *      \post
4564  *      \note   Because this is done only once (at the init stage), no need to be locked
4565
4566  IRQL = PASSIVE_LEVEL
4567
4568  */
4569 NDIS_STATUS MlmeQueueInit(
4570         IN MLME_QUEUE *Queue)
4571 {
4572         INT i;
4573
4574         NdisAllocateSpinLock(&Queue->Lock);
4575
4576         Queue->Num      = 0;
4577         Queue->Head = 0;
4578         Queue->Tail = 0;
4579
4580         for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4581         {
4582                 Queue->Entry[i].Occupied = FALSE;
4583                 Queue->Entry[i].MsgLen = 0;
4584                 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4585         }
4586
4587         return NDIS_STATUS_SUCCESS;
4588 }
4589
4590 /*! \brief       Enqueue a message for other threads, if they want to send messages to MLME thread
4591  *      \param  *Queue    The MLME Queue
4592  *      \param   Machine  The State Machine Id
4593  *      \param   MsgType  The Message Type
4594  *      \param   MsgLen   The Message length
4595  *      \param  *Msg      The message pointer
4596  *      \return  TRUE if enqueue is successful, FALSE if the queue is full
4597  *      \pre
4598  *      \post
4599  *      \note    The message has to be initialized
4600
4601  IRQL = PASSIVE_LEVEL
4602  IRQL = DISPATCH_LEVEL
4603
4604  */
4605 BOOLEAN MlmeEnqueue(
4606         IN      PRTMP_ADAPTER   pAd,
4607         IN ULONG Machine,
4608         IN ULONG MsgType,
4609         IN ULONG MsgLen,
4610         IN VOID *Msg)
4611 {
4612         INT Tail;
4613         MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4614
4615         // Do nothing if the driver is starting halt state.
4616         // This might happen when timer already been fired before cancel timer with mlmehalt
4617         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4618                 return FALSE;
4619
4620         // First check the size, it MUST not exceed the mlme queue size
4621         if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4622         {
4623                 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4624                 return FALSE;
4625         }
4626
4627         if (MlmeQueueFull(Queue))
4628         {
4629                 return FALSE;
4630         }
4631
4632         NdisAcquireSpinLock(&(Queue->Lock));
4633         Tail = Queue->Tail;
4634         Queue->Tail++;
4635         Queue->Num++;
4636         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4637         {
4638                 Queue->Tail = 0;
4639         }
4640
4641         Queue->Entry[Tail].Wcid = RESERVED_WCID;
4642         Queue->Entry[Tail].Occupied = TRUE;
4643         Queue->Entry[Tail].Machine = Machine;
4644         Queue->Entry[Tail].MsgType = MsgType;
4645         Queue->Entry[Tail].MsgLen  = MsgLen;
4646
4647         if (Msg != NULL)
4648         {
4649                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4650         }
4651
4652         NdisReleaseSpinLock(&(Queue->Lock));
4653         return TRUE;
4654 }
4655
4656 /*! \brief       This function is used when Recv gets a MLME message
4657  *      \param  *Queue                   The MLME Queue
4658  *      \param   TimeStampHigh   The upper 32 bit of timestamp
4659  *      \param   TimeStampLow    The lower 32 bit of timestamp
4660  *      \param   Rssi                    The receiving RSSI strength
4661  *      \param   MsgLen                  The length of the message
4662  *      \param  *Msg                     The message pointer
4663  *      \return  TRUE if everything ok, FALSE otherwise (like Queue Full)
4664  *      \pre
4665  *      \post
4666
4667  IRQL = DISPATCH_LEVEL
4668
4669  */
4670 BOOLEAN MlmeEnqueueForRecv(
4671         IN      PRTMP_ADAPTER   pAd,
4672         IN ULONG Wcid,
4673         IN ULONG TimeStampHigh,
4674         IN ULONG TimeStampLow,
4675         IN UCHAR Rssi0,
4676         IN UCHAR Rssi1,
4677         IN UCHAR Rssi2,
4678         IN ULONG MsgLen,
4679         IN VOID *Msg,
4680         IN UCHAR Signal)
4681 {
4682         INT              Tail, Machine;
4683         PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4684         INT              MsgType;
4685         MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4686
4687         // Do nothing if the driver is starting halt state.
4688         // This might happen when timer already been fired before cancel timer with mlmehalt
4689         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4690         {
4691                 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4692                 return FALSE;
4693         }
4694
4695         // First check the size, it MUST not exceed the mlme queue size
4696         if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4697         {
4698                 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4699                 return FALSE;
4700         }
4701
4702         if (MlmeQueueFull(Queue))
4703         {
4704                 return FALSE;
4705         }
4706
4707         {
4708                 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4709                 {
4710                         DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4711                         return FALSE;
4712                 }
4713         }
4714
4715         // OK, we got all the informations, it is time to put things into queue
4716         NdisAcquireSpinLock(&(Queue->Lock));
4717         Tail = Queue->Tail;
4718         Queue->Tail++;
4719         Queue->Num++;
4720         if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4721         {
4722                 Queue->Tail = 0;
4723         }
4724         Queue->Entry[Tail].Occupied = TRUE;
4725         Queue->Entry[Tail].Machine = Machine;
4726         Queue->Entry[Tail].MsgType = MsgType;
4727         Queue->Entry[Tail].MsgLen  = MsgLen;
4728         Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4729         Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4730         Queue->Entry[Tail].Rssi0 = Rssi0;
4731         Queue->Entry[Tail].Rssi1 = Rssi1;
4732         Queue->Entry[Tail].Rssi2 = Rssi2;
4733         Queue->Entry[Tail].Signal = Signal;
4734         Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4735
4736         Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4737
4738         if (Msg != NULL)
4739         {
4740                 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4741         }
4742
4743         NdisReleaseSpinLock(&(Queue->Lock));
4744
4745         RT28XX_MLME_HANDLER(pAd);
4746
4747         return TRUE;
4748 }
4749
4750
4751 /*! \brief       Dequeue a message from the MLME Queue
4752  *      \param  *Queue    The MLME Queue
4753  *      \param  *Elem     The message dequeued from MLME Queue
4754  *      \return  TRUE if the Elem contains something, FALSE otherwise
4755  *      \pre
4756  *      \post
4757
4758  IRQL = DISPATCH_LEVEL
4759
4760  */
4761 BOOLEAN MlmeDequeue(
4762         IN MLME_QUEUE *Queue,
4763         OUT MLME_QUEUE_ELEM **Elem)
4764 {
4765         NdisAcquireSpinLock(&(Queue->Lock));
4766         *Elem = &(Queue->Entry[Queue->Head]);
4767         Queue->Num--;
4768         Queue->Head++;
4769         if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4770         {
4771                 Queue->Head = 0;
4772         }
4773         NdisReleaseSpinLock(&(Queue->Lock));
4774         return TRUE;
4775 }
4776
4777 // IRQL = DISPATCH_LEVEL
4778 VOID    MlmeRestartStateMachine(
4779         IN      PRTMP_ADAPTER   pAd)
4780 {
4781 #ifdef RT2860
4782         MLME_QUEUE_ELEM         *Elem = NULL;
4783 #endif
4784         BOOLEAN                         Cancelled;
4785
4786         DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4787
4788 #ifdef RT2860
4789         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4790         if(pAd->Mlme.bRunning)
4791         {
4792                 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4793                 return;
4794         }
4795         else
4796         {
4797                 pAd->Mlme.bRunning = TRUE;
4798         }
4799         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4800
4801         // Remove all Mlme queues elements
4802         while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4803         {
4804                 //From message type, determine which state machine I should drive
4805                 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4806                 {
4807                         // free MLME element
4808                         Elem->Occupied = FALSE;
4809                         Elem->MsgLen = 0;
4810
4811                 }
4812                 else {
4813                         DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4814                 }
4815         }
4816 #endif /* RT2860 */
4817
4818         {
4819                 // Cancel all timer events
4820                 // Be careful to cancel new added timer
4821                 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,         &Cancelled);
4822                 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,   &Cancelled);
4823                 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,  &Cancelled);
4824                 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,           &Cancelled);
4825                 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,         &Cancelled);
4826                 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,           &Cancelled);
4827         }
4828
4829         // Change back to original channel in case of doing scan
4830         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4831         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4832
4833         // Resume MSDU which is turned off durning scan
4834         RTMPResumeMsduTransmission(pAd);
4835
4836         {
4837                 // Set all state machines back IDLE
4838                 pAd->Mlme.CntlMachine.CurrState    = CNTL_IDLE;
4839                 pAd->Mlme.AssocMachine.CurrState   = ASSOC_IDLE;
4840                 pAd->Mlme.AuthMachine.CurrState    = AUTH_REQ_IDLE;
4841                 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4842                 pAd->Mlme.SyncMachine.CurrState    = SYNC_IDLE;
4843                 pAd->Mlme.ActMachine.CurrState    = ACT_IDLE;
4844         }
4845
4846 #ifdef RT2860
4847         // Remove running state
4848         NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4849         pAd->Mlme.bRunning = FALSE;
4850         NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4851 #endif
4852 }
4853
4854 /*! \brief      test if the MLME Queue is empty
4855  *      \param  *Queue    The MLME Queue
4856  *      \return TRUE if the Queue is empty, FALSE otherwise
4857  *      \pre
4858  *      \post
4859
4860  IRQL = DISPATCH_LEVEL
4861
4862  */
4863 BOOLEAN MlmeQueueEmpty(
4864         IN MLME_QUEUE *Queue)
4865 {
4866         BOOLEAN Ans;
4867
4868         NdisAcquireSpinLock(&(Queue->Lock));
4869         Ans = (Queue->Num == 0);
4870         NdisReleaseSpinLock(&(Queue->Lock));
4871
4872         return Ans;
4873 }
4874
4875 /*! \brief       test if the MLME Queue is full
4876  *      \param   *Queue          The MLME Queue
4877  *      \return  TRUE if the Queue is empty, FALSE otherwise
4878  *      \pre
4879  *      \post
4880
4881  IRQL = PASSIVE_LEVEL
4882  IRQL = DISPATCH_LEVEL
4883
4884  */
4885 BOOLEAN MlmeQueueFull(
4886         IN MLME_QUEUE *Queue)
4887 {
4888         BOOLEAN Ans;
4889
4890         NdisAcquireSpinLock(&(Queue->Lock));
4891         Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4892         NdisReleaseSpinLock(&(Queue->Lock));
4893
4894         return Ans;
4895 }
4896
4897 /*! \brief       The destructor of MLME Queue
4898  *      \param
4899  *      \return
4900  *      \pre
4901  *      \post
4902  *      \note   Clear Mlme Queue, Set Queue->Num to Zero.
4903
4904  IRQL = PASSIVE_LEVEL
4905
4906  */
4907 VOID MlmeQueueDestroy(
4908         IN MLME_QUEUE *pQueue)
4909 {
4910         NdisAcquireSpinLock(&(pQueue->Lock));
4911         pQueue->Num  = 0;
4912         pQueue->Head = 0;
4913         pQueue->Tail = 0;
4914         NdisReleaseSpinLock(&(pQueue->Lock));
4915         NdisFreeSpinLock(&(pQueue->Lock));
4916 }
4917
4918 /*! \brief       To substitute the message type if the message is coming from external
4919  *      \param  pFrame             The frame received
4920  *      \param  *Machine           The state machine
4921  *      \param  *MsgType           the message type for the state machine
4922  *      \return TRUE if the substitution is successful, FALSE otherwise
4923  *      \pre
4924  *      \post
4925
4926  IRQL = DISPATCH_LEVEL
4927
4928  */
4929 BOOLEAN MsgTypeSubst(
4930         IN PRTMP_ADAPTER  pAd,
4931         IN PFRAME_802_11 pFrame,
4932         OUT INT *Machine,
4933         OUT INT *MsgType)
4934 {
4935         USHORT  Seq;
4936         UCHAR   EAPType;
4937         PUCHAR  pData;
4938
4939         // Pointer to start of data frames including SNAP header
4940         pData = (PUCHAR) pFrame + LENGTH_802_11;
4941
4942         // The only data type will pass to this function is EAPOL frame
4943         if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4944         {
4945                 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4946                 {
4947                         // Cisco Aironet SNAP header
4948                         *Machine = AIRONET_STATE_MACHINE;
4949                         *MsgType = MT2_AIRONET_MSG;
4950                         return (TRUE);
4951                 }
4952                 {
4953                         *Machine = WPA_PSK_STATE_MACHINE;
4954                         EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4955                         return(WpaMsgTypeSubst(EAPType, MsgType));
4956                 }
4957         }
4958
4959         switch (pFrame->Hdr.FC.SubType)
4960         {
4961                 case SUBTYPE_ASSOC_REQ:
4962                         *Machine = ASSOC_STATE_MACHINE;
4963                         *MsgType = MT2_PEER_ASSOC_REQ;
4964                         break;
4965                 case SUBTYPE_ASSOC_RSP:
4966                         *Machine = ASSOC_STATE_MACHINE;
4967                         *MsgType = MT2_PEER_ASSOC_RSP;
4968                         break;
4969                 case SUBTYPE_REASSOC_REQ:
4970                         *Machine = ASSOC_STATE_MACHINE;
4971                         *MsgType = MT2_PEER_REASSOC_REQ;
4972                         break;
4973                 case SUBTYPE_REASSOC_RSP:
4974                         *Machine = ASSOC_STATE_MACHINE;
4975                         *MsgType = MT2_PEER_REASSOC_RSP;
4976                         break;
4977                 case SUBTYPE_PROBE_REQ:
4978                         *Machine = SYNC_STATE_MACHINE;
4979                         *MsgType = MT2_PEER_PROBE_REQ;
4980                         break;
4981                 case SUBTYPE_PROBE_RSP:
4982                         *Machine = SYNC_STATE_MACHINE;
4983                         *MsgType = MT2_PEER_PROBE_RSP;
4984                         break;
4985                 case SUBTYPE_BEACON:
4986                         *Machine = SYNC_STATE_MACHINE;
4987                         *MsgType = MT2_PEER_BEACON;
4988                         break;
4989                 case SUBTYPE_ATIM:
4990                         *Machine = SYNC_STATE_MACHINE;
4991                         *MsgType = MT2_PEER_ATIM;
4992                         break;
4993                 case SUBTYPE_DISASSOC:
4994                         *Machine = ASSOC_STATE_MACHINE;
4995                         *MsgType = MT2_PEER_DISASSOC_REQ;
4996                         break;
4997                 case SUBTYPE_AUTH:
4998                         // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4999                         NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5000                         if (Seq == 1 || Seq == 3)
5001                         {
5002                                 *Machine = AUTH_RSP_STATE_MACHINE;
5003                                 *MsgType = MT2_PEER_AUTH_ODD;
5004                         }
5005                         else if (Seq == 2 || Seq == 4)
5006                         {
5007                                 *Machine = AUTH_STATE_MACHINE;
5008                                 *MsgType = MT2_PEER_AUTH_EVEN;
5009                         }
5010                         else
5011                         {
5012                                 return FALSE;
5013                         }
5014                         break;
5015                 case SUBTYPE_DEAUTH:
5016                         *Machine = AUTH_RSP_STATE_MACHINE;
5017                         *MsgType = MT2_PEER_DEAUTH;
5018                         break;
5019                 case SUBTYPE_ACTION:
5020                         *Machine = ACTION_STATE_MACHINE;
5021                         //  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5022                         if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5023                         {
5024                                 *MsgType = MT2_ACT_INVALID;
5025                         }
5026                         else
5027                         {
5028                                 *MsgType = (pFrame->Octet[0]&0x7F);
5029                         }
5030                         break;
5031                 default:
5032                         return FALSE;
5033                         break;
5034         }
5035
5036         return TRUE;
5037 }
5038
5039 // ===========================================================================================
5040 // state_machine.c
5041 // ===========================================================================================
5042
5043 /*! \brief Initialize the state machine.
5044  *      \param *S                       pointer to the state machine
5045  *      \param  Trans           State machine transition function
5046  *      \param  StNr            number of states
5047  *      \param  MsgNr           number of messages
5048  *      \param  DefFunc         default function, when there is invalid state/message combination
5049  *      \param  InitState       initial state of the state machine
5050  *      \param  Base            StateMachine base, internal use only
5051  *      \pre p_sm should be a legal pointer
5052  *      \post
5053
5054  IRQL = PASSIVE_LEVEL
5055
5056  */
5057 VOID StateMachineInit(
5058         IN STATE_MACHINE *S,
5059         IN STATE_MACHINE_FUNC Trans[],
5060         IN ULONG StNr,
5061         IN ULONG MsgNr,
5062         IN STATE_MACHINE_FUNC DefFunc,
5063         IN ULONG InitState,
5064         IN ULONG Base)
5065 {
5066         ULONG i, j;
5067
5068         // set number of states and messages
5069         S->NrState = StNr;
5070         S->NrMsg   = MsgNr;
5071         S->Base    = Base;
5072
5073         S->TransFunc  = Trans;
5074
5075         // init all state transition to default function
5076         for (i = 0; i < StNr; i++)
5077         {
5078                 for (j = 0; j < MsgNr; j++)
5079                 {
5080                         S->TransFunc[i * MsgNr + j] = DefFunc;
5081                 }
5082         }
5083
5084         // set the starting state
5085         S->CurrState = InitState;
5086 }
5087
5088 /*! \brief This function fills in the function pointer into the cell in the state machine
5089  *      \param *S       pointer to the state machine
5090  *      \param St       state
5091  *      \param Msg      incoming message
5092  *      \param f        the function to be executed when (state, message) combination occurs at the state machine
5093  *      \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
5094  *      \post
5095
5096  IRQL = PASSIVE_LEVEL
5097
5098  */
5099 VOID StateMachineSetAction(
5100         IN STATE_MACHINE *S,
5101         IN ULONG St,
5102         IN ULONG Msg,
5103         IN STATE_MACHINE_FUNC Func)
5104 {
5105         ULONG MsgIdx;
5106
5107         MsgIdx = Msg - S->Base;
5108
5109         if (St < S->NrState && MsgIdx < S->NrMsg)
5110         {
5111                 // boundary checking before setting the action
5112                 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5113         }
5114 }
5115
5116 /*! \brief       This function does the state transition
5117  *      \param   *Adapter the NIC adapter pointer
5118  *      \param   *S       the state machine
5119  *      \param   *Elem    the message to be executed
5120  *      \return   None
5121
5122  IRQL = DISPATCH_LEVEL
5123
5124  */
5125 VOID StateMachinePerformAction(
5126         IN      PRTMP_ADAPTER   pAd,
5127         IN STATE_MACHINE *S,
5128         IN MLME_QUEUE_ELEM *Elem)
5129 {
5130         (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5131 }
5132
5133 /*
5134         ==========================================================================
5135         Description:
5136                 The drop function, when machine executes this, the message is simply
5137                 ignored. This function does nothing, the message is freed in
5138                 StateMachinePerformAction()
5139         ==========================================================================
5140  */
5141 VOID Drop(
5142         IN PRTMP_ADAPTER pAd,
5143         IN MLME_QUEUE_ELEM *Elem)
5144 {
5145 }
5146
5147 // ===========================================================================================
5148 // lfsr.c
5149 // ===========================================================================================
5150
5151 /*
5152         ==========================================================================
5153         Description:
5154
5155         IRQL = PASSIVE_LEVEL
5156
5157         ==========================================================================
5158  */
5159 VOID LfsrInit(
5160         IN PRTMP_ADAPTER pAd,
5161         IN ULONG Seed)
5162 {
5163         if (Seed == 0)
5164                 pAd->Mlme.ShiftReg = 1;
5165         else
5166                 pAd->Mlme.ShiftReg = Seed;
5167 }
5168
5169 /*
5170         ==========================================================================
5171         Description:
5172         ==========================================================================
5173  */
5174 UCHAR RandomByte(
5175         IN PRTMP_ADAPTER pAd)
5176 {
5177         ULONG i;
5178         UCHAR R, Result;
5179
5180         R = 0;
5181
5182         if (pAd->Mlme.ShiftReg == 0)
5183         NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5184
5185         for (i = 0; i < 8; i++)
5186         {
5187                 if (pAd->Mlme.ShiftReg & 0x00000001)
5188                 {
5189                         pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5190                         Result = 1;
5191                 }
5192                 else
5193                 {
5194                         pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5195                         Result = 0;
5196                 }
5197                 R = (R << 1) | Result;
5198         }
5199
5200         return R;
5201 }
5202
5203 VOID AsicUpdateAutoFallBackTable(
5204         IN      PRTMP_ADAPTER   pAd,
5205         IN      PUCHAR                  pRateTable)
5206 {
5207         UCHAR                                   i;
5208         HT_FBK_CFG0_STRUC               HtCfg0;
5209         HT_FBK_CFG1_STRUC               HtCfg1;
5210         LG_FBK_CFG0_STRUC               LgCfg0;
5211         LG_FBK_CFG1_STRUC               LgCfg1;
5212         PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate;
5213
5214         // set to initial value
5215         HtCfg0.word = 0x65432100;
5216         HtCfg1.word = 0xedcba988;
5217         LgCfg0.word = 0xedcba988;
5218         LgCfg1.word = 0x00002100;
5219
5220         pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5221         for (i = 1; i < *((PUCHAR) pRateTable); i++)
5222         {
5223                 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5224                 switch (pCurrTxRate->Mode)
5225                 {
5226                         case 0:         //CCK
5227                                 break;
5228                         case 1:         //OFDM
5229                                 {
5230                                         switch(pCurrTxRate->CurrMCS)
5231                                         {
5232                                                 case 0:
5233                                                         LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5234                                                         break;
5235                                                 case 1:
5236                                                         LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5237                                                         break;
5238                                                 case 2:
5239                                                         LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5240                                                         break;
5241                                                 case 3:
5242                                                         LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5243                                                         break;
5244                                                 case 4:
5245                                                         LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5246                                                         break;
5247                                                 case 5:
5248                                                         LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5249                                                         break;
5250                                                 case 6:
5251                                                         LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5252                                                         break;
5253                                                 case 7:
5254                                                         LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5255                                                         break;
5256                                         }
5257                                 }
5258                                 break;
5259                         case 2:         //HT-MIX
5260                         case 3:         //HT-GF
5261                                 {
5262                                         if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5263                                         {
5264                                                 switch(pCurrTxRate->CurrMCS)
5265                                                 {
5266                                                         case 0:
5267                                                                 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5268                                                                 break;
5269                                                         case 1:
5270                                                                 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5271                                                                 break;
5272                                                         case 2:
5273                                                                 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5274                                                                 break;
5275                                                         case 3:
5276                                                                 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5277                                                                 break;
5278                                                         case 4:
5279                                                                 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5280                                                                 break;
5281                                                         case 5:
5282                                                                 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5283                                                                 break;
5284                                                         case 6:
5285                                                                 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5286                                                                 break;
5287                                                         case 7:
5288                                                                 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5289                                                                 break;
5290                                                         case 8:
5291                                                                 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5292                                                                 break;
5293                                                         case 9:
5294                                                                 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5295                                                                 break;
5296                                                         case 10:
5297                                                                 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5298                                                                 break;
5299                                                         case 11:
5300                                                                 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5301                                                                 break;
5302                                                         case 12:
5303                                                                 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5304                                                                 break;
5305                                                         case 13:
5306                                                                 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5307                                                                 break;
5308                                                         case 14:
5309                                                                 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5310                                                                 break;
5311                                                         case 15:
5312                                                                 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5313                                                                 break;
5314                                                         default:
5315                                                                 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5316                                                 }
5317                                         }
5318                                 }
5319                                 break;
5320                 }
5321
5322                 pNextTxRate = pCurrTxRate;
5323         }
5324
5325         RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5326         RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5327         RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5328         RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5329 }
5330
5331 /*
5332         ========================================================================
5333
5334         Routine Description:
5335                 Set MAC register value according operation mode.
5336                 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5337                 If MM or GF mask is not set, those passing argument doesn't not take effect.
5338
5339                 Operation mode meaning:
5340                 = 0 : Pure HT, no preotection.
5341                 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5342                 = 0x10: No Transmission in 40M is protected.
5343                 = 0x11: Transmission in both 40M and 20M shall be protected
5344                 if (bNonGFExist)
5345                         we should choose not to use GF. But still set correct ASIC registers.
5346         ========================================================================
5347 */
5348 VOID    AsicUpdateProtect(
5349         IN              PRTMP_ADAPTER   pAd,
5350         IN              USHORT                  OperationMode,
5351         IN              UCHAR                   SetMask,
5352         IN              BOOLEAN                 bDisableBGProtect,
5353         IN              BOOLEAN                 bNonGFExist)
5354 {
5355         PROT_CFG_STRUC  ProtCfg, ProtCfg4;
5356         UINT32 Protect[6];
5357         USHORT                  offset;
5358         UCHAR                   i;
5359         UINT32 MacReg = 0;
5360
5361         if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5362         {
5363                 return;
5364         }
5365
5366         if (pAd->BATable.numAsOriginator)
5367         {
5368                 //
5369                 // enable the RTS/CTS to avoid channel collision
5370                 //
5371                 SetMask = ALLN_SETPROTECT;
5372                 OperationMode = 8;
5373         }
5374
5375         // Config ASIC RTS threshold register
5376         RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5377         MacReg &= 0xFF0000FF;
5378
5379         // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5380         if ((
5381                         (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5382                         (pAd->CommonCfg.bAggregationCapable == TRUE))
5383             && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5384         {
5385                         MacReg |= (0x1000 << 8);
5386         }
5387         else
5388         {
5389                         MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5390         }
5391
5392         RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5393
5394         // Initial common protection settings
5395         RTMPZeroMemory(Protect, sizeof(Protect));
5396         ProtCfg4.word = 0;
5397         ProtCfg.word = 0;
5398         ProtCfg.field.TxopAllowGF40 = 1;
5399         ProtCfg.field.TxopAllowGF20 = 1;
5400         ProtCfg.field.TxopAllowMM40 = 1;
5401         ProtCfg.field.TxopAllowMM20 = 1;
5402         ProtCfg.field.TxopAllowOfdm = 1;
5403         ProtCfg.field.TxopAllowCck = 1;
5404         ProtCfg.field.RTSThEn = 1;
5405         ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5406
5407         // update PHY mode and rate
5408         if (pAd->CommonCfg.Channel > 14)
5409                 ProtCfg.field.ProtectRate = 0x4000;
5410         ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5411
5412         // Handle legacy(B/G) protection
5413         if (bDisableBGProtect)
5414         {
5415                 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5416                 ProtCfg.field.ProtectCtrl = 0;
5417                 Protect[0] = ProtCfg.word;
5418                 Protect[1] = ProtCfg.word;
5419         }
5420         else
5421         {
5422                 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5423                 ProtCfg.field.ProtectCtrl = 0;                  // CCK do not need to be protected
5424                 Protect[0] = ProtCfg.word;
5425                 ProtCfg.field.ProtectCtrl = ASIC_CTS;   // OFDM needs using CCK to protect
5426                 Protect[1] = ProtCfg.word;
5427         }
5428
5429         // Decide HT frame protection.
5430         if ((SetMask & ALLN_SETPROTECT) != 0)
5431         {
5432                 switch(OperationMode)
5433                 {
5434                         case 0x0:
5435                                 // NO PROTECT
5436                                 // 1.All STAs in the BSS are 20/40 MHz HT
5437                                 // 2. in ai 20/40MHz BSS
5438                                 // 3. all STAs are 20MHz in a 20MHz BSS
5439                                 // Pure HT. no protection.
5440
5441                                 // MM20_PROT_CFG
5442                                 //      Reserved (31:27)
5443                                 //      PROT_TXOP(25:20) -- 010111
5444                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5445                                 //  PROT_CTRL(17:16) -- 00 (None)
5446                                 //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
5447                                 Protect[2] = 0x01744004;
5448
5449                                 // MM40_PROT_CFG
5450                                 //      Reserved (31:27)
5451                                 //      PROT_TXOP(25:20) -- 111111
5452                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5453                                 //  PROT_CTRL(17:16) -- 00 (None)
5454                                 //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
5455                                 Protect[3] = 0x03f44084;
5456
5457                                 // CF20_PROT_CFG
5458                                 //      Reserved (31:27)
5459                                 //      PROT_TXOP(25:20) -- 010111
5460                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5461                                 //  PROT_CTRL(17:16) -- 00 (None)
5462                                 //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
5463                                 Protect[4] = 0x01744004;
5464
5465                                 // CF40_PROT_CFG
5466                                 //      Reserved (31:27)
5467                                 //      PROT_TXOP(25:20) -- 111111
5468                                 //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5469                                 //  PROT_CTRL(17:16) -- 00 (None)
5470                                 //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
5471                                 Protect[5] = 0x03f44084;
5472
5473                                 if (bNonGFExist)
5474                                 {
5475                                         // PROT_NAV(19:18)  -- 01 (Short NAV protectiion)
5476                                         // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5477                                         Protect[4] = 0x01754004;
5478                                         Protect[5] = 0x03f54084;
5479                                 }
5480                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5481                                 break;
5482
5483                         case 1:
5484                                 // This is "HT non-member protection mode."
5485                                 // If there may be non-HT STAs my BSS
5486                                 ProtCfg.word = 0x01744004;      // PROT_CTRL(17:16) : 0 (None)
5487                                 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5488                                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5489                                 {
5490                                         ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
5491                                         ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5492                                 }
5493                                 //Assign Protection method for 20&40 MHz packets
5494                                 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5495                                 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5496                                 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5497                                 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5498                                 Protect[2] = ProtCfg.word;
5499                                 Protect[3] = ProtCfg4.word;
5500                                 Protect[4] = ProtCfg.word;
5501                                 Protect[5] = ProtCfg4.word;
5502                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5503                                 break;
5504
5505                         case 2:
5506                                 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5507                                 ProtCfg.word = 0x01744004;  // PROT_CTRL(17:16) : 0 (None)
5508                                 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5509
5510                                 //Assign Protection method for 40MHz packets
5511                                 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5512                                 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5513                                 Protect[2] = ProtCfg.word;
5514                                 Protect[3] = ProtCfg4.word;
5515                                 if (bNonGFExist)
5516                                 {
5517                                         ProtCfg.field.ProtectCtrl = ASIC_RTS;
5518                                         ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5519                                 }
5520                                 Protect[4] = ProtCfg.word;
5521                                 Protect[5] = ProtCfg4.word;
5522
5523                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5524                                 break;
5525
5526                         case 3:
5527                                 // HT mixed mode.        PROTECT ALL!
5528                                 // Assign Rate
5529                                 ProtCfg.word = 0x01744004;      //duplicaet legacy 24M. BW set 1.
5530                                 ProtCfg4.word = 0x03f44084;
5531                                 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5532                                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5533                                 {
5534                                         ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
5535                                         ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5536                                 }
5537                                 //Assign Protection method for 20&40 MHz packets
5538                                 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5539                                 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5540                                 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5541                                 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5542                                 Protect[2] = ProtCfg.word;
5543                                 Protect[3] = ProtCfg4.word;
5544                                 Protect[4] = ProtCfg.word;
5545                                 Protect[5] = ProtCfg4.word;
5546                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5547                                 break;
5548
5549                         case 8:
5550                                 // Special on for Atheros problem n chip.
5551                                 Protect[2] = 0x01754004;
5552                                 Protect[3] = 0x03f54084;
5553                                 Protect[4] = 0x01754004;
5554                                 Protect[5] = 0x03f54084;
5555                                 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5556                                 break;
5557                 }
5558         }
5559
5560         offset = CCK_PROT_CFG;
5561         for (i = 0;i < 6;i++)
5562         {
5563                 if ((SetMask & (1<< i)))
5564                 {
5565                         RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5566                 }
5567         }
5568 }
5569
5570 #ifdef RT30xx
5571 // add by johnli, RF power sequence setup
5572 /*
5573         ==========================================================================
5574         Description:
5575
5576         Load RF normal operation-mode setup
5577
5578         ==========================================================================
5579  */
5580 VOID RT30xxLoadRFNormalModeSetup(
5581         IN PRTMP_ADAPTER        pAd)
5582 {
5583         UCHAR RFValue;
5584
5585         // 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
5586         RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5587         RFValue = (RFValue & (~0x0C)) | 0x31;
5588         RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5589
5590         // TX_LO2_en, RF R15 register Bit 3 to 0
5591         RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5592         RFValue &= (~0x08);
5593         RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5594
5595         // TX_LO1_en, RF R17 register Bit 3 to 0
5596         RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5597         RFValue &= (~0x08);
5598         // to fix rx long range issue
5599         if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5600         {
5601                 RFValue |= 0x20;
5602         }
5603         RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5604
5605         // RX_LO1_en, RF R20 register Bit 3 to 0
5606         RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5607         RFValue &= (~0x08);
5608         RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5609
5610         // RX_LO2_en, RF R21 register Bit 3 to 0
5611         RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5612         RFValue &= (~0x08);
5613         RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5614
5615         // LDORF_VC, RF R27 register Bit 2 to 0
5616         RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5617         if ((pAd->MACVersion & 0xffff) < 0x0211)
5618                 RFValue = (RFValue & (~0x77)) | 0x3;
5619         else
5620                 RFValue = (RFValue & (~0x77));
5621         RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5622         /* end johnli */
5623 }
5624
5625 /*
5626         ==========================================================================
5627         Description:
5628
5629         Load RF sleep-mode setup
5630
5631         ==========================================================================
5632  */
5633 VOID RT30xxLoadRFSleepModeSetup(
5634         IN PRTMP_ADAPTER        pAd)
5635 {
5636         UCHAR RFValue;
5637         UINT32 MACValue;
5638
5639         // RF_BLOCK_en. RF R1 register Bit 0 to 0
5640         RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5641         RFValue &= (~0x01);
5642         RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5643
5644         // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5645         RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5646         RFValue &= (~0x30);
5647         RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5648
5649         // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5650         RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5651         RFValue &= (~0x0E);
5652         RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5653
5654         // RX_CTB_en, RF R21 register Bit 7 to 0
5655         RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5656         RFValue &= (~0x80);
5657         RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5658
5659         // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5660         RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5661         RFValue |= 0x77;
5662         RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5663
5664         RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5665         MACValue |= 0x1D000000;
5666         RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5667 }
5668
5669 /*
5670         ==========================================================================
5671         Description:
5672
5673         Reverse RF sleep-mode setup
5674
5675         ==========================================================================
5676  */
5677 VOID RT30xxReverseRFSleepModeSetup(
5678         IN PRTMP_ADAPTER        pAd)
5679 {
5680         UCHAR RFValue;
5681         UINT32 MACValue;
5682
5683         // RF_BLOCK_en, RF R1 register Bit 0 to 1
5684         RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5685         RFValue |= 0x01;
5686         RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5687
5688         // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5689         RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5690         RFValue |= 0x30;
5691         RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5692
5693         // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5694         RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5695         RFValue |= 0x0E;
5696         RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5697
5698         // RX_CTB_en, RF R21 register Bit 7 to 1
5699         RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5700         RFValue |= 0x80;
5701         RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5702
5703         // LDORF_VC, RF R27 register Bit 2 to 0
5704         RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5705         if ((pAd->MACVersion & 0xffff) < 0x0211)
5706                 RFValue = (RFValue & (~0x77)) | 0x3;
5707         else
5708                 RFValue = (RFValue & (~0x77));
5709         RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5710
5711         // RT3071 version E has fixed this issue
5712         if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5713         {
5714                 // patch tx EVM issue temporarily
5715                 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5716                 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5717                 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5718         }
5719         else
5720         {
5721                 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5722                 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5723                 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5724         }
5725 }
5726 // end johnli
5727 #endif // RT30xx //
5728
5729 /*
5730         ==========================================================================
5731         Description:
5732
5733         IRQL = PASSIVE_LEVEL
5734         IRQL = DISPATCH_LEVEL
5735
5736         ==========================================================================
5737  */
5738 VOID AsicSwitchChannel(
5739                                           IN PRTMP_ADAPTER pAd,
5740         IN      UCHAR                   Channel,
5741         IN      BOOLEAN                 bScan)
5742 {
5743         ULONG                   R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5744         CHAR    TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5745         UCHAR   index;
5746         UINT32  Value = 0; //BbpReg, Value;
5747         RTMP_RF_REGS *RFRegTable;
5748
5749         // Search Tx power value
5750         // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5751         // in ChannelList, so use TxPower array instead.
5752         //
5753         for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5754         {
5755                 if (Channel == pAd->TxPower[index].Channel)
5756         {
5757                         TxPwer = pAd->TxPower[index].Power;
5758                         TxPwer2 = pAd->TxPower[index].Power2;
5759                         break;
5760                 }
5761         }
5762
5763         if (index == MAX_NUM_OF_CHANNELS)
5764                 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5765
5766 #ifdef RT2870
5767         // The RF programming sequence is difference between 3xxx and 2xxx
5768         if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && (
5769 #ifdef RT30xx
5770              (pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) ||
5771 #endif
5772              (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5773         {
5774                 /* modify by WY for Read RF Reg. error */
5775                 UCHAR RFValue;
5776
5777                 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5778                 {
5779                         if (Channel == FreqItems3020[index].Channel)
5780                         {
5781                                 // Programming channel parameters
5782                                 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5783                                 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5784
5785                                 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5786                                 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5787                                 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5788
5789                                 // Set Tx0 Power
5790                                 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5791                                 RFValue = (RFValue & 0xE0) | TxPwer;
5792                                 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5793
5794 #ifdef RT30xx
5795                                 // Set Tx1 Power
5796                                 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5797                                 RFValue = (RFValue & 0xE0) | TxPwer2;
5798                                 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5799
5800                                 // Tx/Rx Stream setting
5801                                 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5802                                 //if (IS_RT3090(pAd))
5803                                 //      RFValue |= 0x01; // Enable RF block.
5804                                 RFValue &= 0x03;        //clear bit[7~2]
5805                                 if (pAd->Antenna.field.TxPath == 1)
5806                                         RFValue |= 0xA0;
5807                                 else if (pAd->Antenna.field.TxPath == 2)
5808                                         RFValue |= 0x80;
5809                                 if (pAd->Antenna.field.RxPath == 1)
5810                                         RFValue |= 0x50;
5811                                 else if (pAd->Antenna.field.RxPath == 2)
5812                                         RFValue |= 0x40;
5813                                 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5814 #endif
5815
5816                                 // Set RF offset
5817                                 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5818                                 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5819                                 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5820
5821                                 // Set BW
5822                                 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5823                                 {
5824                                         RFValue = pAd->Mlme.CaliBW40RfR24;
5825                                         //DISABLE_11N_CHECK(pAd);
5826                                 }
5827                                 else
5828                                 {
5829                                         RFValue = pAd->Mlme.CaliBW20RfR24;
5830                                 }
5831                                 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5832 #ifdef RT30xx
5833                                 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5834 #endif
5835                                 // Enable RF tuning
5836                                 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5837                                 RFValue = RFValue | 0x1;
5838                                 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5839
5840                                 // latch channel for future usage.
5841                                 pAd->LatchRfRegs.Channel = Channel;
5842
5843 #ifdef RT30xx
5844                                 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5845                                         Channel,
5846                                         pAd->RfIcType,
5847                                         TxPwer,
5848                                         TxPwer2,
5849                                         pAd->Antenna.field.TxPath,
5850                                         FreqItems3020[index].N,
5851                                         FreqItems3020[index].K,
5852                                         FreqItems3020[index].R));
5853 #endif
5854
5855                                 break;
5856                         }
5857                 }
5858
5859                 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5860                         Channel,
5861                         pAd->RfIcType,
5862                         TxPwer,
5863                         TxPwer2,
5864                         pAd->Antenna.field.TxPath,
5865                         FreqItems3020[index].N,
5866                         FreqItems3020[index].K,
5867                         FreqItems3020[index].R));
5868         }
5869         else
5870 #endif // RT2870 //
5871         {
5872                 RFRegTable = RF2850RegTable;
5873
5874                 switch (pAd->RfIcType)
5875                 {
5876                         case RFIC_2820:
5877                         case RFIC_2850:
5878                         case RFIC_2720:
5879                         case RFIC_2750:
5880
5881                         for (index = 0; index < NUM_OF_2850_CHNL; index++)
5882                         {
5883                                 if (Channel == RFRegTable[index].Channel)
5884                                 {
5885                                         R2 = RFRegTable[index].R2;
5886                                         if (pAd->Antenna.field.TxPath == 1)
5887                                         {
5888                                                 R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
5889                                         }
5890
5891                                         if (pAd->Antenna.field.RxPath == 2)
5892                                         {
5893                                                 R2 |= 0x40;     // write 1 to off Rxpath.
5894                                         }
5895                                         else if (pAd->Antenna.field.RxPath == 1)
5896                                         {
5897                                                 R2 |= 0x20040;  // write 1 to off RxPath
5898                                         }
5899
5900                                         if (Channel > 14)
5901                                         {
5902                                                 // initialize R3, R4
5903                                                 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5904                                                 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5905
5906                                                 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5907                                                 // R3
5908                                                 if ((TxPwer >= -7) && (TxPwer < 0))
5909                                                 {
5910                                                         TxPwer = (7+TxPwer);
5911                                                         TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5912                                                         R3 |= (TxPwer << 10);
5913                                                         DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5914                                                 }
5915                                                 else
5916                                                 {
5917                                                         TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5918                                                         R3 |= (TxPwer << 10) | (1 << 9);
5919                                                 }
5920
5921                                                 // R4
5922                                                 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5923                                                 {
5924                                                         TxPwer2 = (7+TxPwer2);
5925                                                         TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5926                                                         R4 |= (TxPwer2 << 7);
5927                                                         DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5928                                                 }
5929                                                 else
5930                                                 {
5931                                                         TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5932                                                         R4 |= (TxPwer2 << 7) | (1 << 6);
5933                                                 }
5934                                         }
5935                                         else
5936                                         {
5937                                                 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5938                                         R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5939                                         }
5940
5941                                         // Based on BBP current mode before changing RF channel.
5942                                         if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5943                                         {
5944                                                 R4 |=0x200000;
5945                                         }
5946
5947                                         // Update variables
5948                                         pAd->LatchRfRegs.Channel = Channel;
5949                                         pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5950                                         pAd->LatchRfRegs.R2 = R2;
5951                                         pAd->LatchRfRegs.R3 = R3;
5952                                         pAd->LatchRfRegs.R4 = R4;
5953
5954                                         // Set RF value 1's set R3[bit2] = [0]
5955                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5956                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5957                                         RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5958                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5959
5960                                         RTMPusecDelay(200);
5961
5962                                         // Set RF value 2's set R3[bit2] = [1]
5963                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5964                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5965                                         RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5966                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5967
5968                                         RTMPusecDelay(200);
5969
5970                                         // Set RF value 3's set R3[bit2] = [0]
5971                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5972                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5973                                         RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5974                                         RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5975
5976                                         break;
5977                                 }
5978                         }
5979                         break;
5980
5981                         default:
5982                         break;
5983                 }
5984         }
5985
5986         // Change BBP setting during siwtch from a->g, g->a
5987         if (Channel <= 14)
5988         {
5989             ULONG       TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5990
5991                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5992                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5993                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5994                 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.
5995                 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5996
5997                 // Rx High power VGA offset for LNA select
5998             if (pAd->NicConfig2.field.ExternalLNAForG)
5999             {
6000                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6001                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6002             }
6003             else
6004             {
6005                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6006                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6007             }
6008
6009                 // 5G band selection PIN, bit1 and bit2 are complement
6010                 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6011                 Value &= (~0x6);
6012                 Value |= (0x04);
6013                 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6014
6015         // Turn off unused PA or LNA when only 1T or 1R
6016                 if (pAd->Antenna.field.TxPath == 1)
6017                 {
6018                         TxPinCfg &= 0xFFFFFFF3;
6019                 }
6020                 if (pAd->Antenna.field.RxPath == 1)
6021                 {
6022                         TxPinCfg &= 0xFFFFF3FF;
6023                 }
6024
6025                 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6026         }
6027         else
6028         {
6029             ULONG       TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6030
6031                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6032                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6033                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6034                 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.
6035                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6036
6037                 // Rx High power VGA offset for LNA select
6038                 if (pAd->NicConfig2.field.ExternalLNAForA)
6039                 {
6040                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6041                 }
6042                 else
6043                 {
6044                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6045                 }
6046
6047                 // 5G band selection PIN, bit1 and bit2 are complement
6048                 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6049                 Value &= (~0x6);
6050                 Value |= (0x02);
6051                 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6052
6053         // Turn off unused PA or LNA when only 1T or 1R
6054                 if (pAd->Antenna.field.TxPath == 1)
6055                 {
6056                         TxPinCfg &= 0xFFFFFFF3;
6057         }
6058                 if (pAd->Antenna.field.RxPath == 1)
6059                 {
6060                         TxPinCfg &= 0xFFFFF3FF;
6061         }
6062
6063                 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6064         }
6065
6066     // R66 should be set according to Channel and use 20MHz when scanning
6067         //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6068         if (bScan)
6069                 RTMPSetAGCInitValue(pAd, BW_20);
6070         else
6071                 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6072
6073         //
6074         // On 11A, We should delay and wait RF/BBP to be stable
6075         // and the appropriate time should be 1000 micro seconds
6076         // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6077         //
6078         RTMPusecDelay(1000);
6079
6080         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",
6081                                                           Channel,
6082                                                           pAd->RfIcType,
6083                                                           (R3 & 0x00003e00) >> 9,
6084                                                           (R4 & 0x000007c0) >> 6,
6085                                                           pAd->Antenna.field.TxPath,
6086                                                           pAd->LatchRfRegs.R1,
6087                                                           pAd->LatchRfRegs.R2,
6088                                                           pAd->LatchRfRegs.R3,
6089                                                           pAd->LatchRfRegs.R4));
6090 }
6091
6092 /*
6093         ==========================================================================
6094         Description:
6095                 This function is required for 2421 only, and should not be used during
6096                 site survey. It's only required after NIC decided to stay at a channel
6097                 for a longer period.
6098                 When this function is called, it's always after AsicSwitchChannel().
6099
6100         IRQL = PASSIVE_LEVEL
6101         IRQL = DISPATCH_LEVEL
6102
6103         ==========================================================================
6104  */
6105 VOID AsicLockChannel(
6106         IN PRTMP_ADAPTER pAd,
6107         IN UCHAR Channel)
6108 {
6109 }
6110
6111 /*
6112         ==========================================================================
6113         Description:
6114
6115         IRQL = PASSIVE_LEVEL
6116         IRQL = DISPATCH_LEVEL
6117
6118         ==========================================================================
6119  */
6120 VOID    AsicAntennaSelect(
6121         IN      PRTMP_ADAPTER   pAd,
6122         IN      UCHAR                   Channel)
6123 {
6124 #ifdef RT30xx
6125                         if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6126                         {
6127                                 // patch for AsicSetRxAnt failed
6128                                 pAd->RxAnt.EvaluatePeriod = 0;
6129
6130                                 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6131                                 // valid indication of the distance between this AP and its clients.
6132                                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6133                                 {
6134                                         SHORT   realavgrssi1;
6135
6136                                         // if no traffic then reset average rssi to trigger evaluation
6137                                         if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6138                                         {
6139                                                 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6140                                                 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6141                                                 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6142                                         }
6143
6144                                         pAd->StaCfg.NumOfAvgRssiSample = 0;
6145                                         realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6146
6147                                         DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6148
6149                                         // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6150                                         if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6151                                         {
6152                                                 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6153                                                 AsicEvaluateRxAnt(pAd);
6154                                         }
6155                                 }
6156                                 else
6157                                 {
6158                                         // if not connected, always switch antenna to try to connect
6159                                         UCHAR   temp;
6160
6161                                         temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6162                                         pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6163                                         pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6164
6165                                         DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6166
6167                                         AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6168                                 }
6169                         }
6170 #endif /* RT30xx */
6171 }
6172
6173 /*
6174         ========================================================================
6175
6176         Routine Description:
6177                 Antenna miscellaneous setting.
6178
6179         Arguments:
6180                 pAd                                             Pointer to our adapter
6181                 BandState                               Indicate current Band State.
6182
6183         Return Value:
6184                 None
6185
6186         IRQL <= DISPATCH_LEVEL
6187
6188         Note:
6189                 1.) Frame End type control
6190                         only valid for G only (RF_2527 & RF_2529)
6191                         0: means DPDT, set BBP R4 bit 5 to 1
6192                         1: means SPDT, set BBP R4 bit 5 to 0
6193
6194
6195         ========================================================================
6196 */
6197 VOID    AsicAntennaSetting(
6198         IN      PRTMP_ADAPTER   pAd,
6199         IN      ABGBAND_STATE   BandState)
6200 {
6201 }
6202
6203 VOID AsicRfTuningExec(
6204         IN PVOID SystemSpecific1,
6205         IN PVOID FunctionContext,
6206         IN PVOID SystemSpecific2,
6207         IN PVOID SystemSpecific3)
6208 {
6209 }
6210
6211 /*
6212         ==========================================================================
6213         Description:
6214                 Gives CCK TX rate 2 more dB TX power.
6215                 This routine works only in LINK UP in INFRASTRUCTURE mode.
6216
6217                 calculate desired Tx power in RF R3.Tx0~5,      should consider -
6218                 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6219                 1. TxPowerPercentage
6220                 2. auto calibration based on TSSI feedback
6221                 3. extra 2 db for CCK
6222                 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6223
6224         NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6225                 it should be called AFTER MlmeDynamicTxRatSwitching()
6226         ==========================================================================
6227  */
6228 VOID AsicAdjustTxPower(
6229         IN PRTMP_ADAPTER pAd)
6230 {
6231         INT                     i, j;
6232         CHAR            DeltaPwr = 0;
6233         BOOLEAN         bAutoTxAgc = FALSE;
6234         UCHAR           TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6235         UCHAR           BbpR1 = 0, BbpR49 = 0, idx;
6236         PCHAR           pTxAgcCompensate;
6237         ULONG           TxPwr[5];
6238         CHAR            Value;
6239
6240 #ifdef RT2860
6241         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6242                 || (pAd->bPCIclkOff == TRUE)
6243                 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6244                 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6245                 return;
6246 #endif
6247
6248         if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6249         {
6250                 if (pAd->CommonCfg.CentralChannel > 14)
6251                 {
6252                         TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6253                         TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6254                         TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6255                         TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6256                         TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6257                 }
6258                 else
6259                 {
6260                         TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6261                         TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6262                         TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6263                         TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6264                         TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6265                 }
6266         }
6267         else
6268         {
6269                 if (pAd->CommonCfg.Channel > 14)
6270                 {
6271                         TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6272                         TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6273                         TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6274                         TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6275                         TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6276                 }
6277                 else
6278                 {
6279                         TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6280                         TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6281                         TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6282                         TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6283                         TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6284                 }
6285         }
6286
6287         // TX power compensation for temperature variation based on TSSI. try every 4 second
6288         if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6289         {
6290                 if (pAd->CommonCfg.Channel <= 14)
6291                 {
6292                         /* bg channel */
6293                         bAutoTxAgc         = pAd->bAutoTxAgcG;
6294                         TssiRef            = pAd->TssiRefG;
6295                         pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6296                         pTssiPlusBoundary  = &pAd->TssiPlusBoundaryG[0];
6297                         TxAgcStep          = pAd->TxAgcStepG;
6298                         pTxAgcCompensate   = &pAd->TxAgcCompensateG;
6299                 }
6300                 else
6301                 {
6302                         /* a channel */
6303                         bAutoTxAgc         = pAd->bAutoTxAgcA;
6304                         TssiRef            = pAd->TssiRefA;
6305                         pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6306                         pTssiPlusBoundary  = &pAd->TssiPlusBoundaryA[0];
6307                         TxAgcStep          = pAd->TxAgcStepA;
6308                         pTxAgcCompensate   = &pAd->TxAgcCompensateA;
6309                 }
6310
6311                 if (bAutoTxAgc)
6312                 {
6313                         /* BbpR1 is unsigned char */
6314                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6315
6316                         /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6317                         /* compensate: +4     +3   +2   +1    0   -1   -2   -3   -4 * steps */
6318                         /* step value is defined in pAd->TxAgcStepG for tx power value */
6319
6320                         /* [4]+1+[4]   p4     p3   p2   p1   o1   m1   m2   m3   m4 */
6321                         /* ex:         0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6322                            above value are examined in mass factory production */
6323                         /*             [4]    [3]  [2]  [1]  [0]  [1]  [2]  [3]  [4] */
6324
6325                         /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6326                         /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6327                         /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6328
6329                         if (BbpR49 > pTssiMinusBoundary[1])
6330                         {
6331                                 // Reading is larger than the reference value
6332                                 // check for how large we need to decrease the Tx power
6333                                 for (idx = 1; idx < 5; idx++)
6334                                 {
6335                                         if (BbpR49 <= pTssiMinusBoundary[idx])  // Found the range
6336                                                 break;
6337                                 }
6338                                 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6339                                 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6340
6341                                 DeltaPwr += (*pTxAgcCompensate);
6342                                 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6343                                         BbpR49, TssiRef, TxAgcStep, idx-1));
6344                         }
6345                         else if (BbpR49 < pTssiPlusBoundary[1])
6346                         {
6347                                 // Reading is smaller than the reference value
6348                                 // check for how large we need to increase the Tx power
6349                                 for (idx = 1; idx < 5; idx++)
6350                                 {
6351                                         if (BbpR49 >= pTssiPlusBoundary[idx])   // Found the range
6352                                                 break;
6353                                 }
6354                                 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6355                                 *pTxAgcCompensate = TxAgcStep * (idx-1);
6356                                 DeltaPwr += (*pTxAgcCompensate);
6357                                 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6358                                         BbpR49, TssiRef, TxAgcStep, idx-1));
6359                         }
6360                         else
6361                         {
6362                                 *pTxAgcCompensate = 0;
6363                                 DBGPRINT(RT_DEBUG_TRACE, ("   Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6364                                         BbpR49, TssiRef, TxAgcStep, 0));
6365                         }
6366                 }
6367         }
6368         else
6369         {
6370                 if (pAd->CommonCfg.Channel <= 14)
6371                 {
6372                         bAutoTxAgc         = pAd->bAutoTxAgcG;
6373                         pTxAgcCompensate   = &pAd->TxAgcCompensateG;
6374                 }
6375                 else
6376                 {
6377                         bAutoTxAgc         = pAd->bAutoTxAgcA;
6378                         pTxAgcCompensate   = &pAd->TxAgcCompensateA;
6379                 }
6380
6381                 if (bAutoTxAgc)
6382                         DeltaPwr += (*pTxAgcCompensate);
6383         }
6384
6385         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6386         BbpR1 &= 0xFC;
6387
6388         /* calculate delta power based on the percentage specified from UI */
6389         // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6390         // We lower TX power here according to the percentage specified from UI
6391         if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff)       // AUTO TX POWER control
6392                 ;
6393         else if (pAd->CommonCfg.TxPowerPercentage > 90)  // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6394                 ;
6395         else if (pAd->CommonCfg.TxPowerPercentage > 60)  // 61 ~ 90%, treat as 75% in terms of mW               // DeltaPwr -= 1;
6396         {
6397                 DeltaPwr -= 1;
6398         }
6399         else if (pAd->CommonCfg.TxPowerPercentage > 30)  // 31 ~ 60%, treat as 50% in terms of mW               // DeltaPwr -= 3;
6400         {
6401                 DeltaPwr -= 3;
6402         }
6403         else if (pAd->CommonCfg.TxPowerPercentage > 15)  // 16 ~ 30%, treat as 25% in terms of mW               // DeltaPwr -= 6;
6404         {
6405                 BbpR1 |= 0x01;
6406         }
6407         else if (pAd->CommonCfg.TxPowerPercentage > 9)   // 10 ~ 15%, treat as 12.5% in terms of mW             // DeltaPwr -= 9;
6408         {
6409                 BbpR1 |= 0x01;
6410                 DeltaPwr -= 3;
6411         }
6412         else                                           // 0 ~ 9 %, treat as MIN(~3%) in terms of mW             // DeltaPwr -= 12;
6413         {
6414                 BbpR1 |= 0x02;
6415         }
6416
6417         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6418
6419         /* reset different new tx power for different TX rate */
6420         for(i=0; i<5; i++)
6421         {
6422                 if (TxPwr[i] != 0xffffffff)
6423                 {
6424                         for (j=0; j<8; j++)
6425                         {
6426                                 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6427
6428                                 if ((Value + DeltaPwr) < 0)
6429                                 {
6430                                         Value = 0; /* min */
6431                                 }
6432                                 else if ((Value + DeltaPwr) > 0xF)
6433                                 {
6434                                         Value = 0xF; /* max */
6435                                 }
6436                                 else
6437                                 {
6438                                         Value += DeltaPwr; /* temperature compensation */
6439                                 }
6440
6441                                 /* fill new value to CSR offset */
6442                                 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6443                         }
6444
6445                         /* write tx power value to CSR */
6446                         /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6447                                                                                         TX power for OFDM 6M/9M
6448                                                                                         TX power for CCK5.5M/11M
6449                                                                                         TX power for CCK1M/2M */
6450                         /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6451                         RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6452                 }
6453         }
6454
6455 }
6456
6457 /*
6458         ==========================================================================
6459         Description:
6460                 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6461                 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6462                 the wakeup timer timeout. Driver has to issue a separate command to wake
6463                 PHY up.
6464
6465         IRQL = DISPATCH_LEVEL
6466
6467         ==========================================================================
6468  */
6469 VOID AsicSleepThenAutoWakeup(
6470         IN PRTMP_ADAPTER pAd,
6471         IN USHORT TbttNumToNextWakeUp)
6472 {
6473     RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6474 }
6475
6476 /*
6477         ==========================================================================
6478         Description:
6479                 AsicForceWakeup() is used whenever manual wakeup is required
6480                 AsicForceSleep() should only be used when not in INFRA BSS. When
6481                 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6482         ==========================================================================
6483  */
6484 VOID AsicForceSleep(
6485         IN PRTMP_ADAPTER pAd)
6486 {
6487
6488 }
6489
6490 /*
6491         ==========================================================================
6492         Description:
6493                 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6494                 expired.
6495
6496         IRQL = PASSIVE_LEVEL
6497         IRQL = DISPATCH_LEVEL
6498         ==========================================================================
6499  */
6500 VOID AsicForceWakeup(
6501         IN PRTMP_ADAPTER pAd,
6502 #ifdef RT2860
6503         IN UCHAR         Level)
6504 #endif
6505 #ifdef RT2870
6506         IN BOOLEAN    bFromTx)
6507 #endif
6508 {
6509     DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6510 #ifdef RT2860
6511     RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6512 #endif
6513 #ifdef RT2870
6514     RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6515 #endif
6516 }
6517
6518 /*
6519         ==========================================================================
6520         Description:
6521                 Set My BSSID
6522
6523         IRQL = DISPATCH_LEVEL
6524
6525         ==========================================================================
6526  */
6527 VOID AsicSetBssid(
6528         IN PRTMP_ADAPTER pAd,
6529         IN PUCHAR pBssid)
6530 {
6531         ULONG             Addr4;
6532         DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6533                 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6534
6535         Addr4 = (ULONG)(pBssid[0])               |
6536                         (ULONG)(pBssid[1] << 8)  |
6537                         (ULONG)(pBssid[2] << 16) |
6538                         (ULONG)(pBssid[3] << 24);
6539         RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6540
6541         Addr4 = 0;
6542         // always one BSSID in STA mode
6543         Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6544
6545         RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6546 }
6547
6548 VOID AsicSetMcastWC(
6549         IN PRTMP_ADAPTER pAd)
6550 {
6551         MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6552         USHORT          offset;
6553
6554         pEntry->Sst        = SST_ASSOC;
6555         pEntry->Aid        = MCAST_WCID;        // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6556         pEntry->PsMode     = PWR_ACTIVE;
6557         pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6558         offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6559 }
6560
6561 /*
6562         ==========================================================================
6563         Description:
6564
6565         IRQL = DISPATCH_LEVEL
6566
6567         ==========================================================================
6568  */
6569 VOID AsicDelWcidTab(
6570         IN PRTMP_ADAPTER pAd,
6571         IN UCHAR        Wcid)
6572 {
6573         ULONG             Addr0 = 0x0, Addr1 = 0x0;
6574         ULONG           offset;
6575
6576         DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6577         offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6578         RTMP_IO_WRITE32(pAd, offset, Addr0);
6579         offset += 4;
6580         RTMP_IO_WRITE32(pAd, offset, Addr1);
6581 }
6582
6583 /*
6584         ==========================================================================
6585         Description:
6586
6587         IRQL = DISPATCH_LEVEL
6588
6589         ==========================================================================
6590  */
6591 VOID AsicEnableRDG(
6592         IN PRTMP_ADAPTER pAd)
6593 {
6594         TX_LINK_CFG_STRUC       TxLinkCfg;
6595         UINT32                          Data = 0;
6596
6597         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6598         TxLinkCfg.field.TxRDGEn = 1;
6599         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6600
6601         RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6602         Data  &= 0xFFFFFF00;
6603         Data  |= 0x80;
6604         RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6605
6606         //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6607 }
6608
6609 /*
6610         ==========================================================================
6611         Description:
6612
6613         IRQL = DISPATCH_LEVEL
6614
6615         ==========================================================================
6616  */
6617 VOID AsicDisableRDG(
6618         IN PRTMP_ADAPTER pAd)
6619 {
6620         TX_LINK_CFG_STRUC       TxLinkCfg;
6621         UINT32                          Data = 0;
6622
6623
6624         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6625         TxLinkCfg.field.TxRDGEn = 0;
6626         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6627
6628         RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6629
6630         Data  &= 0xFFFFFF00;
6631         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6632                 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6633         )
6634         {
6635                 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6636                 if (pAd->CommonCfg.bEnableTxBurst)
6637                         Data |= 0x20;
6638         }
6639         RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6640 }
6641
6642 /*
6643         ==========================================================================
6644         Description:
6645
6646         IRQL = PASSIVE_LEVEL
6647         IRQL = DISPATCH_LEVEL
6648
6649         ==========================================================================
6650  */
6651 VOID AsicDisableSync(
6652         IN PRTMP_ADAPTER pAd)
6653 {
6654         BCN_TIME_CFG_STRUC csr;
6655
6656         DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6657
6658         // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6659         //                        that NIC will never wakes up because TSF stops and no more
6660         //                        TBTT interrupts
6661         pAd->TbttTickCount = 0;
6662         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6663         csr.field.bBeaconGen = 0;
6664         csr.field.bTBTTEnable = 0;
6665         csr.field.TsfSyncMode = 0;
6666         csr.field.bTsfTicking = 0;
6667         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6668
6669 }
6670
6671 /*
6672         ==========================================================================
6673         Description:
6674
6675         IRQL = DISPATCH_LEVEL
6676
6677         ==========================================================================
6678  */
6679 VOID AsicEnableBssSync(
6680         IN PRTMP_ADAPTER pAd)
6681 {
6682         BCN_TIME_CFG_STRUC csr;
6683
6684         DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6685
6686         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6687
6688         {
6689                 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6690                 csr.field.bTsfTicking = 1;
6691                 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6692                 csr.field.bBeaconGen  = 0; // do NOT generate BEACON
6693                 csr.field.bTBTTEnable = 1;
6694         }
6695
6696         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6697 }
6698
6699 /*
6700         ==========================================================================
6701         Description:
6702         Note:
6703                 BEACON frame in shared memory should be built ok before this routine
6704                 can be called. Otherwise, a garbage frame maybe transmitted out every
6705                 Beacon period.
6706
6707         IRQL = DISPATCH_LEVEL
6708
6709         ==========================================================================
6710  */
6711 VOID AsicEnableIbssSync(
6712         IN PRTMP_ADAPTER pAd)
6713 {
6714         BCN_TIME_CFG_STRUC csr9;
6715         PUCHAR                  ptr;
6716         UINT i;
6717
6718         DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6719
6720         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6721         csr9.field.bBeaconGen = 0;
6722         csr9.field.bTBTTEnable = 0;
6723         csr9.field.bTsfTicking = 0;
6724         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6725
6726 #ifdef RT2860
6727         // move BEACON TXD and frame content to on-chip memory
6728         ptr = (PUCHAR)&pAd->BeaconTxWI;
6729         for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
6730         {
6731                 UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6732                 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6733                 ptr += 4;
6734         }
6735
6736         // start right after the 16-byte TXWI field
6737         ptr = pAd->BeaconBuf;
6738         for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6739         {
6740                 UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6741                 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6742                 ptr +=4;
6743         }
6744 #endif
6745 #ifdef RT2870
6746         // move BEACON TXD and frame content to on-chip memory
6747         ptr = (PUCHAR)&pAd->BeaconTxWI;
6748         for (i=0; i<TXWI_SIZE; i+=2)  // 16-byte TXWI field
6749         {
6750                 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6751                 ptr += 2;
6752         }
6753
6754         // start right after the 16-byte TXWI field
6755         ptr = pAd->BeaconBuf;
6756         for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6757         {
6758                 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6759                 ptr +=2;
6760         }
6761 #endif // RT2870 //
6762
6763         // start sending BEACON
6764         csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6765         csr9.field.bTsfTicking = 1;
6766         csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6767         csr9.field.bTBTTEnable = 1;
6768         csr9.field.bBeaconGen = 1;
6769         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6770 }
6771
6772 /*
6773         ==========================================================================
6774         Description:
6775
6776         IRQL = PASSIVE_LEVEL
6777         IRQL = DISPATCH_LEVEL
6778
6779         ==========================================================================
6780  */
6781 VOID AsicSetEdcaParm(
6782         IN PRTMP_ADAPTER pAd,
6783         IN PEDCA_PARM    pEdcaParm)
6784 {
6785         EDCA_AC_CFG_STRUC   Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6786         AC_TXOP_CSR0_STRUC csr0;
6787         AC_TXOP_CSR1_STRUC csr1;
6788         AIFSN_CSR_STRUC    AifsnCsr;
6789         CWMIN_CSR_STRUC    CwminCsr;
6790         CWMAX_CSR_STRUC    CwmaxCsr;
6791         int i;
6792
6793         Ac0Cfg.word = 0;
6794         Ac1Cfg.word = 0;
6795         Ac2Cfg.word = 0;
6796         Ac3Cfg.word = 0;
6797         if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6798         {
6799                 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6800                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6801                 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6802                 {
6803                         if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6804                                 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6805                 }
6806
6807                 //========================================================
6808                 //      MAC Register has a copy .
6809                 //========================================================
6810                 if( pAd->CommonCfg.bEnableTxBurst )
6811                 {
6812                         // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6813                         Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6814                 }
6815                 else
6816                         Ac0Cfg.field.AcTxop = 0;        // QID_AC_BE
6817                 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6818                 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6819                 Ac0Cfg.field.Aifsn = 2;
6820                 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6821
6822                 Ac1Cfg.field.AcTxop = 0;        // QID_AC_BK
6823                 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6824                 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6825                 Ac1Cfg.field.Aifsn = 2;
6826                 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6827
6828                 if (pAd->CommonCfg.PhyMode == PHY_11B)
6829                 {
6830                         Ac2Cfg.field.AcTxop = 192;      // AC_VI: 192*32us ~= 6ms
6831                         Ac3Cfg.field.AcTxop = 96;       // AC_VO: 96*32us  ~= 3ms
6832                 }
6833                 else
6834                 {
6835                         Ac2Cfg.field.AcTxop = 96;       // AC_VI: 96*32us ~= 3ms
6836                         Ac3Cfg.field.AcTxop = 48;       // AC_VO: 48*32us ~= 1.5ms
6837                 }
6838                 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6839                 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6840                 Ac2Cfg.field.Aifsn = 2;
6841                 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6842                 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6843                 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6844                 Ac3Cfg.field.Aifsn = 2;
6845                 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6846
6847                 //========================================================
6848                 //      DMA Register has a copy too.
6849                 //========================================================
6850                 csr0.field.Ac0Txop = 0;         // QID_AC_BE
6851                 csr0.field.Ac1Txop = 0;         // QID_AC_BK
6852                 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6853                 if (pAd->CommonCfg.PhyMode == PHY_11B)
6854                 {
6855                         csr1.field.Ac2Txop = 192;               // AC_VI: 192*32us ~= 6ms
6856                         csr1.field.Ac3Txop = 96;                // AC_VO: 96*32us  ~= 3ms
6857                 }
6858                 else
6859                 {
6860                         csr1.field.Ac2Txop = 96;                // AC_VI: 96*32us ~= 3ms
6861                         csr1.field.Ac3Txop = 48;                // AC_VO: 48*32us ~= 1.5ms
6862                 }
6863                 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6864
6865                 CwminCsr.word = 0;
6866                 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6867                 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6868                 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6869                 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6870                 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6871
6872                 CwmaxCsr.word = 0;
6873                 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6874                 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6875                 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6876                 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6877                 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6878
6879                 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6880
6881                 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6882         }
6883         else
6884         {
6885                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6886                 //========================================================
6887                 //      MAC Register has a copy.
6888                 //========================================================
6889                 //
6890                 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6891                 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6892                 //
6893                 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6894
6895                 Ac0Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BE];
6896                 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6897                 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6898                 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6899
6900                 Ac1Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BK];
6901                 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6902                 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6903                 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6904
6905                 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6906                 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6907                 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6908                 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6909
6910                 {
6911                         // Tuning for Wi-Fi WMM S06
6912                         if (pAd->CommonCfg.bWiFiTest &&
6913                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6914                                 Ac2Cfg.field.Aifsn -= 1;
6915
6916                         // Tuning for TGn Wi-Fi 5.2.32
6917                         // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6918                         if (STA_TGN_WIFI_ON(pAd) &&
6919                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6920                         {
6921                                 Ac0Cfg.field.Aifsn = 3;
6922                                 Ac2Cfg.field.AcTxop = 5;
6923                         }
6924
6925 #ifdef RT30xx
6926                         if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6927                         {
6928                                 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6929                                 Ac2Cfg.field.Aifsn = 5;
6930                         }
6931 #endif // RT30xx //
6932                 }
6933
6934                 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6935                 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6936                 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6937                 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6938
6939 //#ifdef WIFI_TEST
6940                 if (pAd->CommonCfg.bWiFiTest)
6941                 {
6942                         if (Ac3Cfg.field.AcTxop == 102)
6943                         {
6944                         Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6945                                 Ac0Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6946                         Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6947                                 Ac1Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BK];
6948                         Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6949                         } /* End of if */
6950                 }
6951 //#endif // WIFI_TEST //
6952
6953                 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6954                 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6955                 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6956                 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6957
6958
6959                 //========================================================
6960                 //      DMA Register has a copy too.
6961                 //========================================================
6962                 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6963                 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6964                 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6965
6966                 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6967                 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6968                 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6969
6970                 CwminCsr.word = 0;
6971                 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6972                 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6973                 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6974
6975                 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6976
6977                 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6978
6979                 CwmaxCsr.word = 0;
6980                 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6981                 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6982                 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6983                 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6984                 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6985
6986                 AifsnCsr.word = 0;
6987                 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6988                 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6989                 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6990
6991                 {
6992                         // Tuning for Wi-Fi WMM S06
6993                         if (pAd->CommonCfg.bWiFiTest &&
6994                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6995                                 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6996
6997                         // Tuning for TGn Wi-Fi 5.2.32
6998                         // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6999                         if (STA_TGN_WIFI_ON(pAd) &&
7000                                 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7001                         {
7002                                 AifsnCsr.field.Aifsn0 = 3;
7003                                 AifsnCsr.field.Aifsn2 = 7;
7004                         }
7005 #ifdef RT2870
7006                         if (INFRA_ON(pAd))
7007                                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7008 #endif
7009                 }
7010
7011                 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7012 #ifdef RT30xx
7013                 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7014                         AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7015 #endif // RT30xx //
7016
7017                 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7018
7019                 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7020                 if (!ADHOC_ON(pAd))
7021                 {
7022                         DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax  TXOP(us)  ACM\n", pEdcaParm->EdcaUpdateCount));
7023                         DBGPRINT(RT_DEBUG_TRACE,("     AC_BE      %2d     %2d     %2d      %4d     %d\n",
7024                                                                          pEdcaParm->Aifsn[0],
7025                                                                          pEdcaParm->Cwmin[0],
7026                                                                          pEdcaParm->Cwmax[0],
7027                                                                          pEdcaParm->Txop[0]<<5,
7028                                                                          pEdcaParm->bACM[0]));
7029                         DBGPRINT(RT_DEBUG_TRACE,("     AC_BK      %2d     %2d     %2d      %4d     %d\n",
7030                                                                          pEdcaParm->Aifsn[1],
7031                                                                          pEdcaParm->Cwmin[1],
7032                                                                          pEdcaParm->Cwmax[1],
7033                                                                          pEdcaParm->Txop[1]<<5,
7034                                                                          pEdcaParm->bACM[1]));
7035                         DBGPRINT(RT_DEBUG_TRACE,("     AC_VI      %2d     %2d     %2d      %4d     %d\n",
7036                                                                          pEdcaParm->Aifsn[2],
7037                                                                          pEdcaParm->Cwmin[2],
7038                                                                          pEdcaParm->Cwmax[2],
7039                                                                          pEdcaParm->Txop[2]<<5,
7040                                                                          pEdcaParm->bACM[2]));
7041                         DBGPRINT(RT_DEBUG_TRACE,("     AC_VO      %2d     %2d     %2d      %4d     %d\n",
7042                                                                          pEdcaParm->Aifsn[3],
7043                                                                          pEdcaParm->Cwmin[3],
7044                                                                          pEdcaParm->Cwmax[3],
7045                                                                          pEdcaParm->Txop[3]<<5,
7046                                                                          pEdcaParm->bACM[3]));
7047                 }
7048         }
7049 }
7050
7051 /*
7052         ==========================================================================
7053         Description:
7054
7055         IRQL = PASSIVE_LEVEL
7056         IRQL = DISPATCH_LEVEL
7057
7058         ==========================================================================
7059  */
7060 VOID    AsicSetSlotTime(
7061         IN PRTMP_ADAPTER pAd,
7062         IN BOOLEAN bUseShortSlotTime)
7063 {
7064         ULONG   SlotTime;
7065         UINT32  RegValue = 0;
7066
7067         if (pAd->CommonCfg.Channel > 14)
7068                 bUseShortSlotTime = TRUE;
7069
7070         if (bUseShortSlotTime)
7071                 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7072         else
7073                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7074
7075         SlotTime = (bUseShortSlotTime)? 9 : 20;
7076
7077         {
7078                 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7079                 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7080                         || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7081                         )
7082                 {
7083                         // In this case, we will think it is doing Wi-Fi test
7084                         // And we will not set to short slot when bEnableTxBurst is TRUE.
7085                 }
7086                 else if (pAd->CommonCfg.bEnableTxBurst)
7087                         SlotTime = 9;
7088         }
7089
7090         //
7091         // For some reasons, always set it to short slot time.
7092         //
7093         // ToDo: Should consider capability with 11B
7094         //
7095         if (pAd->StaCfg.BssType == BSS_ADHOC)
7096                 SlotTime = 20;
7097
7098         RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7099         RegValue = RegValue & 0xFFFFFF00;
7100
7101         RegValue |= SlotTime;
7102
7103         RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7104 }
7105
7106 /*
7107         ========================================================================
7108         Description:
7109                 Add Shared key information into ASIC.
7110                 Update shared key, TxMic and RxMic to Asic Shared key table
7111                 Update its cipherAlg to Asic Shared key Mode.
7112
7113     Return:
7114         ========================================================================
7115 */
7116 VOID AsicAddSharedKeyEntry(
7117         IN PRTMP_ADAPTER pAd,
7118         IN UCHAR                 BssIndex,
7119         IN UCHAR                 KeyIdx,
7120         IN UCHAR                 CipherAlg,
7121         IN PUCHAR                pKey,
7122         IN PUCHAR                pTxMic,
7123         IN PUCHAR                pRxMic)
7124 {
7125         ULONG offset; //, csr0;
7126         SHAREDKEY_MODE_STRUC csr1;
7127 #ifdef RT2860
7128         INT   i;
7129 #endif
7130
7131         DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7132 //============================================================================================
7133
7134         DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7135         DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7136                 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]));
7137         if (pRxMic)
7138         {
7139                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7140                         pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7141         }
7142         if (pTxMic)
7143         {
7144                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7145                         pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7146         }
7147 //============================================================================================
7148         //
7149         // fill key material - key + TX MIC + RX MIC
7150         //
7151
7152         offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7153 #ifdef RT2860
7154         for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7155         {
7156                 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7157         }
7158 #endif
7159 #ifdef RT2870
7160         RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7161 #endif
7162         offset += MAX_LEN_OF_SHARE_KEY;
7163         if (pTxMic)
7164         {
7165 #ifdef RT2860
7166                 for (i=0; i<8; i++)
7167                 {
7168                         RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7169                 }
7170 #endif
7171 #ifdef RT2870
7172                 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7173 #endif
7174         }
7175
7176         offset += 8;
7177         if (pRxMic)
7178         {
7179 #ifdef RT2860
7180                 for (i=0; i<8; i++)
7181                 {
7182                         RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7183                 }
7184 #endif
7185 #ifdef RT2870
7186                 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7187 #endif
7188         }
7189
7190
7191         //
7192         // Update cipher algorithm. WSTA always use BSS0
7193         //
7194         RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7195         DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7196         if ((BssIndex%2) == 0)
7197         {
7198                 if (KeyIdx == 0)
7199                         csr1.field.Bss0Key0CipherAlg = CipherAlg;
7200                 else if (KeyIdx == 1)
7201                         csr1.field.Bss0Key1CipherAlg = CipherAlg;
7202                 else if (KeyIdx == 2)
7203                         csr1.field.Bss0Key2CipherAlg = CipherAlg;
7204                 else
7205                         csr1.field.Bss0Key3CipherAlg = CipherAlg;
7206         }
7207         else
7208         {
7209                 if (KeyIdx == 0)
7210                         csr1.field.Bss1Key0CipherAlg = CipherAlg;
7211                 else if (KeyIdx == 1)
7212                         csr1.field.Bss1Key1CipherAlg = CipherAlg;
7213                 else if (KeyIdx == 2)
7214                         csr1.field.Bss1Key2CipherAlg = CipherAlg;
7215                 else
7216                         csr1.field.Bss1Key3CipherAlg = CipherAlg;
7217         }
7218         DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7219         RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7220
7221 }
7222
7223 //      IRQL = DISPATCH_LEVEL
7224 VOID AsicRemoveSharedKeyEntry(
7225         IN PRTMP_ADAPTER pAd,
7226         IN UCHAR                 BssIndex,
7227         IN UCHAR                 KeyIdx)
7228 {
7229         //ULONG SecCsr0;
7230         SHAREDKEY_MODE_STRUC csr1;
7231
7232         DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7233
7234         RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7235         if ((BssIndex%2) == 0)
7236         {
7237                 if (KeyIdx == 0)
7238                         csr1.field.Bss0Key0CipherAlg = 0;
7239                 else if (KeyIdx == 1)
7240                         csr1.field.Bss0Key1CipherAlg = 0;
7241                 else if (KeyIdx == 2)
7242                         csr1.field.Bss0Key2CipherAlg = 0;
7243                 else
7244                         csr1.field.Bss0Key3CipherAlg = 0;
7245         }
7246         else
7247         {
7248                 if (KeyIdx == 0)
7249                         csr1.field.Bss1Key0CipherAlg = 0;
7250                 else if (KeyIdx == 1)
7251                         csr1.field.Bss1Key1CipherAlg = 0;
7252                 else if (KeyIdx == 2)
7253                         csr1.field.Bss1Key2CipherAlg = 0;
7254                 else
7255                         csr1.field.Bss1Key3CipherAlg = 0;
7256         }
7257         DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7258         RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7259         ASSERT(BssIndex < 4);
7260         ASSERT(KeyIdx < 4);
7261
7262 }
7263
7264
7265 VOID AsicUpdateWCIDAttribute(
7266         IN PRTMP_ADAPTER pAd,
7267         IN USHORT               WCID,
7268         IN UCHAR                BssIndex,
7269         IN UCHAR        CipherAlg,
7270         IN BOOLEAN              bUsePairewiseKeyTable)
7271 {
7272         ULONG   WCIDAttri = 0, offset;
7273
7274         //
7275         // Update WCID attribute.
7276         // Only TxKey could update WCID attribute.
7277         //
7278         offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7279         WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7280         RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7281 }
7282
7283 VOID AsicUpdateWCIDIVEIV(
7284         IN PRTMP_ADAPTER pAd,
7285         IN USHORT               WCID,
7286         IN ULONG        uIV,
7287         IN ULONG        uEIV)
7288 {
7289         ULONG   offset;
7290
7291         offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7292
7293         RTMP_IO_WRITE32(pAd, offset, uIV);
7294         RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7295 }
7296
7297 VOID AsicUpdateRxWCIDTable(
7298         IN PRTMP_ADAPTER pAd,
7299         IN USHORT               WCID,
7300         IN PUCHAR        pAddr)
7301 {
7302         ULONG offset;
7303         ULONG Addr;
7304
7305         offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7306         Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7307         RTMP_IO_WRITE32(pAd, offset, Addr);
7308         Addr = pAddr[4] + (pAddr[5] << 8);
7309         RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7310 }
7311
7312
7313 /*
7314     ========================================================================
7315
7316     Routine Description:
7317         Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7318
7319     Arguments:
7320         pAd                     Pointer to our adapter
7321         WCID                    WCID Entry number.
7322         BssIndex                BSSID index, station or none multiple BSSID support
7323                                 this value should be 0.
7324         KeyIdx                  This KeyIdx will set to IV's KeyID if bTxKey enabled
7325         pCipherKey              Pointer to Cipher Key.
7326         bUsePairewiseKeyTable   TRUE means saved the key in SharedKey table,
7327                                 otherwise PairewiseKey table
7328         bTxKey                  This is the transmit key if enabled.
7329
7330     Return Value:
7331         None
7332
7333     Note:
7334         This routine will set the relative key stuff to Asic including WCID attribute,
7335         Cipher Key, Cipher algorithm and IV/EIV.
7336
7337         IV/EIV will be update if this CipherKey is the transmission key because
7338         ASIC will base on IV's KeyID value to select Cipher Key.
7339
7340         If bTxKey sets to FALSE, this is not the TX key, but it could be
7341         RX key
7342
7343         For AP mode bTxKey must be always set to TRUE.
7344     ========================================================================
7345 */
7346 VOID AsicAddKeyEntry(
7347         IN PRTMP_ADAPTER pAd,
7348         IN USHORT               WCID,
7349         IN UCHAR                BssIndex,
7350         IN UCHAR                KeyIdx,
7351         IN PCIPHER_KEY  pCipherKey,
7352         IN BOOLEAN              bUsePairewiseKeyTable,
7353         IN BOOLEAN              bTxKey)
7354 {
7355         ULONG   offset;
7356         UCHAR   IV4 = 0;
7357         PUCHAR          pKey = pCipherKey->Key;
7358         PUCHAR          pTxMic = pCipherKey->TxMic;
7359         PUCHAR          pRxMic = pCipherKey->RxMic;
7360         PUCHAR          pTxtsc = pCipherKey->TxTsc;
7361         UCHAR           CipherAlg = pCipherKey->CipherAlg;
7362         SHAREDKEY_MODE_STRUC csr1;
7363 #ifdef RT2860
7364         UCHAR           i;
7365 #endif
7366
7367         DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7368         //
7369         // 1.) decide key table offset
7370         //
7371         if (bUsePairewiseKeyTable)
7372                 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7373         else
7374                 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7375
7376         //
7377         // 2.) Set Key to Asic
7378         //
7379         //for (i = 0; i < KeyLen; i++)
7380 #ifdef RT2860
7381         for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7382         {
7383                 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7384         }
7385 #endif
7386 #ifdef RT2870
7387         RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7388 #endif
7389         offset += MAX_LEN_OF_PEER_KEY;
7390
7391         //
7392         // 3.) Set MIC key if available
7393         //
7394         if (pTxMic)
7395         {
7396 #ifdef RT2860
7397                 for (i = 0; i < 8; i++)
7398                 {
7399                         RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7400                 }
7401 #endif
7402 #ifdef RT2870
7403                 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7404 #endif
7405         }
7406         offset += LEN_TKIP_TXMICK;
7407
7408         if (pRxMic)
7409         {
7410 #ifdef RT2860
7411                 for (i = 0; i < 8; i++)
7412                 {
7413                         RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7414                 }
7415 #endif
7416 #ifdef RT2870
7417                 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7418 #endif
7419         }
7420
7421
7422         //
7423         // 4.) Modify IV/EIV if needs
7424         //     This will force Asic to use this key ID by setting IV.
7425         //
7426         if (bTxKey)
7427         {
7428 #ifdef RT2860
7429                 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7430                 //
7431                 // Write IV
7432                 //
7433                 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7434                 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7435                 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7436
7437                 IV4 = (KeyIdx << 6);
7438                 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7439                         IV4 |= 0x20;  // turn on extension bit means EIV existence
7440
7441                 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7442
7443                 //
7444                 // Write EIV
7445                 //
7446                 offset += 4;
7447                 for (i = 0; i < 4; i++)
7448                 {
7449                         RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7450                 }
7451
7452 #endif
7453 #ifdef RT2870
7454                 UINT32 tmpVal;
7455
7456                 //
7457                 // Write IV
7458                 //
7459                 IV4 = (KeyIdx << 6);
7460                 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7461                         IV4 |= 0x20;  // turn on extension bit means EIV existence
7462
7463                 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7464                 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7465
7466                 //
7467                 // Write EIV
7468                 //
7469                 offset += 4;
7470                 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7471 #endif // RT2870 //
7472                 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7473         }
7474
7475         if (!bUsePairewiseKeyTable)
7476         {
7477                 //
7478                 // Only update the shared key security mode
7479                 //
7480                 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7481                 if ((BssIndex % 2) == 0)
7482                 {
7483                         if (KeyIdx == 0)
7484                                 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7485                         else if (KeyIdx == 1)
7486                                 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7487                         else if (KeyIdx == 2)
7488                                 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7489                         else
7490                                 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7491                 }
7492                 else
7493                 {
7494                         if (KeyIdx == 0)
7495                                 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7496                         else if (KeyIdx == 1)
7497                                 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7498                         else if (KeyIdx == 2)
7499                                 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7500                         else
7501                                 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7502                 }
7503                 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7504         }
7505
7506         DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7507 }
7508
7509
7510 /*
7511         ========================================================================
7512         Description:
7513                 Add Pair-wise key material into ASIC.
7514                 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7515
7516     Return:
7517         ========================================================================
7518 */
7519 VOID AsicAddPairwiseKeyEntry(
7520         IN PRTMP_ADAPTER pAd,
7521         IN PUCHAR        pAddr,
7522         IN UCHAR                WCID,
7523         IN CIPHER_KEY            *pCipherKey)
7524 {
7525         INT i;
7526         ULONG           offset;
7527         PUCHAR           pKey = pCipherKey->Key;
7528         PUCHAR           pTxMic = pCipherKey->TxMic;
7529         PUCHAR           pRxMic = pCipherKey->RxMic;
7530 #ifdef DBG
7531         UCHAR           CipherAlg = pCipherKey->CipherAlg;
7532 #endif // DBG //
7533
7534         // EKEY
7535         offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7536 #ifdef RT2860
7537         for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7538         {
7539                 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7540         }
7541 #endif
7542 #ifdef RT2870
7543         RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7544 #endif // RT2870 //
7545         for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7546         {
7547                 UINT32 Value;
7548                 RTMP_IO_READ32(pAd, offset + i, &Value);
7549         }
7550
7551         offset += MAX_LEN_OF_PEER_KEY;
7552
7553         //  MIC KEY
7554         if (pTxMic)
7555         {
7556 #ifdef RT2860
7557                 for (i=0; i<8; i++)
7558                 {
7559                         RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7560                 }
7561 #endif
7562 #ifdef RT2870
7563                 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7564 #endif // RT2870 //
7565         }
7566         offset += 8;
7567         if (pRxMic)
7568         {
7569 #ifdef RT2860
7570                 for (i=0; i<8; i++)
7571                 {
7572                         RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7573                 }
7574 #endif
7575 #ifdef RT2870
7576                 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7577 #endif // RT2870 //
7578         }
7579
7580         DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7581         DBGPRINT(RT_DEBUG_TRACE,("      Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7582                 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]));
7583         if (pRxMic)
7584         {
7585                 DBGPRINT(RT_DEBUG_TRACE, ("     Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7586                         pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7587         }
7588         if (pTxMic)
7589         {
7590                 DBGPRINT(RT_DEBUG_TRACE, ("     Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7591                         pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7592         }
7593 }
7594 /*
7595         ========================================================================
7596         Description:
7597                 Remove Pair-wise key material from ASIC.
7598
7599     Return:
7600         ========================================================================
7601 */
7602 VOID AsicRemovePairwiseKeyEntry(
7603         IN PRTMP_ADAPTER pAd,
7604         IN UCHAR                 BssIdx,
7605         IN UCHAR                 Wcid)
7606 {
7607         ULONG           WCIDAttri;
7608         USHORT          offset;
7609
7610         // re-set the entry's WCID attribute as OPEN-NONE.
7611         offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7612         WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7613         RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7614 }
7615
7616 BOOLEAN AsicSendCommandToMcu(
7617         IN PRTMP_ADAPTER pAd,
7618         IN UCHAR                 Command,
7619         IN UCHAR                 Token,
7620         IN UCHAR                 Arg0,
7621         IN UCHAR                 Arg1)
7622 {
7623         HOST_CMD_CSR_STRUC      H2MCmd;
7624         H2M_MAILBOX_STRUC       H2MMailbox;
7625         ULONG                           i = 0;
7626
7627         do
7628         {
7629                 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7630                 if (H2MMailbox.field.Owner == 0)
7631                         break;
7632
7633                 RTMPusecDelay(2);
7634         } while(i++ < 100);
7635
7636         if (i > 100)
7637         {
7638                 {
7639 #ifdef RT2860
7640                         UINT32 Data;
7641
7642                         // Reset DMA
7643                         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7644                         Data |= 0x2;
7645                         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7646
7647                         // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7648                         // Reset DMA/CPU ring index
7649                         RTMPRingCleanUp(pAd, QID_AC_BK);
7650                         RTMPRingCleanUp(pAd, QID_AC_BE);
7651                         RTMPRingCleanUp(pAd, QID_AC_VI);
7652                         RTMPRingCleanUp(pAd, QID_AC_VO);
7653                         RTMPRingCleanUp(pAd, QID_HCCA);
7654                         RTMPRingCleanUp(pAd, QID_MGMT);
7655                         RTMPRingCleanUp(pAd, QID_RX);
7656
7657                         // Clear Reset
7658                         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7659                         Data &= 0xfffffffd;
7660                         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7661 #endif /* RT2860 */
7662                 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7663                 }
7664                 //return FALSE;
7665 #ifdef RT2870
7666                 return FALSE;
7667 #endif
7668         }
7669
7670         H2MMailbox.field.Owner    = 1;     // pass ownership to MCU
7671         H2MMailbox.field.CmdToken = Token;
7672         H2MMailbox.field.HighByte = Arg1;
7673         H2MMailbox.field.LowByte  = Arg0;
7674         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7675
7676         H2MCmd.word                       = 0;
7677         H2MCmd.field.HostCommand  = Command;
7678         RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7679
7680         if (Command != 0x80)
7681         {
7682         }
7683
7684         return TRUE;
7685 }
7686
7687 #ifdef RT2860
7688 BOOLEAN AsicCheckCommanOk(
7689         IN PRTMP_ADAPTER pAd,
7690         IN UCHAR                 Command)
7691 {
7692         UINT32  CmdStatus = 0, CID = 0, i;
7693         UINT32  ThisCIDMask = 0;
7694
7695         i = 0;
7696         do
7697         {
7698                 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7699                 // Find where the command is. Because this is randomly specified by firmware.
7700                 if ((CID & CID0MASK) == Command)
7701                 {
7702                         ThisCIDMask = CID0MASK;
7703                         break;
7704                 }
7705                 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7706                 {
7707                         ThisCIDMask = CID1MASK;
7708                         break;
7709                 }
7710                 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7711                 {
7712                         ThisCIDMask = CID2MASK;
7713                         break;
7714                 }
7715                 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7716                 {
7717                         ThisCIDMask = CID3MASK;
7718                         break;
7719                 }
7720
7721                 RTMPusecDelay(100);
7722                 i++;
7723         }while (i < 200);
7724
7725         // Get CommandStatus Value
7726         RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7727
7728         // This command's status is at the same position as command. So AND command position's bitmask to read status.
7729         if (i < 200)
7730         {
7731                 // If Status is 1, the comamnd is success.
7732                 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7733                         || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7734                 {
7735                         DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7736                         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7737                         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7738                         return TRUE;
7739                 }
7740                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7741         }
7742         else
7743         {
7744                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7745         }
7746         // Clear Command and Status.
7747         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7748         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7749
7750         return FALSE;
7751 }
7752 #endif /* RT8260 */
7753
7754 /*
7755         ========================================================================
7756
7757         Routine Description:
7758                 Verify the support rate for different PHY type
7759
7760         Arguments:
7761                 pAd                             Pointer to our adapter
7762
7763         Return Value:
7764                 None
7765
7766         IRQL = PASSIVE_LEVEL
7767
7768         ========================================================================
7769 */
7770 VOID    RTMPCheckRates(
7771         IN              PRTMP_ADAPTER   pAd,
7772         IN OUT  UCHAR                   SupRate[],
7773         IN OUT  UCHAR                   *SupRateLen)
7774 {
7775         UCHAR   RateIdx, i, j;
7776         UCHAR   NewRate[12], NewRateLen;
7777
7778         NewRateLen = 0;
7779
7780         if (pAd->CommonCfg.PhyMode == PHY_11B)
7781                 RateIdx = 4;
7782         else
7783                 RateIdx = 12;
7784
7785         // Check for support rates exclude basic rate bit
7786         for (i = 0; i < *SupRateLen; i++)
7787                 for (j = 0; j < RateIdx; j++)
7788                         if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7789                                 NewRate[NewRateLen++] = SupRate[i];
7790
7791         *SupRateLen = NewRateLen;
7792         NdisMoveMemory(SupRate, NewRate, NewRateLen);
7793 }
7794
7795 BOOLEAN RTMPCheckChannel(
7796         IN PRTMP_ADAPTER pAd,
7797         IN UCHAR                CentralChannel,
7798         IN UCHAR                Channel)
7799 {
7800         UCHAR           k;
7801         UCHAR           UpperChannel = 0, LowerChannel = 0;
7802         UCHAR           NoEffectChannelinList = 0;
7803
7804         // Find upper and lower channel according to 40MHz current operation.
7805         if (CentralChannel < Channel)
7806         {
7807                 UpperChannel = Channel;
7808                 if (CentralChannel > 2)
7809                         LowerChannel = CentralChannel - 2;
7810                 else
7811                         return FALSE;
7812         }
7813         else if (CentralChannel > Channel)
7814         {
7815                 UpperChannel = CentralChannel + 2;
7816                 LowerChannel = Channel;
7817         }
7818
7819         for (k = 0;k < pAd->ChannelListNum;k++)
7820         {
7821                 if (pAd->ChannelList[k].Channel == UpperChannel)
7822                 {
7823                         NoEffectChannelinList ++;
7824                 }
7825                 if (pAd->ChannelList[k].Channel == LowerChannel)
7826                 {
7827                         NoEffectChannelinList ++;
7828                 }
7829         }
7830
7831         DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7832         if (NoEffectChannelinList == 2)
7833                 return TRUE;
7834         else
7835                 return FALSE;
7836 }
7837
7838 /*
7839         ========================================================================
7840
7841         Routine Description:
7842                 Verify the support rate for HT phy type
7843
7844         Arguments:
7845                 pAd                             Pointer to our adapter
7846
7847         Return Value:
7848                 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
7849
7850         IRQL = PASSIVE_LEVEL
7851
7852         ========================================================================
7853 */
7854 BOOLEAN         RTMPCheckHt(
7855         IN      PRTMP_ADAPTER                   pAd,
7856         IN      UCHAR                                   Wcid,
7857         IN      HT_CAPABILITY_IE                *pHtCapability,
7858         IN      ADD_HT_INFO_IE                  *pAddHtInfo)
7859 {
7860         if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7861                 return FALSE;
7862
7863         // If use AMSDU, set flag.
7864         if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7865                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7866         // Save Peer Capability
7867         if (pHtCapability->HtCapInfo.ShortGIfor20)
7868                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7869         if (pHtCapability->HtCapInfo.ShortGIfor40)
7870                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7871         if (pHtCapability->HtCapInfo.TxSTBC)
7872                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7873         if (pHtCapability->HtCapInfo.RxSTBC)
7874                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7875         if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7876         {
7877                 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7878         }
7879
7880         if (Wcid < MAX_LEN_OF_MAC_TABLE)
7881         {
7882                 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7883         }
7884
7885         // Will check ChannelWidth for MCSSet[4] below
7886         pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7887     switch (pAd->CommonCfg.RxStream)
7888         {
7889                 case 1:
7890                         pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7891                         pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7892             pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7893             pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7894                         break;
7895                 case 2:
7896                         pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7897                         pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7898             pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7899             pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7900                         break;
7901                 case 3:
7902                         pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7903                         pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7904             pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7905             pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7906                         break;
7907         }
7908
7909         pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7910
7911     DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7912                 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7913                 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7914
7915         pAd->MlmeAux.HtCapability.HtCapInfo.GF =  pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7916
7917         // Send Assoc Req with my HT capability.
7918         pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =  pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7919         pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =  pAd->CommonCfg.DesiredHtPhy.MimoPs;
7920         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7921         pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7922         pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =  (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7923         pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =  (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7924         pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7925     pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7926         pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7927         pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7928         if (pAd->CommonCfg.bRdg)
7929         {
7930                 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7931         pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7932         }
7933
7934     if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7935         pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;  // BW20 can't transmit MCS32
7936
7937         COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7938         return TRUE;
7939 }
7940
7941 /*
7942         ========================================================================
7943
7944         Routine Description:
7945                 Verify the support rate for different PHY type
7946
7947         Arguments:
7948                 pAd                             Pointer to our adapter
7949
7950         Return Value:
7951                 None
7952
7953         IRQL = PASSIVE_LEVEL
7954
7955         ========================================================================
7956 */
7957 VOID RTMPUpdateMlmeRate(
7958         IN PRTMP_ADAPTER        pAd)
7959 {
7960         UCHAR   MinimumRate;
7961         UCHAR   ProperMlmeRate; //= RATE_54;
7962         UCHAR   i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7963         BOOLEAN bMatch = FALSE;
7964
7965         switch (pAd->CommonCfg.PhyMode)
7966         {
7967                 case PHY_11B:
7968                         ProperMlmeRate = RATE_11;
7969                         MinimumRate = RATE_1;
7970                         break;
7971                 case PHY_11BG_MIXED:
7972                 case PHY_11ABGN_MIXED:
7973                 case PHY_11BGN_MIXED:
7974                         if ((pAd->MlmeAux.SupRateLen == 4) &&
7975                                 (pAd->MlmeAux.ExtRateLen == 0))
7976                                 // B only AP
7977                                 ProperMlmeRate = RATE_11;
7978                         else
7979                                 ProperMlmeRate = RATE_24;
7980
7981                         if (pAd->MlmeAux.Channel <= 14)
7982                                 MinimumRate = RATE_1;
7983                         else
7984                                 MinimumRate = RATE_6;
7985                         break;
7986                 case PHY_11A:
7987                 case PHY_11N_2_4G:      // rt2860 need to check mlmerate for 802.11n
7988                 case PHY_11GN_MIXED:
7989                 case PHY_11AGN_MIXED:
7990                 case PHY_11AN_MIXED:
7991                 case PHY_11N_5G:
7992                         ProperMlmeRate = RATE_24;
7993                         MinimumRate = RATE_6;
7994                         break;
7995                 case PHY_11ABG_MIXED:
7996                         ProperMlmeRate = RATE_24;
7997                         if (pAd->MlmeAux.Channel <= 14)
7998                            MinimumRate = RATE_1;
7999                         else
8000                                 MinimumRate = RATE_6;
8001                         break;
8002                 default: // error
8003                         ProperMlmeRate = RATE_1;
8004                         MinimumRate = RATE_1;
8005                         break;
8006         }
8007
8008         for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8009         {
8010                 for (j = 0; j < RateIdx; j++)
8011                 {
8012                         if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8013                         {
8014                                 if (j == ProperMlmeRate)
8015                                 {
8016                                         bMatch = TRUE;
8017                                         break;
8018                                 }
8019                         }
8020                 }
8021
8022                 if (bMatch)
8023                         break;
8024         }
8025
8026         if (bMatch == FALSE)
8027         {
8028                 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8029                 {
8030                         for (j = 0; j < RateIdx; j++)
8031                         {
8032                                 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8033                                 {
8034                                         if (j == ProperMlmeRate)
8035                                         {
8036                                                 bMatch = TRUE;
8037                                                 break;
8038                                         }
8039                                 }
8040                         }
8041
8042                         if (bMatch)
8043                                 break;
8044                 }
8045         }
8046
8047         if (bMatch == FALSE)
8048         {
8049                 ProperMlmeRate = MinimumRate;
8050         }
8051
8052         pAd->CommonCfg.MlmeRate = MinimumRate;
8053         pAd->CommonCfg.RtsRate = ProperMlmeRate;
8054         if (pAd->CommonCfg.MlmeRate >= RATE_6)
8055         {
8056                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8057                 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8058                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8059                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8060         }
8061         else
8062         {
8063                 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8064                 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8065                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8066                 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8067         }
8068
8069         DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n" , pAd->CommonCfg.MlmeTransmit.word));
8070 }
8071
8072 CHAR RTMPMaxRssi(
8073         IN PRTMP_ADAPTER        pAd,
8074         IN CHAR                         Rssi0,
8075         IN CHAR                         Rssi1,
8076         IN CHAR                         Rssi2)
8077 {
8078         CHAR    larger = -127;
8079
8080         if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8081         {
8082                 larger = Rssi0;
8083         }
8084
8085         if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8086         {
8087                 larger = max(Rssi0, Rssi1);
8088         }
8089
8090         if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8091         {
8092                 larger = max(larger, Rssi2);
8093         }
8094
8095         if (larger == -127)
8096                 larger = 0;
8097
8098         return larger;
8099 }
8100
8101 #ifdef RT30xx
8102 // Antenna divesity use GPIO3 and EESK pin for control
8103 // Antenna and EEPROM access are both using EESK pin,
8104 // Therefor we should avoid accessing EESK at the same time
8105 // Then restore antenna after EEPROM access
8106 VOID AsicSetRxAnt(
8107         IN PRTMP_ADAPTER        pAd,
8108         IN UCHAR                        Ant)
8109 {
8110         UINT32  Value;
8111         UINT32  x;
8112
8113         if ((pAd->EepromAccess)                                                                         ||
8114                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))  ||
8115                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))   ||
8116                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))                  ||
8117                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8118         {
8119                 return;
8120         }
8121
8122         // the antenna selection is through firmware and MAC register(GPIO3)
8123         if (Ant == 0)
8124         {
8125                 // Main antenna
8126                 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8127                 x |= (EESK);
8128                 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8129
8130                 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8131                 Value &= ~(0x0808);
8132                 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8133                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8134         }
8135         else
8136         {
8137                 // Aux antenna
8138                 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8139                 x &= ~(EESK);
8140                 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8141
8142                 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8143                 Value &= ~(0x0808);
8144                 Value |= 0x08;
8145                 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8146                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8147         }
8148 }
8149 #endif /* RT30xx */
8150
8151 /*
8152     ========================================================================
8153     Routine Description:
8154         Periodic evaluate antenna link status
8155
8156     Arguments:
8157         pAd         - Adapter pointer
8158
8159     Return Value:
8160         None
8161
8162     ========================================================================
8163 */
8164 VOID AsicEvaluateRxAnt(
8165         IN PRTMP_ADAPTER        pAd)
8166 {
8167         UCHAR   BBPR3 = 0;
8168
8169         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8170                                 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8171                                 fRTMP_ADAPTER_RADIO_OFF |
8172                                 fRTMP_ADAPTER_NIC_NOT_EXIST |
8173                                 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
8174                                 || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8175 #ifdef RT30xx
8176                                 || (pAd->EepromAccess)
8177 #endif
8178                                 )
8179                         return;
8180
8181 #ifdef RT30xx
8182         // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8183         // one is antenna diversity:there is only one antenna can rx and tx
8184         // the other is failed antenna remove:two physical antenna can rx and tx
8185         if (pAd->NicConfig2.field.AntDiversity)
8186         {
8187                 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8188                         pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8189
8190                 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8191
8192                 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8193                 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8194                 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8195
8196                 // a one-shot timer to end the evalution
8197                 // dynamic adjust antenna evaluation period according to the traffic
8198                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8199                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8200                 else
8201                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8202         }
8203         else
8204 #endif
8205         {
8206                 if (pAd->StaCfg.Psm == PWR_SAVE)
8207                         return;
8208
8209                 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8210                 BBPR3 &= (~0x18);
8211                 if(pAd->Antenna.field.RxPath == 3)
8212                 {
8213                         BBPR3 |= (0x10);
8214                 }
8215                 else if(pAd->Antenna.field.RxPath == 2)
8216                 {
8217                         BBPR3 |= (0x8);
8218                 }
8219                 else if(pAd->Antenna.field.RxPath == 1)
8220                 {
8221                         BBPR3 |= (0x0);
8222                 }
8223                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8224
8225 #ifdef RT2860
8226                 pAd->StaCfg.BBPR3 = BBPR3;
8227 #endif
8228         }
8229
8230         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8231                 )
8232         {
8233                 ULONG   TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8234                                                                 pAd->RalinkCounters.OneSecTxRetryOkCount +
8235                                                                 pAd->RalinkCounters.OneSecTxFailCount;
8236
8237                         // dynamic adjust antenna evaluation period according to the traffic
8238                 if (TxTotalCnt > 50)
8239                 {
8240                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8241                         pAd->Mlme.bLowThroughput = FALSE;
8242                 }
8243                 else
8244                 {
8245                         RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8246                         pAd->Mlme.bLowThroughput = TRUE;
8247                 }
8248         }
8249 }
8250
8251 /*
8252     ========================================================================
8253     Routine Description:
8254         After evaluation, check antenna link status
8255
8256     Arguments:
8257         pAd         - Adapter pointer
8258
8259     Return Value:
8260         None
8261
8262     ========================================================================
8263 */
8264 VOID AsicRxAntEvalTimeout(
8265         IN PVOID SystemSpecific1,
8266         IN PVOID FunctionContext,
8267         IN PVOID SystemSpecific2,
8268         IN PVOID SystemSpecific3)
8269 {
8270         RTMP_ADAPTER    *pAd = (RTMP_ADAPTER *)FunctionContext;
8271         UCHAR                   BBPR3 = 0;
8272         CHAR                    larger = -127, rssi0, rssi1, rssi2;
8273
8274         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8275                                                         fRTMP_ADAPTER_HALT_IN_PROGRESS  |
8276                                                         fRTMP_ADAPTER_RADIO_OFF                 |
8277                                                         fRTMP_ADAPTER_NIC_NOT_EXIST)
8278                                                         || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8279 #ifdef RT30xx
8280                                                         || (pAd->EepromAccess)
8281 #endif // RT30xx //
8282                                                         )
8283                 return;
8284
8285         {
8286 #ifdef RT30xx
8287                 if (pAd->NicConfig2.field.AntDiversity)
8288                 {
8289                         if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8290                         {
8291                                 UCHAR                   temp;
8292
8293                                 //
8294                                 // select PrimaryRxAntPair
8295                                 //    Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8296                                 //    Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8297                                 //
8298                                 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8299                                 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8300                                 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8301
8302                                 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8303                                 pAd->RxAnt.EvaluateStableCnt = 0;
8304                         }
8305                         else
8306                         {
8307                                 // if the evaluated antenna is not better than original, switch back to original antenna
8308                                 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8309                                 pAd->RxAnt.EvaluateStableCnt ++;
8310                         }
8311
8312                         pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8313
8314                         DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8315                                         pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8316                 }
8317                 else
8318 #endif
8319                 {
8320                         if (pAd->StaCfg.Psm == PWR_SAVE)
8321                                 return;
8322
8323                         // if the traffic is low, use average rssi as the criteria
8324                         if (pAd->Mlme.bLowThroughput == TRUE)
8325                         {
8326                                 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8327                                 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8328                                 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8329                         }
8330                         else
8331                         {
8332                                 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8333                                 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8334                                 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8335                         }
8336
8337                         if(pAd->Antenna.field.RxPath == 3)
8338                         {
8339                                 larger = max(rssi0, rssi1);
8340
8341                                 if (larger > (rssi2 + 20))
8342                                         pAd->Mlme.RealRxPath = 2;
8343                                 else
8344                                         pAd->Mlme.RealRxPath = 3;
8345                         }
8346                         else if(pAd->Antenna.field.RxPath == 2)
8347                         {
8348                                 if (rssi0 > (rssi1 + 20))
8349                                         pAd->Mlme.RealRxPath = 1;
8350                                 else
8351                                         pAd->Mlme.RealRxPath = 2;
8352                         }
8353
8354                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8355                         BBPR3 &= (~0x18);
8356                         if(pAd->Mlme.RealRxPath == 3)
8357                         {
8358                                 BBPR3 |= (0x10);
8359                         }
8360                         else if(pAd->Mlme.RealRxPath == 2)
8361                         {
8362                                 BBPR3 |= (0x8);
8363                         }
8364                         else if(pAd->Mlme.RealRxPath == 1)
8365                         {
8366                                 BBPR3 |= (0x0);
8367                         }
8368                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8369 #ifdef RT2860
8370                         pAd->StaCfg.BBPR3 = BBPR3;
8371 #endif
8372                 }
8373         }
8374 }
8375
8376 VOID APSDPeriodicExec(
8377         IN PVOID SystemSpecific1,
8378         IN PVOID FunctionContext,
8379         IN PVOID SystemSpecific2,
8380         IN PVOID SystemSpecific3)
8381 {
8382         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8383
8384         if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8385                 return;
8386
8387         pAd->CommonCfg.TriggerTimerCount++;
8388
8389 }
8390
8391 /*
8392     ========================================================================
8393     Routine Description:
8394         Set/reset MAC registers according to bPiggyBack parameter
8395
8396     Arguments:
8397         pAd         - Adapter pointer
8398         bPiggyBack  - Enable / Disable Piggy-Back
8399
8400     Return Value:
8401         None
8402
8403     ========================================================================
8404 */
8405 VOID RTMPSetPiggyBack(
8406     IN PRTMP_ADAPTER    pAd,
8407     IN BOOLEAN          bPiggyBack)
8408 {
8409         TX_LINK_CFG_STRUC  TxLinkCfg;
8410
8411         RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8412
8413         TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8414         RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8415 }
8416
8417 /*
8418     ========================================================================
8419     Routine Description:
8420         check if this entry need to switch rate automatically
8421
8422     Arguments:
8423         pAd
8424         pEntry
8425
8426     Return Value:
8427         TURE
8428         FALSE
8429
8430     ========================================================================
8431 */
8432 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8433         IN PRTMP_ADAPTER    pAd,
8434         IN PMAC_TABLE_ENTRY     pEntry)
8435 {
8436         BOOLEAN         result = TRUE;
8437
8438         {
8439                 // only associated STA counts
8440                 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8441                 {
8442                         result = pAd->StaCfg.bAutoTxRateSwitch;
8443                 }
8444                 else
8445                         result = FALSE;
8446         }
8447
8448         return result;
8449 }
8450
8451
8452 BOOLEAN RTMPAutoRateSwitchCheck(
8453         IN PRTMP_ADAPTER    pAd)
8454 {
8455         if (pAd->StaCfg.bAutoTxRateSwitch)
8456                 return TRUE;
8457
8458         return FALSE;
8459 }
8460
8461
8462 /*
8463     ========================================================================
8464     Routine Description:
8465         check if this entry need to fix tx legacy rate
8466
8467     Arguments:
8468         pAd
8469         pEntry
8470
8471     Return Value:
8472         TURE
8473         FALSE
8474
8475     ========================================================================
8476 */
8477 UCHAR RTMPStaFixedTxMode(
8478         IN PRTMP_ADAPTER    pAd,
8479         IN PMAC_TABLE_ENTRY     pEntry)
8480 {
8481         UCHAR   tx_mode = FIXED_TXMODE_HT;
8482
8483         tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8484
8485         return tx_mode;
8486 }
8487
8488 /*
8489     ========================================================================
8490     Routine Description:
8491         Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8492
8493     Arguments:
8494         pAd
8495         pEntry
8496
8497     Return Value:
8498         TURE
8499         FALSE
8500
8501     ========================================================================
8502 */
8503 VOID RTMPUpdateLegacyTxSetting(
8504                 UCHAR                           fixed_tx_mode,
8505                 PMAC_TABLE_ENTRY        pEntry)
8506 {
8507         HTTRANSMIT_SETTING TransmitSetting;
8508
8509         if (fixed_tx_mode == FIXED_TXMODE_HT)
8510                 return;
8511
8512         TransmitSetting.word = 0;
8513
8514         TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8515         TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8516
8517         if (fixed_tx_mode == FIXED_TXMODE_CCK)
8518         {
8519                 TransmitSetting.field.MODE = MODE_CCK;
8520                 // CCK mode allow MCS 0~3
8521                 if (TransmitSetting.field.MCS > MCS_3)
8522                         TransmitSetting.field.MCS = MCS_3;
8523         }
8524         else
8525         {
8526                 TransmitSetting.field.MODE = MODE_OFDM;
8527                 // OFDM mode allow MCS 0~7
8528                 if (TransmitSetting.field.MCS > MCS_7)
8529                         TransmitSetting.field.MCS = MCS_7;
8530         }
8531
8532         if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8533         {
8534                 pEntry->HTPhyMode.word = TransmitSetting.word;
8535                 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8536                                 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8537         }
8538 }
8539
8540 /*
8541         ==========================================================================
8542         Description:
8543                 dynamic tune BBP R66 to find a balance between sensibility and
8544                 noise isolation
8545
8546         IRQL = DISPATCH_LEVEL
8547
8548         ==========================================================================
8549  */
8550 VOID AsicStaBbpTuning(
8551         IN PRTMP_ADAPTER pAd)
8552 {
8553         UCHAR   OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8554         CHAR    Rssi;
8555
8556         // 2860C did not support Fase CCA, therefore can't tune
8557         if (pAd->MACVersion == 0x28600100)
8558                 return;
8559
8560         //
8561         // work as a STA
8562         //
8563         if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)  // no R66 tuning when SCANNING
8564                 return;
8565
8566         if ((pAd->OpMode == OPMODE_STA)
8567                 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8568                         )
8569                 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8570 #ifdef RT2860
8571                 && (pAd->bPCIclkOff == FALSE))
8572 #endif
8573 #ifdef RT2870
8574                 )
8575 #endif
8576         {
8577                 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8578                 R66 = OrigR66Value;
8579
8580                 if (pAd->Antenna.field.RxPath > 1)
8581                         Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8582                 else
8583                         Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8584
8585                 if (pAd->LatchRfRegs.Channel <= 14)
8586                 {       //BG band
8587 #ifdef RT2870
8588                         // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8589                         // Otherwise, it will have some throughput side effect when low RSSI
8590 #ifndef RT30xx
8591                         if (IS_RT3070(pAd))
8592 #endif
8593 #ifdef RT30xx
8594                         if (IS_RT30xx(pAd))
8595 #endif
8596                         {
8597                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8598                                 {
8599                                         R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8600                                         if (OrigR66Value != R66)
8601                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8602                                 }
8603                                 else
8604                                 {
8605                                         R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8606                                         if (OrigR66Value != R66)
8607                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8608                                 }
8609                         }
8610                         else
8611 #endif // RT2870 //
8612                         {
8613                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8614                                 {
8615                                         R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8616                                         if (OrigR66Value != R66)
8617                                         {
8618                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8619                                         }
8620                                 }
8621                                 else
8622                                 {
8623                                         R66 = 0x2E + GET_LNA_GAIN(pAd);
8624                                         if (OrigR66Value != R66)
8625                                         {
8626                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8627                                         }
8628                                 }
8629                         }
8630                 }
8631                 else
8632                 {       //A band
8633                         if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8634                         {
8635                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8636                                 {
8637                                         R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8638                                         if (OrigR66Value != R66)
8639                                         {
8640                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8641                                         }
8642                                 }
8643                                 else
8644                                 {
8645                                         R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8646                                         if (OrigR66Value != R66)
8647                                         {
8648                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8649                                         }
8650                                 }
8651                         }
8652                         else
8653                         {
8654                                 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8655                                 {
8656                                         R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8657                                         if (OrigR66Value != R66)
8658                                         {
8659                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8660                                         }
8661                                 }
8662                                 else
8663                                 {
8664                                         R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8665                                         if (OrigR66Value != R66)
8666                                         {
8667                                                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8668                                         }
8669                                 }
8670                         }
8671                 }
8672
8673
8674         }
8675 }
8676
8677 #ifdef RT2860
8678 VOID AsicResetFromDMABusy(
8679         IN PRTMP_ADAPTER pAd)
8680 {
8681         UINT32          Data;
8682         BOOLEAN         bCtrl = FALSE;
8683
8684         DBGPRINT(RT_DEBUG_TRACE, ("--->  AsicResetFromDMABusy  !!!!!!!!!!!!!!!!!!!!!!! \n"));
8685
8686         // Be sure restore link control value so we can write register.
8687         RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8688         if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8689         {
8690                 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8691                 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8692                 RTMPusecDelay(6000);
8693                 pAd->bPCIclkOff = FALSE;
8694                 bCtrl = TRUE;
8695         }
8696         // Reset DMA
8697         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8698         Data |= 0x2;
8699         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8700
8701         // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8702         // Reset DMA/CPU ring index
8703         RTMPRingCleanUp(pAd, QID_AC_BK);
8704         RTMPRingCleanUp(pAd, QID_AC_BE);
8705         RTMPRingCleanUp(pAd, QID_AC_VI);
8706         RTMPRingCleanUp(pAd, QID_AC_VO);
8707         RTMPRingCleanUp(pAd, QID_HCCA);
8708         RTMPRingCleanUp(pAd, QID_MGMT);
8709         RTMPRingCleanUp(pAd, QID_RX);
8710
8711         // Clear Reset
8712         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8713         Data &= 0xfffffffd;
8714         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8715
8716         // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8717         if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8718                 RTMPPCIeLinkCtrlSetting(pAd, 3);
8719
8720         RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8721         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8722         DBGPRINT(RT_DEBUG_TRACE, ("<---  AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!!  \n"));
8723 }
8724
8725 VOID AsicResetBBP(
8726         IN PRTMP_ADAPTER pAd)
8727 {
8728         DBGPRINT(RT_DEBUG_TRACE, ("--->  Asic HardReset BBP  !!!!!!!!!!!!!!!!!!!!!!! \n"));
8729
8730         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8731         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8732         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8733
8734         // After hard-reset BBP, initialize all BBP values.
8735         NICRestoreBBPValue(pAd);
8736         DBGPRINT(RT_DEBUG_TRACE, ("<---  Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!!  \n"));
8737 }
8738
8739 VOID AsicResetMAC(
8740         IN PRTMP_ADAPTER pAd)
8741 {
8742         ULONG           Data;
8743
8744         DBGPRINT(RT_DEBUG_TRACE, ("--->  AsicResetMAC   !!!! \n"));
8745         RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8746         Data |= 0x4;
8747         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8748         Data &= 0xfffffffb;
8749         RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8750
8751         DBGPRINT(RT_DEBUG_TRACE, ("<---  AsicResetMAC   !!!! \n"));
8752 }
8753
8754 VOID AsicResetPBF(
8755         IN PRTMP_ADAPTER pAd)
8756 {
8757         ULONG           Value1, Value2;
8758         ULONG           Data;
8759
8760         RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8761         RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8762
8763         Value2 &= 0xff;
8764         // sum should be equals to 0xff, which is the total buffer size.
8765         if ((Value1 + Value2) < 0xff)
8766         {
8767                 DBGPRINT(RT_DEBUG_TRACE, ("--->  Asic HardReset PBF !!!! \n"));
8768                 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8769                 Data |= 0x8;
8770                 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8771                 Data &= 0xfffffff7;
8772                 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8773
8774                 DBGPRINT(RT_DEBUG_TRACE, ("<---  Asic HardReset PBF !!!! \n"));
8775         }
8776 }
8777 #endif /* RT2860 */
8778
8779 VOID RTMPSetAGCInitValue(
8780         IN PRTMP_ADAPTER        pAd,
8781         IN UCHAR                        BandWidth)
8782 {
8783         UCHAR   R66 = 0x30;
8784
8785         if (pAd->LatchRfRegs.Channel <= 14)
8786         {       // BG band
8787                 R66 = 0x2E + GET_LNA_GAIN(pAd);
8788                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8789         }
8790         else
8791         {       //A band
8792                 if (BandWidth == BW_20)
8793                 {
8794                         R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8795                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8796                 }
8797                 else
8798                 {
8799                         R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8800                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8801                 }
8802         }
8803
8804 }
8805
8806 VOID AsicTurnOffRFClk(
8807         IN PRTMP_ADAPTER pAd,
8808         IN      UCHAR           Channel)
8809 {
8810
8811         // RF R2 bit 18 = 0
8812         UINT32                  R1 = 0, R2 = 0, R3 = 0;
8813         UCHAR                   index;
8814         RTMP_RF_REGS    *RFRegTable;
8815
8816         // The RF programming sequence is difference between 3xxx and 2xxx
8817         if (IS_RT3090(pAd))
8818         {
8819                 RT30xxLoadRFSleepModeSetup(pAd);  // add by johnli,  RF power sequence setup, load RF sleep-mode setup
8820                 return;
8821         }
8822
8823         RFRegTable = RF2850RegTable;
8824
8825         switch (pAd->RfIcType)
8826         {
8827                 case RFIC_2820:
8828                 case RFIC_2850:
8829                 case RFIC_2720:
8830                 case RFIC_2750:
8831
8832                         for (index = 0; index < NUM_OF_2850_CHNL; index++)
8833                         {
8834                                 if (Channel == RFRegTable[index].Channel)
8835                                 {
8836                                         R1 = RFRegTable[index].R1 & 0xffffdfff;
8837                                         R2 = RFRegTable[index].R2 & 0xfffbffff;
8838                                         R3 = RFRegTable[index].R3 & 0xfff3ffff;
8839
8840                                         RTMP_RF_IO_WRITE32(pAd, R1);
8841                                         RTMP_RF_IO_WRITE32(pAd, R2);
8842
8843                                         // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8844                                         // Set RF R2 bit18=0, R3 bit[18:19]=0
8845                                         //if (pAd->StaCfg.bRadio == FALSE)
8846                                         if (1)
8847                                         {
8848                                                 RTMP_RF_IO_WRITE32(pAd, R3);
8849
8850                                                 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x,  R3 = 0x%08x \n",
8851                                                         Channel, pAd->RfIcType, R2, R3));
8852                                         }
8853                                         else
8854                                                 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8855                                                         Channel, pAd->RfIcType, R2));
8856                                         break;
8857                                 }
8858                         }
8859                         break;
8860
8861                 default:
8862                         break;
8863         }
8864 }
8865
8866
8867 VOID AsicTurnOnRFClk(
8868         IN PRTMP_ADAPTER pAd,
8869         IN      UCHAR                   Channel)
8870 {
8871
8872         // RF R2 bit 18 = 0
8873         UINT32                  R1 = 0, R2 = 0, R3 = 0;
8874         UCHAR                   index;
8875         RTMP_RF_REGS    *RFRegTable;
8876
8877         // The RF programming sequence is difference between 3xxx and 2xxx
8878         if (IS_RT3090(pAd))
8879                 return;
8880
8881         RFRegTable = RF2850RegTable;
8882
8883         switch (pAd->RfIcType)
8884         {
8885                 case RFIC_2820:
8886                 case RFIC_2850:
8887                 case RFIC_2720:
8888                 case RFIC_2750:
8889
8890                         for (index = 0; index < NUM_OF_2850_CHNL; index++)
8891                         {
8892                                 if (Channel == RFRegTable[index].Channel)
8893                                 {
8894                                         R3 = pAd->LatchRfRegs.R3;
8895                                         R3 &= 0xfff3ffff;
8896                                         R3 |= 0x00080000;
8897                                         RTMP_RF_IO_WRITE32(pAd, R3);
8898
8899                                         R1 = RFRegTable[index].R1;
8900                                         RTMP_RF_IO_WRITE32(pAd, R1);
8901
8902                                         R2 = RFRegTable[index].R2;
8903                                         if (pAd->Antenna.field.TxPath == 1)
8904                                         {
8905                                                 R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
8906                                         }
8907
8908                                         if (pAd->Antenna.field.RxPath == 2)
8909                                         {
8910                                                 R2 |= 0x40;     // write 1 to off Rxpath.
8911                                         }
8912                                         else if (pAd->Antenna.field.RxPath == 1)
8913                                         {
8914                                                 R2 |= 0x20040;  // write 1 to off RxPath
8915                                         }
8916                                         RTMP_RF_IO_WRITE32(pAd, R2);
8917
8918                                         break;
8919                                 }
8920                         }
8921                         break;
8922
8923                 default:
8924                         break;
8925         }
8926
8927         DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8928                 Channel,
8929                 pAd->RfIcType,
8930                 R2));
8931 }
8932