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