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