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