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