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