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