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