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