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