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