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