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