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