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