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