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