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