Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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