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