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