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