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