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