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