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