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