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