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