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