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