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