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 #include <linux/kernel.h>
42 
43 u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 };
44 
45 u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
46 u8 RSN_OUI[] = { 0x00, 0x0f, 0xac };
47 u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
48 u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
49 u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 };
50 u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 };
51 u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c };
52 u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
53 u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c };
54 
55 u8 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 u8 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 u8 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 u8 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 u8 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 	0x0c, 0x0a, 0, 0, 0,	/* Initial used item after association */
132 	0x00, 0x00, 0, 40, 101,
133 	0x01, 0x00, 1, 40, 50,
134 	0x02, 0x00, 2, 25, 45,
135 	0x03, 0x21, 0, 20, 35,
136 	0x04, 0x21, 1, 20, 35,
137 	0x05, 0x21, 2, 20, 35,
138 	0x06, 0x21, 3, 15, 35,
139 	0x07, 0x21, 4, 15, 30,
140 	0x08, 0x21, 5, 10, 25,
141 	0x09, 0x21, 6, 8, 14,
142 	0x0a, 0x21, 7, 8, 14,
143 	0x0b, 0x23, 7, 8, 14,
144 };
145 
146 u8 RateSwitchTable11N2S[] = {
147 /* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
148 	0x0e, 0x0c, 0, 0, 0,	/* Initial used item after association */
149 	0x00, 0x00, 0, 40, 101,
150 	0x01, 0x00, 1, 40, 50,
151 	0x02, 0x00, 2, 25, 45,
152 	0x03, 0x21, 0, 20, 35,
153 	0x04, 0x21, 1, 20, 35,
154 	0x05, 0x21, 2, 20, 35,
155 	0x06, 0x21, 3, 15, 35,
156 	0x07, 0x21, 4, 15, 30,
157 	0x08, 0x20, 11, 15, 30,
158 	0x09, 0x20, 12, 15, 30,
159 	0x0a, 0x20, 13, 8, 20,
160 	0x0b, 0x20, 14, 8, 20,
161 	0x0c, 0x20, 15, 8, 25,
162 	0x0d, 0x22, 15, 8, 15,
163 };
164 
165 u8 RateSwitchTable11N3S[] = {
166 /* 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) */
167 	0x0b, 0x00, 0, 0, 0,	/* 0x0a, 0x00,  0,  0,  0,      // Initial used item after association */
168 	0x00, 0x21, 0, 30, 101,
169 	0x01, 0x21, 1, 20, 50,
170 	0x02, 0x21, 2, 20, 50,
171 	0x03, 0x21, 3, 15, 50,
172 	0x04, 0x21, 4, 15, 30,
173 	0x05, 0x20, 11, 15, 30,	/* Required by System-Alan @ 20080812 */
174 	0x06, 0x20, 12, 15, 30,	/* 0x05, 0x20, 12, 15, 30, */
175 	0x07, 0x20, 13, 8, 20,	/* 0x06, 0x20, 13,  8, 20, */
176 	0x08, 0x20, 14, 8, 20,	/* 0x07, 0x20, 14,  8, 20, */
177 	0x09, 0x20, 15, 8, 25,	/* 0x08, 0x20, 15,  8, 25, */
178 	0x0a, 0x22, 15, 8, 25,	/* 0x09, 0x22, 15,  8, 25, */
179 };
180 
181 u8 RateSwitchTable11N2SForABand[] = {
182 /* 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) */
183 	0x0b, 0x09, 0, 0, 0,	/* Initial used item after association */
184 	0x00, 0x21, 0, 30, 101,
185 	0x01, 0x21, 1, 20, 50,
186 	0x02, 0x21, 2, 20, 50,
187 	0x03, 0x21, 3, 15, 50,
188 	0x04, 0x21, 4, 15, 30,
189 	0x05, 0x21, 5, 15, 30,
190 	0x06, 0x20, 12, 15, 30,
191 	0x07, 0x20, 13, 8, 20,
192 	0x08, 0x20, 14, 8, 20,
193 	0x09, 0x20, 15, 8, 25,
194 	0x0a, 0x22, 15, 8, 25,
195 };
196 
197 u8 RateSwitchTable11N3SForABand[] = {	/* 3*3 */
198 /* 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) */
199 	0x0b, 0x09, 0, 0, 0,	/* Initial used item after association */
200 	0x00, 0x21, 0, 30, 101,
201 	0x01, 0x21, 1, 20, 50,
202 	0x02, 0x21, 2, 20, 50,
203 	0x03, 0x21, 3, 15, 50,
204 	0x04, 0x21, 4, 15, 30,
205 	0x05, 0x21, 5, 15, 30,
206 	0x06, 0x20, 12, 15, 30,
207 	0x07, 0x20, 13, 8, 20,
208 	0x08, 0x20, 14, 8, 20,
209 	0x09, 0x20, 15, 8, 25,
210 	0x0a, 0x22, 15, 8, 25,
211 };
212 
213 u8 RateSwitchTable11BGN1S[] = {
214 /* 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) */
215 	0x0c, 0x0a, 0, 0, 0,	/* Initial used item after association */
216 	0x00, 0x00, 0, 40, 101,
217 	0x01, 0x00, 1, 40, 50,
218 	0x02, 0x00, 2, 25, 45,
219 	0x03, 0x21, 0, 20, 35,
220 	0x04, 0x21, 1, 20, 35,
221 	0x05, 0x21, 2, 20, 35,
222 	0x06, 0x21, 3, 15, 35,
223 	0x07, 0x21, 4, 15, 30,
224 	0x08, 0x21, 5, 10, 25,
225 	0x09, 0x21, 6, 8, 14,
226 	0x0a, 0x21, 7, 8, 14,
227 	0x0b, 0x23, 7, 8, 14,
228 };
229 
230 u8 RateSwitchTable11BGN2S[] = {
231 /* 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) */
232 	0x0e, 0x0c, 0, 0, 0,	/* Initial used item after association */
233 	0x00, 0x00, 0, 40, 101,
234 	0x01, 0x00, 1, 40, 50,
235 	0x02, 0x00, 2, 25, 45,
236 	0x03, 0x21, 0, 20, 35,
237 	0x04, 0x21, 1, 20, 35,
238 	0x05, 0x21, 2, 20, 35,
239 	0x06, 0x21, 3, 15, 35,
240 	0x07, 0x21, 4, 15, 30,
241 	0x08, 0x20, 11, 15, 30,
242 	0x09, 0x20, 12, 15, 30,
243 	0x0a, 0x20, 13, 8, 20,
244 	0x0b, 0x20, 14, 8, 20,
245 	0x0c, 0x20, 15, 8, 25,
246 	0x0d, 0x22, 15, 8, 15,
247 };
248 
249 u8 RateSwitchTable11BGN3S[] = {	/* 3*3 */
250 /* 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) */
251 	0x0a, 0x00, 0, 0, 0,	/* Initial used item after association */
252 	0x00, 0x21, 0, 30, 101,	/*50 */
253 	0x01, 0x21, 1, 20, 50,
254 	0x02, 0x21, 2, 20, 50,
255 	0x03, 0x21, 3, 20, 50,
256 	0x04, 0x21, 4, 15, 50,
257 	0x05, 0x20, 20, 15, 30,
258 	0x06, 0x20, 21, 8, 20,
259 	0x07, 0x20, 22, 8, 20,
260 	0x08, 0x20, 23, 8, 25,
261 	0x09, 0x22, 23, 8, 25,
262 };
263 
264 u8 RateSwitchTable11BGN2SForABand[] = {
265 /* 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) */
266 	0x0b, 0x09, 0, 0, 0,	/* Initial used item after association */
267 	0x00, 0x21, 0, 30, 101,	/*50 */
268 	0x01, 0x21, 1, 20, 50,
269 	0x02, 0x21, 2, 20, 50,
270 	0x03, 0x21, 3, 15, 50,
271 	0x04, 0x21, 4, 15, 30,
272 	0x05, 0x21, 5, 15, 30,
273 	0x06, 0x20, 12, 15, 30,
274 	0x07, 0x20, 13, 8, 20,
275 	0x08, 0x20, 14, 8, 20,
276 	0x09, 0x20, 15, 8, 25,
277 	0x0a, 0x22, 15, 8, 25,
278 };
279 
280 u8 RateSwitchTable11BGN3SForABand[] = {	/* 3*3 */
281 /* 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) */
282 	0x0c, 0x09, 0, 0, 0,	/* Initial used item after association */
283 	0x00, 0x21, 0, 30, 101,	/*50 */
284 	0x01, 0x21, 1, 20, 50,
285 	0x02, 0x21, 2, 20, 50,
286 	0x03, 0x21, 3, 15, 50,
287 	0x04, 0x21, 4, 15, 30,
288 	0x05, 0x21, 5, 15, 30,
289 	0x06, 0x21, 12, 15, 30,
290 	0x07, 0x20, 20, 15, 30,
291 	0x08, 0x20, 21, 8, 20,
292 	0x09, 0x20, 22, 8, 20,
293 	0x0a, 0x20, 23, 8, 25,
294 	0x0b, 0x22, 23, 8, 25,
295 };
296 
297 extern u8 OfdmRateToRxwiMCS[];
298 /* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */
299 /* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */
300 unsigned long BasicRateMask[12] =
301     { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ ,
302 0xfffff00f /* 11 */ ,
303 	0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ ,
304 	    0xfffff0ff /* 18 */ ,
305 	0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ ,
306 	    0xffffffff /* 54 */
307 };
308 
309 u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
310 u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
311 
312 /* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */
313 /*              this value, then it's quaranteed capable of operating in 36 mbps TX rate in */
314 /*              clean environment. */
315 /*                                                                TxRate: 1   2   5.5   11       6        9    12       18       24   36   48   54       72  100 */
316 char RssiSafeLevelForTxRate[] =
317     { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
318 
319 u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
320 u16 RateIdTo500Kbps[] =
321     { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
322 
323 u8 SsidIe = IE_SSID;
324 u8 SupRateIe = IE_SUPP_RATES;
325 u8 ExtRateIe = IE_EXT_SUPP_RATES;
326 u8 HtCapIe = IE_HT_CAP;
327 u8 AddHtInfoIe = IE_ADD_HT;
328 u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET;
329 u8 ErpIe = IE_ERP;
330 u8 DsIe = IE_DS_PARM;
331 u8 TimIe = IE_TIM;
332 u8 WpaIe = IE_WPA;
333 u8 Wpa2Ie = IE_WPA2;
334 u8 IbssIe = IE_IBSS_PARM;
335 
336 extern u8 WPA_OUI[];
337 
338 u8 SES_OUI[] = { 0x00, 0x90, 0x4c };
339 
340 u8 ZeroSsid[32] =
341     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00,
343 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 	    0x00, 0x00, 0x00, 0x00
345 };
346 
347 /*
348 	==========================================================================
349 	Description:
350 		initialize the MLME task and its data structure (queue, spinlock,
351 		timer, state machines).
352 
353 	IRQL = PASSIVE_LEVEL
354 
355 	Return:
356 		always return NDIS_STATUS_SUCCESS
357 
358 	==========================================================================
359 */
MlmeInit(struct rt_rtmp_adapter * pAd)360 int MlmeInit(struct rt_rtmp_adapter *pAd)
361 {
362 	int Status = NDIS_STATUS_SUCCESS;
363 
364 	DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
365 
366 	do {
367 		Status = MlmeQueueInit(&pAd->Mlme.Queue);
368 		if (Status != NDIS_STATUS_SUCCESS)
369 			break;
370 
371 		pAd->Mlme.bRunning = FALSE;
372 		NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
373 
374 		{
375 			BssTableInit(&pAd->ScanTab);
376 
377 			/* init STA state machines */
378 			AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine,
379 					      pAd->Mlme.AssocFunc);
380 			AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine,
381 					     pAd->Mlme.AuthFunc);
382 			AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine,
383 						pAd->Mlme.AuthRspFunc);
384 			SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine,
385 					     pAd->Mlme.SyncFunc);
386 
387 			/* Since we are using switch/case to implement it, the init is different from the above */
388 			/* state machine init */
389 			MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
390 		}
391 
392 		WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine,
393 				    pAd->Mlme.WpaFunc);
394 
395 		ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine,
396 				       pAd->Mlme.ActFunc);
397 
398 		/* Init mlme periodic timer */
399 		RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer,
400 			      GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
401 
402 		/* Set mlme periodic timer */
403 		RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
404 
405 		/* software-based RX Antenna diversity */
406 		RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer,
407 			      GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd,
408 			      FALSE);
409 
410 		{
411 #ifdef RTMP_PCI_SUPPORT
412 			if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
413 				/* only PCIe cards need these two timers */
414 				RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer,
415 					      GET_TIMER_FUNCTION
416 					      (PsPollWakeExec), pAd, FALSE);
417 				RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer,
418 					      GET_TIMER_FUNCTION(RadioOnExec),
419 					      pAd, FALSE);
420 			}
421 #endif /* RTMP_PCI_SUPPORT // */
422 
423 			RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer,
424 				      GET_TIMER_FUNCTION(LinkDownExec), pAd,
425 				      FALSE);
426 
427 #ifdef RTMP_MAC_USB
428 			RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer,
429 				      GET_TIMER_FUNCTION
430 				      (RtmpUsbStaAsicForceWakeupTimeout), pAd,
431 				      FALSE);
432 			pAd->Mlme.AutoWakeupTimerRunning = FALSE;
433 #endif /* RTMP_MAC_USB // */
434 		}
435 
436 	} while (FALSE);
437 
438 	DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
439 
440 	return Status;
441 }
442 
443 /*
444 	==========================================================================
445 	Description:
446 		main loop of the MLME
447 	Pre:
448 		Mlme has to be initialized, and there are something inside the queue
449 	Note:
450 		This function is invoked from MPSetInformation and MPReceive;
451 		This task guarantee only one MlmeHandler will run.
452 
453 	IRQL = DISPATCH_LEVEL
454 
455 	==========================================================================
456  */
MlmeHandler(struct rt_rtmp_adapter * pAd)457 void MlmeHandler(struct rt_rtmp_adapter *pAd)
458 {
459 	struct rt_mlme_queue_elem *Elem = NULL;
460 
461 	/* Only accept MLME and Frame from peer side, no other (control/data) frame should */
462 	/* get into this state machine */
463 
464 	NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
465 	if (pAd->Mlme.bRunning) {
466 		NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
467 		return;
468 	} else {
469 		pAd->Mlme.bRunning = TRUE;
470 	}
471 	NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
472 
473 	while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
474 		if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
475 		    RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
476 		    RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
477 			DBGPRINT(RT_DEBUG_TRACE,
478 				 ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n",
479 				  pAd->Mlme.Queue.Num));
480 			break;
481 		}
482 		/*From message type, determine which state machine I should drive */
483 		if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
484 #ifdef RTMP_MAC_USB
485 			if (Elem->MsgType == MT2_RESET_CONF) {
486 				DBGPRINT_RAW(RT_DEBUG_TRACE,
487 					     ("reset MLME state machine!\n"));
488 				MlmeRestartStateMachine(pAd);
489 				Elem->Occupied = FALSE;
490 				Elem->MsgLen = 0;
491 				continue;
492 			}
493 #endif /* RTMP_MAC_USB // */
494 
495 			/* if dequeue success */
496 			switch (Elem->Machine) {
497 				/* STA state machines */
498 			case ASSOC_STATE_MACHINE:
499 				StateMachinePerformAction(pAd,
500 							  &pAd->Mlme.
501 							  AssocMachine, Elem);
502 				break;
503 			case AUTH_STATE_MACHINE:
504 				StateMachinePerformAction(pAd,
505 							  &pAd->Mlme.
506 							  AuthMachine, Elem);
507 				break;
508 			case AUTH_RSP_STATE_MACHINE:
509 				StateMachinePerformAction(pAd,
510 							  &pAd->Mlme.
511 							  AuthRspMachine, Elem);
512 				break;
513 			case SYNC_STATE_MACHINE:
514 				StateMachinePerformAction(pAd,
515 							  &pAd->Mlme.
516 							  SyncMachine, Elem);
517 				break;
518 			case MLME_CNTL_STATE_MACHINE:
519 				MlmeCntlMachinePerformAction(pAd,
520 							     &pAd->Mlme.
521 							     CntlMachine, Elem);
522 				break;
523 			case WPA_PSK_STATE_MACHINE:
524 				StateMachinePerformAction(pAd,
525 							  &pAd->Mlme.
526 							  WpaPskMachine, Elem);
527 				break;
528 
529 			case ACTION_STATE_MACHINE:
530 				StateMachinePerformAction(pAd,
531 							  &pAd->Mlme.ActMachine,
532 							  Elem);
533 				break;
534 
535 			case WPA_STATE_MACHINE:
536 				StateMachinePerformAction(pAd,
537 							  &pAd->Mlme.WpaMachine,
538 							  Elem);
539 				break;
540 
541 			default:
542 				DBGPRINT(RT_DEBUG_TRACE,
543 					 ("ERROR: Illegal machine %ld in MlmeHandler()\n",
544 					  Elem->Machine));
545 				break;
546 			}	/* end of switch */
547 
548 			/* free MLME element */
549 			Elem->Occupied = FALSE;
550 			Elem->MsgLen = 0;
551 
552 		} else {
553 			DBGPRINT_ERR("MlmeHandler: MlmeQueue empty\n");
554 		}
555 	}
556 
557 	NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
558 	pAd->Mlme.bRunning = FALSE;
559 	NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
560 }
561 
562 /*
563 	==========================================================================
564 	Description:
565 		Destructor of MLME (Destroy queue, state machine, spin lock and timer)
566 	Parameters:
567 		Adapter - NIC Adapter pointer
568 	Post:
569 		The MLME task will no longer work properly
570 
571 	IRQL = PASSIVE_LEVEL
572 
573 	==========================================================================
574  */
MlmeHalt(struct rt_rtmp_adapter * pAd)575 void MlmeHalt(struct rt_rtmp_adapter *pAd)
576 {
577 	BOOLEAN Cancelled;
578 
579 	DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
580 
581 	if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
582 		/* disable BEACON generation and other BEACON related hardware timers */
583 		AsicDisableSync(pAd);
584 	}
585 
586 	{
587 		/* Cancel pending timers */
588 		RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
589 		RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
590 		RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
591 		RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
592 		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
593 		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
594 
595 #ifdef RTMP_MAC_PCI
596 		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
597 		    && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) {
598 			RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
599 			RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
600 		}
601 #endif /* RTMP_MAC_PCI // */
602 
603 		RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
604 
605 #ifdef RTMP_MAC_USB
606 		RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
607 #endif /* RTMP_MAC_USB // */
608 	}
609 
610 	RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
611 	RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
612 
613 	if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
614 		struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps;
615 
616 		/* Set LED */
617 		RTMPSetLED(pAd, LED_HALT);
618 		RTMPSetSignalLED(pAd, -100);	/* Force signal strength Led to be turned off, firmware is not done it. */
619 #ifdef RTMP_MAC_USB
620 		{
621 			LED_CFG_STRUC LedCfg;
622 			RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
623 			LedCfg.field.LedPolar = 0;
624 			LedCfg.field.RLedMode = 0;
625 			LedCfg.field.GLedMode = 0;
626 			LedCfg.field.YLedMode = 0;
627 			RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
628 		}
629 #endif /* RTMP_MAC_USB // */
630 
631 		if (pChipOps->AsicHaltAction)
632 			pChipOps->AsicHaltAction(pAd);
633 	}
634 
635 	RTMPusecDelay(5000);	/*  5 msec to guarantee Ant Diversity timer canceled */
636 
637 	MlmeQueueDestroy(&pAd->Mlme.Queue);
638 	NdisFreeSpinLock(&pAd->Mlme.TaskLock);
639 
640 	DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
641 }
642 
MlmeResetRalinkCounters(struct rt_rtmp_adapter * pAd)643 void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd)
644 {
645 	pAd->RalinkCounters.LastOneSecRxOkDataCnt =
646 	    pAd->RalinkCounters.OneSecRxOkDataCnt;
647 	/* clear all OneSecxxx counters. */
648 	pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
649 	pAd->RalinkCounters.OneSecFalseCCACnt = 0;
650 	pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
651 	pAd->RalinkCounters.OneSecRxOkCnt = 0;
652 	pAd->RalinkCounters.OneSecTxFailCount = 0;
653 	pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
654 	pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
655 	pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
656 	pAd->RalinkCounters.OneSecReceivedByteCount = 0;
657 	pAd->RalinkCounters.OneSecTransmittedByteCount = 0;
658 
659 	/* TODO: for debug only. to be removed */
660 	pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
661 	pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
662 	pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
663 	pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
664 	pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
665 	pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
666 	pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
667 	pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
668 	pAd->RalinkCounters.OneSecTxDoneCount = 0;
669 	pAd->RalinkCounters.OneSecRxCount = 0;
670 	pAd->RalinkCounters.OneSecTxAggregationCount = 0;
671 	pAd->RalinkCounters.OneSecRxAggregationCount = 0;
672 
673 	return;
674 }
675 
676 /*
677 	==========================================================================
678 	Description:
679 		This routine is executed periodically to -
680 		1. Decide if it's a right time to turn on PwrMgmt bit of all
681 		   outgoiing frames
682 		2. Calculate ChannelQuality based on statistics of the last
683 		   period, so that TX rate won't toggling very frequently between a
684 		   successful TX and a failed TX.
685 		3. If the calculated ChannelQuality indicated current connection not
686 		   healthy, then a ROAMing attempt is tried here.
687 
688 	IRQL = DISPATCH_LEVEL
689 
690 	==========================================================================
691  */
692 #define ADHOC_BEACON_LOST_TIME		(8*OS_HZ)	/* 8 sec */
MlmePeriodicExec(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)693 void MlmePeriodicExec(void *SystemSpecific1,
694 		      void *FunctionContext,
695 		      void *SystemSpecific2, void *SystemSpecific3)
696 {
697 	unsigned long TxTotalCnt;
698 	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
699 
700 #ifdef RTMP_MAC_PCI
701 	{
702 		/* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */
703 		/* Move code to here, because following code will return when radio is off */
704 		if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) ==
705 		     0) && (pAd->StaCfg.bHardwareRadio == TRUE)
706 		    && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
707 		    && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
708 		    /*&&(pAd->bPCIclkOff == FALSE) */
709 		    ) {
710 			u32 data = 0;
711 
712 			/* Read GPIO pin2 as Hardware controlled radio state */
713 #ifndef RT3090
714 			RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
715 #endif /* RT3090 // */
716 /*KH(PCIE PS):Added based on Jane<-- */
717 #ifdef RT3090
718 /* Read GPIO pin2 as Hardware controlled radio state */
719 /* We need to Read GPIO if HW said so no mater what advance power saving */
720 			if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
721 			    &&
722 			    (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
723 			    && (pAd->StaCfg.PSControl.field.EnablePSinIdle ==
724 				TRUE)) {
725 				/* Want to make sure device goes to L0 state before reading register. */
726 				RTMPPCIeLinkCtrlValueRestore(pAd, 0);
727 				RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
728 				RTMPPCIeLinkCtrlSetting(pAd, 3);
729 			} else
730 				RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
731 #endif /* RT3090 // */
732 /*KH(PCIE PS):Added based on Jane--> */
733 
734 			if (data & 0x04) {
735 				pAd->StaCfg.bHwRadio = TRUE;
736 			} else {
737 				pAd->StaCfg.bHwRadio = FALSE;
738 			}
739 			if (pAd->StaCfg.bRadio !=
740 			    (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) {
741 				pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio
742 						      && pAd->StaCfg.bSwRadio);
743 				if (pAd->StaCfg.bRadio == TRUE) {
744 					MlmeRadioOn(pAd);
745 					/* Update extra information */
746 					pAd->ExtraInfo = EXTRA_INFO_CLEAR;
747 				} else {
748 					MlmeRadioOff(pAd);
749 					/* Update extra information */
750 					pAd->ExtraInfo = HW_RADIO_OFF;
751 				}
752 			}
753 		}
754 	}
755 #endif /* RTMP_MAC_PCI // */
756 
757 	/* Do nothing if the driver is starting halt state. */
758 	/* This might happen when timer already been fired before cancel timer with mlmehalt */
759 	if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
760 				  fRTMP_ADAPTER_RADIO_OFF |
761 				  fRTMP_ADAPTER_RADIO_MEASUREMENT |
762 				  fRTMP_ADAPTER_RESET_IN_PROGRESS))))
763 		return;
764 
765 	RTMP_MLME_PRE_SANITY_CHECK(pAd);
766 
767 	{
768 		/* Do nothing if monitor mode is on */
769 		if (MONITOR_ON(pAd))
770 			return;
771 
772 		if (pAd->Mlme.PeriodicRound & 0x1) {
773 			/* This is the fix for wifi 11n extension channel overlapping test case.  for 2860D */
774 			if (((pAd->MACVersion & 0xffff) == 0x0101) &&
775 			    (STA_TGN_WIFI_ON(pAd)) &&
776 			    (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
777 			{
778 				RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
779 				pAd->CommonCfg.IOTestParm.bToggle = TRUE;
780 			} else if ((STA_TGN_WIFI_ON(pAd)) &&
781 				   ((pAd->MACVersion & 0xffff) == 0x0101)) {
782 				RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
783 				pAd->CommonCfg.IOTestParm.bToggle = FALSE;
784 			}
785 		}
786 	}
787 
788 	pAd->bUpdateBcnCntDone = FALSE;
789 
790 /*      RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */
791 	pAd->Mlme.PeriodicRound++;
792 
793 #ifdef RTMP_MAC_USB
794 	/* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */
795 	NICUpdateFifoStaCounters(pAd);
796 #endif /* RTMP_MAC_USB // */
797 
798 	/* execute every 500ms */
799 	if ((pAd->Mlme.PeriodicRound % 5 == 0)
800 	    && RTMPAutoRateSwitchCheck(pAd)
801 	    /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ )
802 	{
803 		/* perform dynamic tx rate switching based on past TX history */
804 		{
805 			if ((OPSTATUS_TEST_FLAG
806 			     (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
807 			    )
808 			    && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
809 				MlmeDynamicTxRateSwitching(pAd);
810 		}
811 	}
812 	/* Normal 1 second Mlme PeriodicExec. */
813 	if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) {
814 		pAd->Mlme.OneSecPeriodicRound++;
815 
816 		/*ORIBATimerTimeout(pAd); */
817 
818 		/* Media status changed, report to NDIS */
819 		if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) {
820 			RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
821 			if (OPSTATUS_TEST_FLAG
822 			    (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
823 				pAd->IndicateMediaState =
824 				    NdisMediaStateConnected;
825 				RTMP_IndicateMediaState(pAd);
826 
827 			} else {
828 				pAd->IndicateMediaState =
829 				    NdisMediaStateDisconnected;
830 				RTMP_IndicateMediaState(pAd);
831 			}
832 		}
833 
834 		NdisGetSystemUpTime(&pAd->Mlme.Now32);
835 
836 		/* add the most up-to-date h/w raw counters into software variable, so that */
837 		/* the dynamic tuning mechanism below are based on most up-to-date information */
838 		NICUpdateRawCounters(pAd);
839 
840 #ifdef RTMP_MAC_USB
841 		RTUSBWatchDog(pAd);
842 #endif /* RTMP_MAC_USB // */
843 
844 		/* Need statistics after read counter. So put after NICUpdateRawCounters */
845 		ORIBATimerTimeout(pAd);
846 
847 		/* if MGMT RING is full more than twice within 1 second, we consider there's */
848 		/* a hardware problem stucking the TX path. In this case, try a hardware reset */
849 		/* to recover the system */
850 		/*      if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */
851 		/*              RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */
852 		/*      else */
853 		/*              pAd->RalinkCounters.MgmtRingFullCount = 0; */
854 
855 		/* The time period for checking antenna is according to traffic */
856 		{
857 			if (pAd->Mlme.bEnableAutoAntennaCheck) {
858 				TxTotalCnt =
859 				    pAd->RalinkCounters.OneSecTxNoRetryOkCount +
860 				    pAd->RalinkCounters.OneSecTxRetryOkCount +
861 				    pAd->RalinkCounters.OneSecTxFailCount;
862 
863 				/* dynamic adjust antenna evaluation period according to the traffic */
864 				if (TxTotalCnt > 50) {
865 					if (pAd->Mlme.OneSecPeriodicRound %
866 					    10 == 0) {
867 						AsicEvaluateRxAnt(pAd);
868 					}
869 				} else {
870 					if (pAd->Mlme.OneSecPeriodicRound % 3 ==
871 					    0) {
872 						AsicEvaluateRxAnt(pAd);
873 					}
874 				}
875 			}
876 		}
877 
878 		STAMlmePeriodicExec(pAd);
879 
880 		MlmeResetRalinkCounters(pAd);
881 
882 		{
883 #ifdef RTMP_MAC_PCI
884 			if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
885 			    && (pAd->bPCIclkOff == FALSE))
886 #endif /* RTMP_MAC_PCI // */
887 			{
888 				/* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */
889 				/* and sending CTS-to-self over and over. */
890 				/* Software Patch Solution: */
891 				/* 1. Polling debug state register 0x10F4 every one second. */
892 				/* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */
893 				/* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */
894 
895 				u32 MacReg = 0;
896 
897 				RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
898 				if (((MacReg & 0x20000000) && (MacReg & 0x80))
899 				    || ((MacReg & 0x20000000)
900 					&& (MacReg & 0x20))) {
901 					RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
902 					RTMPusecDelay(1);
903 					RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
904 
905 					DBGPRINT(RT_DEBUG_WARN,
906 						 ("Warning, MAC specific condition occurs \n"));
907 				}
908 			}
909 		}
910 
911 		RTMP_MLME_HANDLER(pAd);
912 	}
913 
914 	pAd->bUpdateBcnCntDone = FALSE;
915 }
916 
917 /*
918 	==========================================================================
919 	Validate SSID for connection try and rescan purpose
920 	Valid SSID will have visible chars only.
921 	The valid length is from 0 to 32.
922 	IRQL = DISPATCH_LEVEL
923 	==========================================================================
924  */
MlmeValidateSSID(u8 * pSsid,u8 SsidLen)925 BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen)
926 {
927 	int index;
928 
929 	if (SsidLen > MAX_LEN_OF_SSID)
930 		return (FALSE);
931 
932 	/* Check each character value */
933 	for (index = 0; index < SsidLen; index++) {
934 		if (pSsid[index] < 0x20)
935 			return (FALSE);
936 	}
937 
938 	/* All checked */
939 	return (TRUE);
940 }
941 
MlmeSelectTxRateTable(struct rt_rtmp_adapter * pAd,struct rt_mac_table_entry * pEntry,u8 ** ppTable,u8 * pTableSize,u8 * pInitTxRateIdx)942 void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd,
943 			   struct rt_mac_table_entry *pEntry,
944 			   u8 ** ppTable,
945 			   u8 *pTableSize, u8 *pInitTxRateIdx)
946 {
947 	do {
948 		/* decide the rate table for tuning */
949 		if (pAd->CommonCfg.TxRateTableSize > 0) {
950 			*ppTable = RateSwitchTable;
951 			*pTableSize = RateSwitchTable[0];
952 			*pInitTxRateIdx = RateSwitchTable[1];
953 
954 			break;
955 		}
956 
957 		if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) {
958 			if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) {	/* 11N 1S Adhoc */
959 				*ppTable = RateSwitchTable11N1S;
960 				*pTableSize = RateSwitchTable11N1S[0];
961 				*pInitTxRateIdx = RateSwitchTable11N1S[1];
962 
963 			} else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) {	/* 11N 2S Adhoc */
964 				if (pAd->LatchRfRegs.Channel <= 14) {
965 					*ppTable = RateSwitchTable11N2S;
966 					*pTableSize = RateSwitchTable11N2S[0];
967 					*pInitTxRateIdx =
968 					    RateSwitchTable11N2S[1];
969 				} else {
970 					*ppTable = RateSwitchTable11N2SForABand;
971 					*pTableSize =
972 					    RateSwitchTable11N2SForABand[0];
973 					*pInitTxRateIdx =
974 					    RateSwitchTable11N2SForABand[1];
975 				}
976 
977 			} else if ((pEntry->RateLen == 4)
978 				   && (pEntry->HTCapability.MCSSet[0] == 0)
979 				   && (pEntry->HTCapability.MCSSet[1] == 0)
980 			    ) {
981 				*ppTable = RateSwitchTable11B;
982 				*pTableSize = RateSwitchTable11B[0];
983 				*pInitTxRateIdx = RateSwitchTable11B[1];
984 
985 			} else if (pAd->LatchRfRegs.Channel <= 14) {
986 				*ppTable = RateSwitchTable11BG;
987 				*pTableSize = RateSwitchTable11BG[0];
988 				*pInitTxRateIdx = RateSwitchTable11BG[1];
989 
990 			} else {
991 				*ppTable = RateSwitchTable11G;
992 				*pTableSize = RateSwitchTable11G[0];
993 				*pInitTxRateIdx = RateSwitchTable11G[1];
994 
995 			}
996 			break;
997 		}
998 		/*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
999 		/*      ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1000 		if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) {	/* 11BGN 1S AP */
1001 			*ppTable = RateSwitchTable11BGN1S;
1002 			*pTableSize = RateSwitchTable11BGN1S[0];
1003 			*pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1004 
1005 			break;
1006 		}
1007 		/*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
1008 		/*      (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1009 		if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) {	/* 11BGN 2S AP */
1010 			if (pAd->LatchRfRegs.Channel <= 14) {
1011 				*ppTable = RateSwitchTable11BGN2S;
1012 				*pTableSize = RateSwitchTable11BGN2S[0];
1013 				*pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1014 
1015 			} else {
1016 				*ppTable = RateSwitchTable11BGN2SForABand;
1017 				*pTableSize = RateSwitchTable11BGN2SForABand[0];
1018 				*pInitTxRateIdx =
1019 				    RateSwitchTable11BGN2SForABand[1];
1020 
1021 			}
1022 			break;
1023 		}
1024 		/*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1025 		if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) {	/* 11N 1S AP */
1026 			*ppTable = RateSwitchTable11N1S;
1027 			*pTableSize = RateSwitchTable11N1S[0];
1028 			*pInitTxRateIdx = RateSwitchTable11N1S[1];
1029 
1030 			break;
1031 		}
1032 		/*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1033 		if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) {	/* 11N 2S AP */
1034 			if (pAd->LatchRfRegs.Channel <= 14) {
1035 				*ppTable = RateSwitchTable11N2S;
1036 				*pTableSize = RateSwitchTable11N2S[0];
1037 				*pInitTxRateIdx = RateSwitchTable11N2S[1];
1038 			} else {
1039 				*ppTable = RateSwitchTable11N2SForABand;
1040 				*pTableSize = RateSwitchTable11N2SForABand[0];
1041 				*pInitTxRateIdx =
1042 				    RateSwitchTable11N2SForABand[1];
1043 			}
1044 
1045 			break;
1046 		}
1047 		/*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1048 		if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode == PHY_11B)
1049 		    /*Iverson mark for Adhoc b mode,sta will use rate 54  Mbps when connect with sta b/g/n mode */
1050 		    /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */
1051 		    ) {		/* B only AP */
1052 			*ppTable = RateSwitchTable11B;
1053 			*pTableSize = RateSwitchTable11B[0];
1054 			*pInitTxRateIdx = RateSwitchTable11B[1];
1055 
1056 			break;
1057 		}
1058 		/*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1059 		if ((pEntry->RateLen > 8)
1060 		    && (pEntry->HTCapability.MCSSet[0] == 0)
1061 		    && (pEntry->HTCapability.MCSSet[1] == 0)
1062 		    ) {		/* B/G  mixed AP */
1063 			*ppTable = RateSwitchTable11BG;
1064 			*pTableSize = RateSwitchTable11BG[0];
1065 			*pInitTxRateIdx = RateSwitchTable11BG[1];
1066 
1067 			break;
1068 		}
1069 		/*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1070 		if ((pEntry->RateLen == 8)
1071 		    && (pEntry->HTCapability.MCSSet[0] == 0)
1072 		    && (pEntry->HTCapability.MCSSet[1] == 0)
1073 		    ) {		/* G only AP */
1074 			*ppTable = RateSwitchTable11G;
1075 			*pTableSize = RateSwitchTable11G[0];
1076 			*pInitTxRateIdx = RateSwitchTable11G[1];
1077 
1078 			break;
1079 		}
1080 
1081 		{
1082 			/*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1083 			if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) {	/* Legacy mode */
1084 				if (pAd->CommonCfg.MaxTxRate <= RATE_11) {
1085 					*ppTable = RateSwitchTable11B;
1086 					*pTableSize = RateSwitchTable11B[0];
1087 					*pInitTxRateIdx = RateSwitchTable11B[1];
1088 				} else if ((pAd->CommonCfg.MaxTxRate > RATE_11)
1089 					   && (pAd->CommonCfg.MinTxRate >
1090 					       RATE_11)) {
1091 					*ppTable = RateSwitchTable11G;
1092 					*pTableSize = RateSwitchTable11G[0];
1093 					*pInitTxRateIdx = RateSwitchTable11G[1];
1094 
1095 				} else {
1096 					*ppTable = RateSwitchTable11BG;
1097 					*pTableSize = RateSwitchTable11BG[0];
1098 					*pInitTxRateIdx =
1099 					    RateSwitchTable11BG[1];
1100 				}
1101 				break;
1102 			}
1103 			if (pAd->LatchRfRegs.Channel <= 14) {
1104 				if (pAd->CommonCfg.TxStream == 1) {
1105 					*ppTable = RateSwitchTable11N1S;
1106 					*pTableSize = RateSwitchTable11N1S[0];
1107 					*pInitTxRateIdx =
1108 					    RateSwitchTable11N1S[1];
1109 					DBGPRINT_RAW(RT_DEBUG_ERROR,
1110 						     ("DRS: unknown mode,default use 11N 1S AP \n"));
1111 				} else {
1112 					*ppTable = RateSwitchTable11N2S;
1113 					*pTableSize = RateSwitchTable11N2S[0];
1114 					*pInitTxRateIdx =
1115 					    RateSwitchTable11N2S[1];
1116 					DBGPRINT_RAW(RT_DEBUG_ERROR,
1117 						     ("DRS: unknown mode,default use 11N 2S AP \n"));
1118 				}
1119 			} else {
1120 				if (pAd->CommonCfg.TxStream == 1) {
1121 					*ppTable = RateSwitchTable11N1S;
1122 					*pTableSize = RateSwitchTable11N1S[0];
1123 					*pInitTxRateIdx =
1124 					    RateSwitchTable11N1S[1];
1125 					DBGPRINT_RAW(RT_DEBUG_ERROR,
1126 						     ("DRS: unknown mode,default use 11N 1S AP \n"));
1127 				} else {
1128 					*ppTable = RateSwitchTable11N2SForABand;
1129 					*pTableSize =
1130 					    RateSwitchTable11N2SForABand[0];
1131 					*pInitTxRateIdx =
1132 					    RateSwitchTable11N2SForABand[1];
1133 					DBGPRINT_RAW(RT_DEBUG_ERROR,
1134 						     ("DRS: unknown mode,default use 11N 2S AP \n"));
1135 				}
1136 			}
1137 			DBGPRINT_RAW(RT_DEBUG_ERROR,
1138 				     ("DRS: unknown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1139 				      pAd->StaActive.SupRateLen,
1140 				      pAd->StaActive.ExtRateLen,
1141 				      pAd->StaActive.SupportedPhyInfo.MCSSet[0],
1142 				      pAd->StaActive.SupportedPhyInfo.
1143 				      MCSSet[1]));
1144 		}
1145 	} while (FALSE);
1146 }
1147 
STAMlmePeriodicExec(struct rt_rtmp_adapter * pAd)1148 void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd)
1149 {
1150 	unsigned long TxTotalCnt;
1151 	int i;
1152 
1153 	/*
1154 	   We return here in ATE mode, because the statistics
1155 	   that ATE need are not collected via this routine.
1156 	 */
1157 #if defined(RT305x)||defined(RT3070)
1158 	/* request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18 */
1159 	if (!pAd->CommonCfg.HighPowerPatchDisabled) {
1160 #ifdef RT3070
1161 		if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201)))
1162 #endif /* RT3070 // */
1163 		{
1164 			if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0)
1165 			    && (pAd->StaCfg.RssiSample.AvgRssi0 >
1166 				(pAd->BbpRssiToDbmDelta - 35))) {
1167 				RT30xxWriteRFRegister(pAd, RF_R27, 0x20);
1168 			} else {
1169 				RT30xxWriteRFRegister(pAd, RF_R27, 0x23);
1170 			}
1171 		}
1172 	}
1173 #endif
1174 #ifdef PCIE_PS_SUPPORT
1175 /* don't perform idle-power-save mechanism within 3 min after driver initialization. */
1176 /* This can make rebooter test more robust */
1177 	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
1178 		if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
1179 		    && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1180 		    && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1181 		    && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) {
1182 			if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) {
1183 				if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1184 				    TRUE) {
1185 					DBGPRINT(RT_DEBUG_TRACE,
1186 						 ("%s\n", __func__));
1187 					RT28xxPciAsicRadioOff(pAd,
1188 							      GUI_IDLE_POWER_SAVE,
1189 							      0);
1190 				} else {
1191 					AsicSendCommandToMcu(pAd, 0x30,
1192 							     PowerSafeCID, 0xff,
1193 							     0x2);
1194 					/* Wait command success */
1195 					AsicCheckCommanOk(pAd, PowerSafeCID);
1196 					RTMP_SET_FLAG(pAd,
1197 						      fRTMP_ADAPTER_IDLE_RADIO_OFF);
1198 					DBGPRINT(RT_DEBUG_TRACE,
1199 						 ("PSM - rt30xx Issue Sleep command)\n"));
1200 				}
1201 			} else if (pAd->Mlme.OneSecPeriodicRound > 180) {
1202 				if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1203 				    TRUE) {
1204 					DBGPRINT(RT_DEBUG_TRACE,
1205 						 ("%s\n", __func__));
1206 					RT28xxPciAsicRadioOff(pAd,
1207 							      GUI_IDLE_POWER_SAVE,
1208 							      0);
1209 				} else {
1210 					AsicSendCommandToMcu(pAd, 0x30,
1211 							     PowerSafeCID, 0xff,
1212 							     0x02);
1213 					/* Wait command success */
1214 					AsicCheckCommanOk(pAd, PowerSafeCID);
1215 					RTMP_SET_FLAG(pAd,
1216 						      fRTMP_ADAPTER_IDLE_RADIO_OFF);
1217 					DBGPRINT(RT_DEBUG_TRACE,
1218 						 ("PSM -  rt28xx Issue Sleep command)\n"));
1219 				}
1220 			}
1221 		} else {
1222 			DBGPRINT(RT_DEBUG_TRACE,
1223 				 ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1224 				  pAd->CommonCfg.SsidLen,
1225 				  pAd->CommonCfg.Ssid[0],
1226 				  pAd->CommonCfg.Ssid[1],
1227 				  pAd->CommonCfg.Ssid[2],
1228 				  pAd->CommonCfg.Ssid[3], pAd->MlmeAux.SsidLen,
1229 				  pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1],
1230 				  pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
1231 		}
1232 	}
1233 #endif /* PCIE_PS_SUPPORT // */
1234 
1235 	if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) {
1236 		/* WPA MIC error should block association attempt for 60 seconds */
1237 		if (pAd->StaCfg.bBlockAssoc &&
1238 		    RTMP_TIME_AFTER(pAd->Mlme.Now32,
1239 				    pAd->StaCfg.LastMicErrorTime +
1240 				    (60 * OS_HZ)))
1241 			pAd->StaCfg.bBlockAssoc = FALSE;
1242 	}
1243 
1244 	if ((pAd->PreMediaState != pAd->IndicateMediaState)
1245 	    && (pAd->CommonCfg.bWirelessEvent)) {
1246 		if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1247 			RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1248 					      pAd->MacTab.Content[BSSID_WCID].
1249 					      Addr, BSS0, 0);
1250 		}
1251 		pAd->PreMediaState = pAd->IndicateMediaState;
1252 	}
1253 
1254 	if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) {
1255 	} else {
1256 		AsicStaBbpTuning(pAd);
1257 	}
1258 
1259 	TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1260 	    pAd->RalinkCounters.OneSecTxRetryOkCount +
1261 	    pAd->RalinkCounters.OneSecTxFailCount;
1262 
1263 	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
1264 		/* update channel quality for Roaming and UI LinkQuality display */
1265 		MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32);
1266 	}
1267 	/* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */
1268 	/* Radio is currently in noisy environment */
1269 	if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1270 		AsicAdjustTxPower(pAd);
1271 
1272 	if (INFRA_ON(pAd)) {
1273 
1274 		/* Is PSM bit consistent with user power management policy? */
1275 		/* This is the only place that will set PSM bit ON. */
1276 		if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1277 			MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1278 
1279 		pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1280 
1281 		if ((RTMP_TIME_AFTER
1282 		     (pAd->Mlme.Now32,
1283 		      pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ)))
1284 		    &&
1285 		    (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1286 		    &&
1287 		    (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) <
1288 		      600))) {
1289 			RTMPSetAGCInitValue(pAd, BW_20);
1290 			DBGPRINT(RT_DEBUG_TRACE,
1291 				 ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n",
1292 				  (0x2E + GET_LNA_GAIN(pAd))));
1293 		}
1294 		/*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */
1295 		/*    (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */
1296 		{
1297 			if (pAd->CommonCfg.bAPSDCapable
1298 			    && pAd->CommonCfg.APEdcaParm.bAPSDCapable) {
1299 				/* When APSD is enabled, the period changes as 20 sec */
1300 				if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1301 					RTMPSendNullFrame(pAd,
1302 							  pAd->CommonCfg.TxRate,
1303 							  TRUE);
1304 			} else {
1305 				/* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */
1306 				if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) {
1307 					if (pAd->CommonCfg.bWmmCapable)
1308 						RTMPSendNullFrame(pAd,
1309 								  pAd->
1310 								  CommonCfg.
1311 								  TxRate, TRUE);
1312 					else
1313 						RTMPSendNullFrame(pAd,
1314 								  pAd->
1315 								  CommonCfg.
1316 								  TxRate,
1317 								  FALSE);
1318 				}
1319 			}
1320 		}
1321 
1322 		if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) {
1323 			DBGPRINT(RT_DEBUG_TRACE,
1324 				 ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n",
1325 				  pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1326 
1327 			/* Lost AP, send disconnect & link down event */
1328 			LinkDown(pAd, FALSE);
1329 
1330 			RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL,
1331 						0);
1332 
1333 			/* RTMPPatchMacBbpBug(pAd); */
1334 			MlmeAutoReconnectLastSSID(pAd);
1335 		} else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) {
1336 			pAd->RalinkCounters.BadCQIAutoRecoveryCount++;
1337 			DBGPRINT(RT_DEBUG_TRACE,
1338 				 ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n",
1339 				  pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1340 			MlmeAutoReconnectLastSSID(pAd);
1341 		}
1342 
1343 		if (pAd->StaCfg.bAutoRoaming) {
1344 			BOOLEAN rv = FALSE;
1345 			char dBmToRoam = pAd->StaCfg.dBmToRoam;
1346 			char MaxRssi = RTMPMaxRssi(pAd,
1347 						   pAd->StaCfg.RssiSample.
1348 						   LastRssi0,
1349 						   pAd->StaCfg.RssiSample.
1350 						   LastRssi1,
1351 						   pAd->StaCfg.RssiSample.
1352 						   LastRssi2);
1353 
1354 			/* Scanning, ignore Roaming */
1355 			if (!RTMP_TEST_FLAG
1356 			    (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
1357 			    && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1358 			    && (MaxRssi <= dBmToRoam)) {
1359 				DBGPRINT(RT_DEBUG_TRACE,
1360 					 ("Rssi=%d, dBmToRoam=%d\n", MaxRssi,
1361 					  (char)dBmToRoam));
1362 
1363 				/* Add auto seamless roaming */
1364 				if (rv == FALSE)
1365 					rv = MlmeCheckForFastRoaming(pAd);
1366 
1367 				if (rv == FALSE) {
1368 					if ((pAd->StaCfg.LastScanTime +
1369 					     10 * OS_HZ) < pAd->Mlme.Now32) {
1370 						DBGPRINT(RT_DEBUG_TRACE,
1371 							 ("MMCHK - Roaming, No eligible entry, try new scan!\n"));
1372 						pAd->StaCfg.ScanCnt = 2;
1373 						pAd->StaCfg.LastScanTime =
1374 						    pAd->Mlme.Now32;
1375 						MlmeAutoScan(pAd);
1376 					}
1377 				}
1378 			}
1379 		}
1380 	} else if (ADHOC_ON(pAd)) {
1381 		/* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */
1382 		/* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */
1383 		/* join later. */
1384 		if (RTMP_TIME_AFTER
1385 		    (pAd->Mlme.Now32,
1386 		     pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)
1387 		    && OPSTATUS_TEST_FLAG(pAd,
1388 					  fOP_STATUS_MEDIA_STATE_CONNECTED)) {
1389 			struct rt_mlme_start_req StartReq;
1390 
1391 			DBGPRINT(RT_DEBUG_TRACE,
1392 				 ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1393 			LinkDown(pAd, FALSE);
1394 
1395 			StartParmFill(pAd, &StartReq,
1396 				      (char *) pAd->MlmeAux.Ssid,
1397 				      pAd->MlmeAux.SsidLen);
1398 			MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ,
1399 				    sizeof(struct rt_mlme_start_req), &StartReq);
1400 			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1401 		}
1402 
1403 		for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1404 			struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i];
1405 
1406 			if (pEntry->ValidAsCLI == FALSE)
1407 				continue;
1408 
1409 			if (RTMP_TIME_AFTER
1410 			    (pAd->Mlme.Now32,
1411 			     pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1412 				MacTableDeleteEntry(pAd, pEntry->Aid,
1413 						    pEntry->Addr);
1414 		}
1415 	} else			/* no INFRA nor ADHOC connection */
1416 	{
1417 
1418 		if (pAd->StaCfg.bScanReqIsFromWebUI &&
1419 		    RTMP_TIME_BEFORE(pAd->Mlme.Now32,
1420 				     pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
1421 			goto SKIP_AUTO_SCAN_CONN;
1422 		else
1423 			pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1424 
1425 		if ((pAd->StaCfg.bAutoReconnect == TRUE)
1426 		    && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1427 		    &&
1428 		    (MlmeValidateSSID
1429 		     (pAd->MlmeAux.AutoReconnectSsid,
1430 		      pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1431 			if ((pAd->ScanTab.BssNr == 0)
1432 			    && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) {
1433 				struct rt_mlme_scan_req ScanReq;
1434 
1435 				if (RTMP_TIME_AFTER
1436 				    (pAd->Mlme.Now32,
1437 				     pAd->StaCfg.LastScanTime + (10 * OS_HZ))) {
1438 					DBGPRINT(RT_DEBUG_TRACE,
1439 						 ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n",
1440 						  pAd->MlmeAux.
1441 						  AutoReconnectSsid));
1442 					ScanParmFill(pAd, &ScanReq,
1443 						     (char *)pAd->MlmeAux.
1444 						     AutoReconnectSsid,
1445 						     pAd->MlmeAux.
1446 						     AutoReconnectSsidLen,
1447 						     BSS_ANY, SCAN_ACTIVE);
1448 					MlmeEnqueue(pAd, SYNC_STATE_MACHINE,
1449 						    MT2_MLME_SCAN_REQ,
1450 						    sizeof
1451 						    (struct rt_mlme_scan_req),
1452 						    &ScanReq);
1453 					pAd->Mlme.CntlMachine.CurrState =
1454 					    CNTL_WAIT_OID_LIST_SCAN;
1455 					/* Reset Missed scan number */
1456 					pAd->StaCfg.LastScanTime =
1457 					    pAd->Mlme.Now32;
1458 				} else if (pAd->StaCfg.BssType == BSS_ADHOC)	/* Quit the forever scan when in a very clean room */
1459 					MlmeAutoReconnectLastSSID(pAd);
1460 			} else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1461 				if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) {
1462 					MlmeAutoScan(pAd);
1463 					pAd->StaCfg.LastScanTime =
1464 					    pAd->Mlme.Now32;
1465 				} else {
1466 					MlmeAutoReconnectLastSSID(pAd);
1467 				}
1468 			}
1469 		}
1470 	}
1471 
1472 SKIP_AUTO_SCAN_CONN:
1473 
1474 	if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap != 0)
1475 	    && (pAd->MacTab.fAnyBASession == FALSE)) {
1476 		pAd->MacTab.fAnyBASession = TRUE;
1477 		AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE,
1478 				  FALSE);
1479 	} else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap == 0)
1480 		   && (pAd->MacTab.fAnyBASession == TRUE)) {
1481 		pAd->MacTab.fAnyBASession = FALSE;
1482 		AsicUpdateProtect(pAd,
1483 				  pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1484 				  OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1485 	}
1486 
1487 	return;
1488 }
1489 
1490 /* Link down report */
LinkDownExec(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)1491 void LinkDownExec(void *SystemSpecific1,
1492 		  void *FunctionContext,
1493 		  void *SystemSpecific2, void *SystemSpecific3)
1494 {
1495 	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
1496 
1497 	if (pAd != NULL) {
1498 		struct rt_mlme_disassoc_req DisassocReq;
1499 
1500 		if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
1501 		    (INFRA_ON(pAd))) {
1502 			DBGPRINT(RT_DEBUG_TRACE,
1503 				 ("LinkDownExec(): disassociate with current AP...\n"));
1504 			DisassocParmFill(pAd, &DisassocReq,
1505 					 pAd->CommonCfg.Bssid,
1506 					 REASON_DISASSOC_STA_LEAVING);
1507 			MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
1508 				    MT2_MLME_DISASSOC_REQ,
1509 				    sizeof(struct rt_mlme_disassoc_req),
1510 				    &DisassocReq);
1511 			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1512 
1513 			pAd->IndicateMediaState = NdisMediaStateDisconnected;
1514 			RTMP_IndicateMediaState(pAd);
1515 			pAd->ExtraInfo = GENERAL_LINK_DOWN;
1516 		}
1517 	}
1518 }
1519 
1520 /* IRQL = DISPATCH_LEVEL */
MlmeAutoScan(struct rt_rtmp_adapter * pAd)1521 void MlmeAutoScan(struct rt_rtmp_adapter *pAd)
1522 {
1523 	/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1524 	if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1525 		DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1526 		MlmeEnqueue(pAd,
1527 			    MLME_CNTL_STATE_MACHINE,
1528 			    OID_802_11_BSSID_LIST_SCAN,
1529 			    pAd->MlmeAux.AutoReconnectSsidLen,
1530 			    pAd->MlmeAux.AutoReconnectSsid);
1531 		RTMP_MLME_HANDLER(pAd);
1532 	}
1533 }
1534 
1535 /* IRQL = DISPATCH_LEVEL */
MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter * pAd)1536 void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd)
1537 {
1538 	if (pAd->StaCfg.bAutoConnectByBssid) {
1539 		DBGPRINT(RT_DEBUG_TRACE,
1540 			("Driver auto reconnect to last OID_802_11_BSSID "
1541 				"setting - %pM\n", pAd->MlmeAux.Bssid));
1542 
1543 		pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1544 		MlmeEnqueue(pAd,
1545 			    MLME_CNTL_STATE_MACHINE,
1546 			    OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid);
1547 
1548 		pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1549 
1550 		RTMP_MLME_HANDLER(pAd);
1551 	}
1552 	/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1553 	else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1554 		 (MlmeValidateSSID
1555 		  (pAd->MlmeAux.AutoReconnectSsid,
1556 		   pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1557 		struct rt_ndis_802_11_ssid OidSsid;
1558 		OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1559 		NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid,
1560 			       pAd->MlmeAux.AutoReconnectSsidLen);
1561 
1562 		DBGPRINT(RT_DEBUG_TRACE,
1563 			 ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
1564 			  pAd->MlmeAux.AutoReconnectSsid,
1565 			  pAd->MlmeAux.AutoReconnectSsidLen));
1566 		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID,
1567 			    sizeof(struct rt_ndis_802_11_ssid), &OidSsid);
1568 		RTMP_MLME_HANDLER(pAd);
1569 	}
1570 }
1571 
1572 /*
1573 	==========================================================================
1574 	Description:
1575 		This routine checks if there're other APs out there capable for
1576 		roaming. Caller should call this routine only when Link up in INFRA mode
1577 		and channel quality is below CQI_GOOD_THRESHOLD.
1578 
1579 	IRQL = DISPATCH_LEVEL
1580 
1581 	Output:
1582 	==========================================================================
1583  */
MlmeCheckForRoaming(struct rt_rtmp_adapter * pAd,unsigned long Now32)1584 void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32)
1585 {
1586 	u16 i;
1587 	struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1588 	struct rt_bss_entry *pBss;
1589 
1590 	DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1591 	/* put all roaming candidates into RoamTab, and sort in RSSI order */
1592 	BssTableInit(pRoamTab);
1593 	for (i = 0; i < pAd->ScanTab.BssNr; i++) {
1594 		pBss = &pAd->ScanTab.BssEntry[i];
1595 
1596 		if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) <
1597 		    Now32)
1598 			continue;	/* AP disappear */
1599 		if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1600 			continue;	/* RSSI too weak. forget it. */
1601 		if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1602 			continue;	/* skip current AP */
1603 		if (pBss->Rssi <
1604 		    (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1605 			continue;	/* only AP with stronger RSSI is eligible for roaming */
1606 
1607 		/* AP passing all above rules is put into roaming candidate table */
1608 		NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
1609 			       sizeof(struct rt_bss_entry));
1610 		pRoamTab->BssNr += 1;
1611 	}
1612 
1613 	if (pRoamTab->BssNr > 0) {
1614 		/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1615 		if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1616 			pAd->RalinkCounters.PoorCQIRoamingCount++;
1617 			DBGPRINT(RT_DEBUG_TRACE,
1618 				 ("MMCHK - Roaming attempt #%ld\n",
1619 				  pAd->RalinkCounters.PoorCQIRoamingCount));
1620 			MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1621 				    MT2_MLME_ROAMING_REQ, 0, NULL);
1622 			RTMP_MLME_HANDLER(pAd);
1623 		}
1624 	}
1625 	DBGPRINT(RT_DEBUG_TRACE,
1626 		 ("<== MlmeCheckForRoaming(# of candidate= %d)\n",
1627 		  pRoamTab->BssNr));
1628 }
1629 
1630 /*
1631 	==========================================================================
1632 	Description:
1633 		This routine checks if there're other APs out there capable for
1634 		roaming. Caller should call this routine only when link up in INFRA mode
1635 		and channel quality is below CQI_GOOD_THRESHOLD.
1636 
1637 	IRQL = DISPATCH_LEVEL
1638 
1639 	Output:
1640 	==========================================================================
1641  */
MlmeCheckForFastRoaming(struct rt_rtmp_adapter * pAd)1642 BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd)
1643 {
1644 	u16 i;
1645 	struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1646 	struct rt_bss_entry *pBss;
1647 
1648 	DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1649 	/* put all roaming candidates into RoamTab, and sort in RSSI order */
1650 	BssTableInit(pRoamTab);
1651 	for (i = 0; i < pAd->ScanTab.BssNr; i++) {
1652 		pBss = &pAd->ScanTab.BssEntry[i];
1653 
1654 		if ((pBss->Rssi <= -50)
1655 		    && (pBss->Channel == pAd->CommonCfg.Channel))
1656 			continue;	/* RSSI too weak. forget it. */
1657 		if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1658 			continue;	/* skip current AP */
1659 		if (!SSID_EQUAL
1660 		    (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid,
1661 		     pAd->CommonCfg.SsidLen))
1662 			continue;	/* skip different SSID */
1663 		if (pBss->Rssi <
1664 		    (RTMPMaxRssi
1665 		     (pAd, pAd->StaCfg.RssiSample.LastRssi0,
1666 		      pAd->StaCfg.RssiSample.LastRssi1,
1667 		      pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1668 			continue;	/* skip AP without better RSSI */
1669 
1670 		DBGPRINT(RT_DEBUG_TRACE,
1671 			 ("LastRssi0 = %d, pBss->Rssi = %d\n",
1672 			  RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0,
1673 				      pAd->StaCfg.RssiSample.LastRssi1,
1674 				      pAd->StaCfg.RssiSample.LastRssi2),
1675 			  pBss->Rssi));
1676 		/* AP passing all above rules is put into roaming candidate table */
1677 		NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
1678 			       sizeof(struct rt_bss_entry));
1679 		pRoamTab->BssNr += 1;
1680 	}
1681 
1682 	DBGPRINT(RT_DEBUG_TRACE,
1683 		 ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1684 	if (pRoamTab->BssNr > 0) {
1685 		/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1686 		if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1687 			pAd->RalinkCounters.PoorCQIRoamingCount++;
1688 			DBGPRINT(RT_DEBUG_TRACE,
1689 				 ("MMCHK - Roaming attempt #%ld\n",
1690 				  pAd->RalinkCounters.PoorCQIRoamingCount));
1691 			MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1692 				    MT2_MLME_ROAMING_REQ, 0, NULL);
1693 			RTMP_MLME_HANDLER(pAd);
1694 			return TRUE;
1695 		}
1696 	}
1697 
1698 	return FALSE;
1699 }
1700 
MlmeSetTxRate(struct rt_rtmp_adapter * pAd,struct rt_mac_table_entry * pEntry,struct rt_rtmp_tx_rate_switch * pTxRate)1701 void MlmeSetTxRate(struct rt_rtmp_adapter *pAd,
1702 		   struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate)
1703 {
1704 	u8 MaxMode = MODE_OFDM;
1705 
1706 	MaxMode = MODE_HTGREENFIELD;
1707 
1708 	if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC)
1709 	    && (pAd->Antenna.field.TxPath == 2))
1710 		pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1711 	else
1712 		pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1713 
1714 	if (pTxRate->CurrMCS < MCS_AUTO)
1715 		pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1716 
1717 	if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1718 		pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1719 
1720 	if (ADHOC_ON(pAd)) {
1721 		/* If peer adhoc is b-only mode, we can't send 11g rate. */
1722 		pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1723 		pEntry->HTPhyMode.field.STBC = STBC_NONE;
1724 
1725 		/* */
1726 		/* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */
1727 		/* */
1728 		pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1729 		pEntry->HTPhyMode.field.ShortGI =
1730 		    pAd->StaCfg.HTPhyMode.field.ShortGI;
1731 		pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1732 
1733 		/* Patch speed error in status page */
1734 		pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1735 	} else {
1736 		if (pTxRate->Mode <= MaxMode)
1737 			pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1738 
1739 		if (pTxRate->ShortGI
1740 		    && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1741 			pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1742 		else
1743 			pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1744 
1745 		/* Reexam each bandwidth's SGI support. */
1746 		if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) {
1747 			if ((pEntry->HTPhyMode.field.BW == BW_20)
1748 			    &&
1749 			    (!CLIENT_STATUS_TEST_FLAG
1750 			     (pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1751 				pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1752 			if ((pEntry->HTPhyMode.field.BW == BW_40)
1753 			    &&
1754 			    (!CLIENT_STATUS_TEST_FLAG
1755 			     (pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1756 				pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1757 		}
1758 		/* Turn RTS/CTS rate to 6Mbps. */
1759 		if ((pEntry->HTPhyMode.field.MCS == 0)
1760 		    && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) {
1761 			pEntry->HTPhyMode.field.MCS =
1762 			    pAd->StaCfg.HTPhyMode.field.MCS;
1763 			if (pAd->MacTab.fAnyBASession) {
1764 				AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1765 						  ALLN_SETPROTECT, TRUE,
1766 						  (BOOLEAN) pAd->MlmeAux.
1767 						  AddHtInfo.AddHtInfo2.
1768 						  NonGfPresent);
1769 			} else {
1770 				AsicUpdateProtect(pAd,
1771 						  pAd->MlmeAux.AddHtInfo.
1772 						  AddHtInfo2.OperaionMode,
1773 						  ALLN_SETPROTECT, TRUE,
1774 						  (BOOLEAN) pAd->MlmeAux.
1775 						  AddHtInfo.AddHtInfo2.
1776 						  NonGfPresent);
1777 			}
1778 		} else if ((pEntry->HTPhyMode.field.MCS == 8)
1779 			   && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) {
1780 			pEntry->HTPhyMode.field.MCS =
1781 			    pAd->StaCfg.HTPhyMode.field.MCS;
1782 			if (pAd->MacTab.fAnyBASession) {
1783 				AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1784 						  ALLN_SETPROTECT, TRUE,
1785 						  (BOOLEAN) pAd->MlmeAux.
1786 						  AddHtInfo.AddHtInfo2.
1787 						  NonGfPresent);
1788 			} else {
1789 				AsicUpdateProtect(pAd,
1790 						  pAd->MlmeAux.AddHtInfo.
1791 						  AddHtInfo2.OperaionMode,
1792 						  ALLN_SETPROTECT, TRUE,
1793 						  (BOOLEAN) pAd->MlmeAux.
1794 						  AddHtInfo.AddHtInfo2.
1795 						  NonGfPresent);
1796 			}
1797 		} else if ((pEntry->HTPhyMode.field.MCS != 0)
1798 			   && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) {
1799 			AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1800 					  TRUE,
1801 					  (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1802 					  AddHtInfo2.NonGfPresent);
1803 
1804 		} else if ((pEntry->HTPhyMode.field.MCS != 8)
1805 			   && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) {
1806 			AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1807 					  TRUE,
1808 					  (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1809 					  AddHtInfo2.NonGfPresent);
1810 		}
1811 
1812 		pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1813 		pEntry->HTPhyMode.field.ShortGI =
1814 		    pAd->StaCfg.HTPhyMode.field.ShortGI;
1815 		pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1816 		pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1817 		if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD)
1818 		    && pAd->WIFItestbed.bGreenField)
1819 			pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1820 	}
1821 
1822 	pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word);
1823 }
1824 
1825 /*
1826 	==========================================================================
1827 	Description:
1828 		This routine calculates the acumulated TxPER of eaxh TxRate. And
1829 		according to the calculation result, change CommonCfg.TxRate which
1830 		is the stable TX Rate we expect the Radio situation could sustained.
1831 
1832 		CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1833 	Output:
1834 		CommonCfg.TxRate -
1835 
1836 	IRQL = DISPATCH_LEVEL
1837 
1838 	NOTE:
1839 		call this routine every second
1840 	==========================================================================
1841  */
MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter * pAd)1842 void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd)
1843 {
1844 	u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1845 	unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt;
1846 	unsigned long TxErrorRatio = 0;
1847 	BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
1848 	struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
1849 	u8 *pTable;
1850 	u8 TableSize = 0;
1851 	u8 InitTxRateIdx = 0, TrainUp, TrainDown;
1852 	char Rssi, RssiOffset = 0;
1853 	TX_STA_CNT1_STRUC StaTx1;
1854 	TX_STA_CNT0_STRUC TxStaCnt0;
1855 	unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1856 	struct rt_mac_table_entry *pEntry;
1857 	struct rt_rssi_sample *pRssi = &pAd->StaCfg.RssiSample;
1858 
1859 	/* */
1860 	/* walk through MAC table, see if need to change AP's TX rate toward each entry */
1861 	/* */
1862 	for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1863 		pEntry = &pAd->MacTab.Content[i];
1864 
1865 		/* check if this entry need to switch rate automatically */
1866 		if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1867 			continue;
1868 
1869 		if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) {
1870 			Rssi = RTMPMaxRssi(pAd,
1871 					   pRssi->AvgRssi0,
1872 					   pRssi->AvgRssi1, pRssi->AvgRssi2);
1873 
1874 			/* Update statistic counter */
1875 			RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1876 			RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1877 			pAd->bUpdateBcnCntDone = TRUE;
1878 			TxRetransmit = StaTx1.field.TxRetransmit;
1879 			TxSuccess = StaTx1.field.TxSuccess;
1880 			TxFailCount = TxStaCnt0.field.TxFailCount;
1881 			TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1882 
1883 			pAd->RalinkCounters.OneSecTxRetryOkCount +=
1884 			    StaTx1.field.TxRetransmit;
1885 			pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
1886 			    StaTx1.field.TxSuccess;
1887 			pAd->RalinkCounters.OneSecTxFailCount +=
1888 			    TxStaCnt0.field.TxFailCount;
1889 			pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
1890 			    StaTx1.field.TxSuccess;
1891 			pAd->WlanCounters.RetryCount.u.LowPart +=
1892 			    StaTx1.field.TxRetransmit;
1893 			pAd->WlanCounters.FailedCount.u.LowPart +=
1894 			    TxStaCnt0.field.TxFailCount;
1895 
1896 			/* if no traffic in the past 1-sec period, don't change TX rate, */
1897 			/* but clear all bad history. because the bad history may affect the next */
1898 			/* Chariot throughput test */
1899 			AccuTxTotalCnt =
1900 			    pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1901 			    pAd->RalinkCounters.OneSecTxRetryOkCount +
1902 			    pAd->RalinkCounters.OneSecTxFailCount;
1903 
1904 			if (TxTotalCnt)
1905 				TxErrorRatio =
1906 				    ((TxRetransmit +
1907 				      TxFailCount) * 100) / TxTotalCnt;
1908 		} else {
1909 			if (INFRA_ON(pAd) && (i == 1))
1910 				Rssi = RTMPMaxRssi(pAd,
1911 						   pRssi->AvgRssi0,
1912 						   pRssi->AvgRssi1,
1913 						   pRssi->AvgRssi2);
1914 			else
1915 				Rssi = RTMPMaxRssi(pAd,
1916 						   pEntry->RssiSample.AvgRssi0,
1917 						   pEntry->RssiSample.AvgRssi1,
1918 						   pEntry->RssiSample.AvgRssi2);
1919 
1920 			TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1921 			    pEntry->OneSecTxRetryOkCount +
1922 			    pEntry->OneSecTxFailCount;
1923 
1924 			if (TxTotalCnt)
1925 				TxErrorRatio =
1926 				    ((pEntry->OneSecTxRetryOkCount +
1927 				      pEntry->OneSecTxFailCount) * 100) /
1928 				    TxTotalCnt;
1929 		}
1930 
1931 		if (TxTotalCnt) {
1932 			/*
1933 			   Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1934 			   We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1935 			 */
1936 			if (TxErrorRatio == 100) {
1937 				TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp;
1938 				unsigned long Index;
1939 				unsigned long MACValue;
1940 
1941 				RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1942 				TxRtyCfgtmp.word = TxRtyCfg.word;
1943 				TxRtyCfg.field.LongRtyLimit = 0x0;
1944 				TxRtyCfg.field.ShortRtyLimit = 0x0;
1945 				RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1946 
1947 				RTMPusecDelay(1);
1948 
1949 				Index = 0;
1950 				MACValue = 0;
1951 				do {
1952 					RTMP_IO_READ32(pAd, TXRXQ_PCNT,
1953 						       &MACValue);
1954 					if ((MACValue & 0xffffff) == 0)
1955 						break;
1956 					Index++;
1957 					RTMPusecDelay(1000);
1958 				} while ((Index < 330)
1959 					 &&
1960 					 (!RTMP_TEST_FLAG
1961 					  (pAd,
1962 					   fRTMP_ADAPTER_HALT_IN_PROGRESS)));
1963 
1964 				RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1965 				TxRtyCfg.field.LongRtyLimit =
1966 				    TxRtyCfgtmp.field.LongRtyLimit;
1967 				TxRtyCfg.field.ShortRtyLimit =
1968 				    TxRtyCfgtmp.field.ShortRtyLimit;
1969 				RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1970 			}
1971 		}
1972 
1973 		CurrRateIdx = pEntry->CurrTxRateIndex;
1974 
1975 		MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
1976 				      &InitTxRateIdx);
1977 
1978 		if (CurrRateIdx >= TableSize) {
1979 			CurrRateIdx = TableSize - 1;
1980 		}
1981 		/* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */
1982 		/* So need to sync here. */
1983 		pCurrTxRate =
1984 		    (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
1985 		if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1986 		    /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */
1987 		    ) {
1988 
1989 			/* Need to sync Real Tx rate and our record. */
1990 			/* Then return for next DRS. */
1991 			pCurrTxRate =
1992 			    (struct rt_rtmp_tx_rate_switch *) & pTable[(InitTxRateIdx + 1)
1993 							    * 5];
1994 			pEntry->CurrTxRateIndex = InitTxRateIdx;
1995 			MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1996 
1997 			/* reset all OneSecTx counters */
1998 			RESET_ONE_SEC_TX_CNT(pEntry);
1999 			continue;
2000 		}
2001 		/* decide the next upgrade rate and downgrade rate, if any */
2002 		if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
2003 			UpRateIdx = CurrRateIdx + 1;
2004 			DownRateIdx = CurrRateIdx - 1;
2005 		} else if (CurrRateIdx == 0) {
2006 			UpRateIdx = CurrRateIdx + 1;
2007 			DownRateIdx = CurrRateIdx;
2008 		} else if (CurrRateIdx == (TableSize - 1)) {
2009 			UpRateIdx = CurrRateIdx;
2010 			DownRateIdx = CurrRateIdx - 1;
2011 		}
2012 
2013 		pCurrTxRate =
2014 		    (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
2015 
2016 		if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2017 			TrainUp =
2018 			    (pCurrTxRate->TrainUp +
2019 			     (pCurrTxRate->TrainUp >> 1));
2020 			TrainDown =
2021 			    (pCurrTxRate->TrainDown +
2022 			     (pCurrTxRate->TrainDown >> 1));
2023 		} else {
2024 			TrainUp = pCurrTxRate->TrainUp;
2025 			TrainDown = pCurrTxRate->TrainDown;
2026 		}
2027 
2028 		/*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */
2029 
2030 		/* */
2031 		/* Keep the last time TxRateChangeAction status. */
2032 		/* */
2033 		pEntry->LastTimeTxRateChangeAction =
2034 		    pEntry->LastSecTxRateChangeAction;
2035 
2036 		/* */
2037 		/* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2038 		/*         (criteria copied from RT2500 for Netopia case) */
2039 		/* */
2040 		if (TxTotalCnt <= 15) {
2041 			char idx = 0;
2042 			u8 TxRateIdx;
2043 			u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 =
2044 			    0, MCS5 = 0, MCS6 = 0, MCS7 = 0;
2045 			u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2046 			u8 MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0;	/* 3*3 */
2047 
2048 			/* check the existence and index of each needed MCS */
2049 			while (idx < pTable[0]) {
2050 				pCurrTxRate =
2051 				    (struct rt_rtmp_tx_rate_switch *) & pTable[(idx + 1) *
2052 								    5];
2053 
2054 				if (pCurrTxRate->CurrMCS == MCS_0) {
2055 					MCS0 = idx;
2056 				} else if (pCurrTxRate->CurrMCS == MCS_1) {
2057 					MCS1 = idx;
2058 				} else if (pCurrTxRate->CurrMCS == MCS_2) {
2059 					MCS2 = idx;
2060 				} else if (pCurrTxRate->CurrMCS == MCS_3) {
2061 					MCS3 = idx;
2062 				} else if (pCurrTxRate->CurrMCS == MCS_4) {
2063 					MCS4 = idx;
2064 				} else if (pCurrTxRate->CurrMCS == MCS_5) {
2065 					MCS5 = idx;
2066 				} else if (pCurrTxRate->CurrMCS == MCS_6) {
2067 					MCS6 = idx;
2068 				}
2069 				/*else if (pCurrTxRate->CurrMCS == MCS_7) */
2070 				else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800))	/* prevent the highest MCS using short GI when 1T and low throughput */
2071 				{
2072 					MCS7 = idx;
2073 				} else if (pCurrTxRate->CurrMCS == MCS_12) {
2074 					MCS12 = idx;
2075 				} else if (pCurrTxRate->CurrMCS == MCS_13) {
2076 					MCS13 = idx;
2077 				} else if (pCurrTxRate->CurrMCS == MCS_14) {
2078 					MCS14 = idx;
2079 				}
2080 				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 */
2081 				{
2082 					MCS15 = idx;
2083 				} else if (pCurrTxRate->CurrMCS == MCS_20)	/* 3*3 */
2084 				{
2085 					MCS20 = idx;
2086 				} else if (pCurrTxRate->CurrMCS == MCS_21) {
2087 					MCS21 = idx;
2088 				} else if (pCurrTxRate->CurrMCS == MCS_22) {
2089 					MCS22 = idx;
2090 				} else if (pCurrTxRate->CurrMCS == MCS_23) {
2091 					MCS23 = idx;
2092 				}
2093 				idx++;
2094 			}
2095 
2096 			if (pAd->LatchRfRegs.Channel <= 14) {
2097 				if (pAd->NicConfig2.field.ExternalLNAForG) {
2098 					RssiOffset = 2;
2099 				} else {
2100 					RssiOffset = 5;
2101 				}
2102 			} else {
2103 				if (pAd->NicConfig2.field.ExternalLNAForA) {
2104 					RssiOffset = 5;
2105 				} else {
2106 					RssiOffset = 8;
2107 				}
2108 			}
2109 
2110 			/*if (MCS15) */
2111 			if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) {	/* N mode with 3 stream // 3*3 */
2112 				if (MCS23 && (Rssi >= -70))
2113 					TxRateIdx = MCS23;
2114 				else if (MCS22 && (Rssi >= -72))
2115 					TxRateIdx = MCS22;
2116 				else if (MCS21 && (Rssi >= -76))
2117 					TxRateIdx = MCS21;
2118 				else if (MCS20 && (Rssi >= -78))
2119 					TxRateIdx = MCS20;
2120 				else if (MCS4 && (Rssi >= -82))
2121 					TxRateIdx = MCS4;
2122 				else if (MCS3 && (Rssi >= -84))
2123 					TxRateIdx = MCS3;
2124 				else if (MCS2 && (Rssi >= -86))
2125 					TxRateIdx = MCS2;
2126 				else if (MCS1 && (Rssi >= -88))
2127 					TxRateIdx = MCS1;
2128 				else
2129 					TxRateIdx = MCS0;
2130 			}
2131 /*              else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */
2132 			else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand))	/* 3*3 */
2133 			{	/* N mode with 2 stream */
2134 				if (MCS15 && (Rssi >= (-70 + RssiOffset)))
2135 					TxRateIdx = MCS15;
2136 				else if (MCS14 && (Rssi >= (-72 + RssiOffset)))
2137 					TxRateIdx = MCS14;
2138 				else if (MCS13 && (Rssi >= (-76 + RssiOffset)))
2139 					TxRateIdx = MCS13;
2140 				else if (MCS12 && (Rssi >= (-78 + RssiOffset)))
2141 					TxRateIdx = MCS12;
2142 				else if (MCS4 && (Rssi >= (-82 + RssiOffset)))
2143 					TxRateIdx = MCS4;
2144 				else if (MCS3 && (Rssi >= (-84 + RssiOffset)))
2145 					TxRateIdx = MCS3;
2146 				else if (MCS2 && (Rssi >= (-86 + RssiOffset)))
2147 					TxRateIdx = MCS2;
2148 				else if (MCS1 && (Rssi >= (-88 + RssiOffset)))
2149 					TxRateIdx = MCS1;
2150 				else
2151 					TxRateIdx = MCS0;
2152 			} else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) {	/* N mode with 1 stream */
2153 				if (MCS7 && (Rssi > (-72 + RssiOffset)))
2154 					TxRateIdx = MCS7;
2155 				else if (MCS6 && (Rssi > (-74 + RssiOffset)))
2156 					TxRateIdx = MCS6;
2157 				else if (MCS5 && (Rssi > (-77 + RssiOffset)))
2158 					TxRateIdx = MCS5;
2159 				else if (MCS4 && (Rssi > (-79 + RssiOffset)))
2160 					TxRateIdx = MCS4;
2161 				else if (MCS3 && (Rssi > (-81 + RssiOffset)))
2162 					TxRateIdx = MCS3;
2163 				else if (MCS2 && (Rssi > (-83 + RssiOffset)))
2164 					TxRateIdx = MCS2;
2165 				else if (MCS1 && (Rssi > (-86 + RssiOffset)))
2166 					TxRateIdx = MCS1;
2167 				else
2168 					TxRateIdx = MCS0;
2169 			} else {	/* Legacy mode */
2170 				if (MCS7 && (Rssi > -70))
2171 					TxRateIdx = MCS7;
2172 				else if (MCS6 && (Rssi > -74))
2173 					TxRateIdx = MCS6;
2174 				else if (MCS5 && (Rssi > -78))
2175 					TxRateIdx = MCS5;
2176 				else if (MCS4 && (Rssi > -82))
2177 					TxRateIdx = MCS4;
2178 				else if (MCS4 == 0)	/* for B-only mode */
2179 					TxRateIdx = MCS3;
2180 				else if (MCS3 && (Rssi > -85))
2181 					TxRateIdx = MCS3;
2182 				else if (MCS2 && (Rssi > -87))
2183 					TxRateIdx = MCS2;
2184 				else if (MCS1 && (Rssi > -90))
2185 					TxRateIdx = MCS1;
2186 				else
2187 					TxRateIdx = MCS0;
2188 			}
2189 
2190 			/*              if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */
2191 			{
2192 				pEntry->CurrTxRateIndex = TxRateIdx;
2193 				pNextTxRate =
2194 				    (struct rt_rtmp_tx_rate_switch *) &
2195 				    pTable[(pEntry->CurrTxRateIndex + 1) * 5];
2196 				MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2197 			}
2198 
2199 			NdisZeroMemory(pEntry->TxQuality,
2200 				       sizeof(u16)*
2201 				       MAX_STEP_OF_TX_RATE_SWITCH);
2202 			NdisZeroMemory(pEntry->PER,
2203 				       sizeof(u8)*
2204 				       MAX_STEP_OF_TX_RATE_SWITCH);
2205 			pEntry->fLastSecAccordingRSSI = TRUE;
2206 			/* reset all OneSecTx counters */
2207 			RESET_ONE_SEC_TX_CNT(pEntry);
2208 
2209 			continue;
2210 		}
2211 
2212 		if (pEntry->fLastSecAccordingRSSI == TRUE) {
2213 			pEntry->fLastSecAccordingRSSI = FALSE;
2214 			pEntry->LastSecTxRateChangeAction = 0;
2215 			/* reset all OneSecTx counters */
2216 			RESET_ONE_SEC_TX_CNT(pEntry);
2217 
2218 			continue;
2219 		}
2220 
2221 		do {
2222 			BOOLEAN bTrainUpDown = FALSE;
2223 
2224 			pEntry->CurrTxRateStableTime++;
2225 
2226 			/* downgrade TX quality if PER >= Rate-Down threshold */
2227 			if (TxErrorRatio >= TrainDown) {
2228 				bTrainUpDown = TRUE;
2229 				pEntry->TxQuality[CurrRateIdx] =
2230 				    DRS_TX_QUALITY_WORST_BOUND;
2231 			}
2232 			/* upgrade TX quality if PER <= Rate-Up threshold */
2233 			else if (TxErrorRatio <= TrainUp) {
2234 				bTrainUpDown = TRUE;
2235 				bUpgradeQuality = TRUE;
2236 				if (pEntry->TxQuality[CurrRateIdx])
2237 					pEntry->TxQuality[CurrRateIdx]--;	/* quality very good in CurrRate */
2238 
2239 				if (pEntry->TxRateUpPenalty)
2240 					pEntry->TxRateUpPenalty--;
2241 				else if (pEntry->TxQuality[UpRateIdx])
2242 					pEntry->TxQuality[UpRateIdx]--;	/* may improve next UP rate's quality */
2243 			}
2244 
2245 			pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio;
2246 
2247 			if (bTrainUpDown) {
2248 				/* perform DRS - consider TxRate Down first, then rate up. */
2249 				if ((CurrRateIdx != DownRateIdx)
2250 				    && (pEntry->TxQuality[CurrRateIdx] >=
2251 					DRS_TX_QUALITY_WORST_BOUND)) {
2252 					pEntry->CurrTxRateIndex = DownRateIdx;
2253 				} else if ((CurrRateIdx != UpRateIdx)
2254 					   && (pEntry->TxQuality[UpRateIdx] <=
2255 					       0)) {
2256 					pEntry->CurrTxRateIndex = UpRateIdx;
2257 				}
2258 			}
2259 		} while (FALSE);
2260 
2261 		/* if rate-up happen, clear all bad history of all TX rates */
2262 		if (pEntry->CurrTxRateIndex > CurrRateIdx) {
2263 			pEntry->CurrTxRateStableTime = 0;
2264 			pEntry->TxRateUpPenalty = 0;
2265 			pEntry->LastSecTxRateChangeAction = 1;	/* rate UP */
2266 			NdisZeroMemory(pEntry->TxQuality,
2267 				       sizeof(u16)*
2268 				       MAX_STEP_OF_TX_RATE_SWITCH);
2269 			NdisZeroMemory(pEntry->PER,
2270 				       sizeof(u8)*
2271 				       MAX_STEP_OF_TX_RATE_SWITCH);
2272 
2273 			/* */
2274 			/* For TxRate fast train up */
2275 			/* */
2276 			if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2277 				RTMPSetTimer(&pAd->StaCfg.
2278 					     StaQuickResponeForRateUpTimer,
2279 					     100);
2280 
2281 				pAd->StaCfg.
2282 				    StaQuickResponeForRateUpTimerRunning = TRUE;
2283 			}
2284 			bTxRateChanged = TRUE;
2285 		}
2286 		/* if rate-down happen, only clear DownRate's bad history */
2287 		else if (pEntry->CurrTxRateIndex < CurrRateIdx) {
2288 			pEntry->CurrTxRateStableTime = 0;
2289 			pEntry->TxRateUpPenalty = 0;	/* no penalty */
2290 			pEntry->LastSecTxRateChangeAction = 2;	/* rate DOWN */
2291 			pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2292 			pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2293 
2294 			/* */
2295 			/* For TxRate fast train down */
2296 			/* */
2297 			if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2298 				RTMPSetTimer(&pAd->StaCfg.
2299 					     StaQuickResponeForRateUpTimer,
2300 					     100);
2301 
2302 				pAd->StaCfg.
2303 				    StaQuickResponeForRateUpTimerRunning = TRUE;
2304 			}
2305 			bTxRateChanged = TRUE;
2306 		} else {
2307 			pEntry->LastSecTxRateChangeAction = 0;	/* rate no change */
2308 			bTxRateChanged = FALSE;
2309 		}
2310 
2311 		pEntry->LastTxOkCount = TxSuccess;
2312 		{
2313 			u8 tmpTxRate;
2314 
2315 			/* to fix tcp ack issue */
2316 			if (!bTxRateChanged
2317 			    && (pAd->RalinkCounters.OneSecReceivedByteCount >
2318 				(pAd->RalinkCounters.
2319 				 OneSecTransmittedByteCount * 5))) {
2320 				tmpTxRate = DownRateIdx;
2321 				DBGPRINT_RAW(RT_DEBUG_TRACE,
2322 					     ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2323 					      pAd->RalinkCounters.
2324 					      OneSecReceivedByteCount,
2325 					      pAd->RalinkCounters.
2326 					      OneSecTransmittedByteCount,
2327 					      pEntry->CurrTxRateIndex,
2328 					      tmpTxRate));
2329 			} else {
2330 				tmpTxRate = pEntry->CurrTxRateIndex;
2331 			}
2332 
2333 			pNextTxRate =
2334 			    (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) *
2335 							    5];
2336 		}
2337 		if (bTxRateChanged && pNextTxRate) {
2338 			MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2339 		}
2340 		/* reset all OneSecTx counters */
2341 		RESET_ONE_SEC_TX_CNT(pEntry);
2342 	}
2343 }
2344 
2345 /*
2346 	========================================================================
2347 	Routine Description:
2348 		Station side, Auto TxRate faster train up timer call back function.
2349 
2350 	Arguments:
2351 		SystemSpecific1			- Not used.
2352 		FunctionContext			- Pointer to our Adapter context.
2353 		SystemSpecific2			- Not used.
2354 		SystemSpecific3			- Not used.
2355 
2356 	Return Value:
2357 		None
2358 
2359 	========================================================================
2360 */
StaQuickResponeForRateUpExec(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)2361 void StaQuickResponeForRateUpExec(void *SystemSpecific1,
2362 				  void *FunctionContext,
2363 				  void *SystemSpecific2,
2364 				  void *SystemSpecific3)
2365 {
2366 	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
2367 	u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2368 	unsigned long TxTotalCnt;
2369 	unsigned long TxErrorRatio = 0;
2370 	BOOLEAN bTxRateChanged;	/*, bUpgradeQuality = FALSE; */
2371 	struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
2372 	u8 *pTable;
2373 	u8 TableSize = 0;
2374 	u8 InitTxRateIdx = 0, TrainUp, TrainDown;
2375 	TX_STA_CNT1_STRUC StaTx1;
2376 	TX_STA_CNT0_STRUC TxStaCnt0;
2377 	char Rssi, ratio;
2378 	unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2379 	struct rt_mac_table_entry *pEntry;
2380 	unsigned long i;
2381 
2382 	pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2383 
2384 	/* */
2385 	/* walk through MAC table, see if need to change AP's TX rate toward each entry */
2386 	/* */
2387 	for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
2388 		pEntry = &pAd->MacTab.Content[i];
2389 
2390 		/* check if this entry need to switch rate automatically */
2391 		if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2392 			continue;
2393 
2394 		if (INFRA_ON(pAd) && (i == 1))
2395 			Rssi = RTMPMaxRssi(pAd,
2396 					   pAd->StaCfg.RssiSample.AvgRssi0,
2397 					   pAd->StaCfg.RssiSample.AvgRssi1,
2398 					   pAd->StaCfg.RssiSample.AvgRssi2);
2399 		else
2400 			Rssi = RTMPMaxRssi(pAd,
2401 					   pEntry->RssiSample.AvgRssi0,
2402 					   pEntry->RssiSample.AvgRssi1,
2403 					   pEntry->RssiSample.AvgRssi2);
2404 
2405 		CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2406 
2407 		MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
2408 				      &InitTxRateIdx);
2409 
2410 		/* decide the next upgrade rate and downgrade rate, if any */
2411 		if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
2412 			UpRateIdx = CurrRateIdx + 1;
2413 			DownRateIdx = CurrRateIdx - 1;
2414 		} else if (CurrRateIdx == 0) {
2415 			UpRateIdx = CurrRateIdx + 1;
2416 			DownRateIdx = CurrRateIdx;
2417 		} else if (CurrRateIdx == (TableSize - 1)) {
2418 			UpRateIdx = CurrRateIdx;
2419 			DownRateIdx = CurrRateIdx - 1;
2420 		}
2421 
2422 		pCurrTxRate =
2423 		    (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
2424 
2425 		if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2426 			TrainUp =
2427 			    (pCurrTxRate->TrainUp +
2428 			     (pCurrTxRate->TrainUp >> 1));
2429 			TrainDown =
2430 			    (pCurrTxRate->TrainDown +
2431 			     (pCurrTxRate->TrainDown >> 1));
2432 		} else {
2433 			TrainUp = pCurrTxRate->TrainUp;
2434 			TrainDown = pCurrTxRate->TrainDown;
2435 		}
2436 
2437 		if (pAd->MacTab.Size == 1) {
2438 			/* Update statistic counter */
2439 			RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2440 			RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2441 
2442 			TxRetransmit = StaTx1.field.TxRetransmit;
2443 			TxSuccess = StaTx1.field.TxSuccess;
2444 			TxFailCount = TxStaCnt0.field.TxFailCount;
2445 			TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2446 
2447 			pAd->RalinkCounters.OneSecTxRetryOkCount +=
2448 			    StaTx1.field.TxRetransmit;
2449 			pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
2450 			    StaTx1.field.TxSuccess;
2451 			pAd->RalinkCounters.OneSecTxFailCount +=
2452 			    TxStaCnt0.field.TxFailCount;
2453 			pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
2454 			    StaTx1.field.TxSuccess;
2455 			pAd->WlanCounters.RetryCount.u.LowPart +=
2456 			    StaTx1.field.TxRetransmit;
2457 			pAd->WlanCounters.FailedCount.u.LowPart +=
2458 			    TxStaCnt0.field.TxFailCount;
2459 
2460 			if (TxTotalCnt)
2461 				TxErrorRatio =
2462 				    ((TxRetransmit +
2463 				      TxFailCount) * 100) / TxTotalCnt;
2464 		} else {
2465 			TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2466 			    pEntry->OneSecTxRetryOkCount +
2467 			    pEntry->OneSecTxFailCount;
2468 
2469 			if (TxTotalCnt)
2470 				TxErrorRatio =
2471 				    ((pEntry->OneSecTxRetryOkCount +
2472 				      pEntry->OneSecTxFailCount) * 100) /
2473 				    TxTotalCnt;
2474 		}
2475 
2476 		/* */
2477 		/* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2478 		/*         (criteria copied from RT2500 for Netopia case) */
2479 		/* */
2480 		if (TxTotalCnt <= 12) {
2481 			NdisZeroMemory(pAd->DrsCounters.TxQuality,
2482 				       sizeof(u16)*
2483 				       MAX_STEP_OF_TX_RATE_SWITCH);
2484 			NdisZeroMemory(pAd->DrsCounters.PER,
2485 				       sizeof(u8)*
2486 				       MAX_STEP_OF_TX_RATE_SWITCH);
2487 
2488 			if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2489 			    && (CurrRateIdx != DownRateIdx)) {
2490 				pAd->CommonCfg.TxRateIndex = DownRateIdx;
2491 				pAd->DrsCounters.TxQuality[CurrRateIdx] =
2492 				    DRS_TX_QUALITY_WORST_BOUND;
2493 			} else
2494 			    if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2495 				 2) && (CurrRateIdx != UpRateIdx)) {
2496 				pAd->CommonCfg.TxRateIndex = UpRateIdx;
2497 			}
2498 
2499 			DBGPRINT_RAW(RT_DEBUG_TRACE,
2500 				     ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2501 			return;
2502 		}
2503 
2504 		do {
2505 			unsigned long OneSecTxNoRetryOKRationCount;
2506 
2507 			if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2508 				ratio = 5;
2509 			else
2510 				ratio = 4;
2511 
2512 			/* downgrade TX quality if PER >= Rate-Down threshold */
2513 			if (TxErrorRatio >= TrainDown) {
2514 				pAd->DrsCounters.TxQuality[CurrRateIdx] =
2515 				    DRS_TX_QUALITY_WORST_BOUND;
2516 			}
2517 
2518 			pAd->DrsCounters.PER[CurrRateIdx] =
2519 			    (u8)TxErrorRatio;
2520 
2521 			OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2522 
2523 			/* perform DRS - consider TxRate Down first, then rate up. */
2524 			if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2525 			    && (CurrRateIdx != DownRateIdx)) {
2526 				if ((pAd->DrsCounters.LastTxOkCount + 2) >=
2527 				    OneSecTxNoRetryOKRationCount) {
2528 					pAd->CommonCfg.TxRateIndex =
2529 					    DownRateIdx;
2530 					pAd->DrsCounters.
2531 					    TxQuality[CurrRateIdx] =
2532 					    DRS_TX_QUALITY_WORST_BOUND;
2533 
2534 				}
2535 
2536 			} else
2537 			    if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2538 				 2) && (CurrRateIdx != UpRateIdx)) {
2539 				if ((TxErrorRatio >= 50)
2540 				    || (TxErrorRatio >= TrainDown)) {
2541 
2542 				} else if ((pAd->DrsCounters.LastTxOkCount + 2)
2543 					   >= OneSecTxNoRetryOKRationCount) {
2544 					pAd->CommonCfg.TxRateIndex = UpRateIdx;
2545 				}
2546 			}
2547 		} while (FALSE);
2548 
2549 		/* if rate-up happen, clear all bad history of all TX rates */
2550 		if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) {
2551 			pAd->DrsCounters.TxRateUpPenalty = 0;
2552 			NdisZeroMemory(pAd->DrsCounters.TxQuality,
2553 				       sizeof(u16)*
2554 				       MAX_STEP_OF_TX_RATE_SWITCH);
2555 			NdisZeroMemory(pAd->DrsCounters.PER,
2556 				       sizeof(u8)*
2557 				       MAX_STEP_OF_TX_RATE_SWITCH);
2558 			bTxRateChanged = TRUE;
2559 		}
2560 		/* if rate-down happen, only clear DownRate's bad history */
2561 		else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) {
2562 			DBGPRINT_RAW(RT_DEBUG_TRACE,
2563 				     ("QuickDRS: --TX rate from %d to %d \n",
2564 				      CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2565 
2566 			pAd->DrsCounters.TxRateUpPenalty = 0;	/* no penalty */
2567 			pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] =
2568 			    0;
2569 			pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2570 			bTxRateChanged = TRUE;
2571 		} else {
2572 			bTxRateChanged = FALSE;
2573 		}
2574 
2575 		pNextTxRate =
2576 		    (struct rt_rtmp_tx_rate_switch *) &
2577 		    pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5];
2578 		if (bTxRateChanged && pNextTxRate) {
2579 			MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2580 		}
2581 	}
2582 }
2583 
2584 /*
2585 	==========================================================================
2586 	Description:
2587 		This routine is executed periodically inside MlmePeriodicExec() after
2588 		association with an AP.
2589 		It checks if StaCfg.Psm is consistent with user policy (recorded in
2590 		StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2591 		there're some conditions to consider:
2592 		1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2593 		   the time when Mibss==TRUE
2594 		2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2595 		   if outgoing traffic available in TxRing or MgmtRing.
2596 	Output:
2597 		1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2598 
2599 	IRQL = DISPATCH_LEVEL
2600 
2601 	==========================================================================
2602  */
MlmeCheckPsmChange(struct rt_rtmp_adapter * pAd,unsigned long Now32)2603 void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32)
2604 {
2605 	unsigned long PowerMode;
2606 
2607 	/* condition - */
2608 	/* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */
2609 	/* 2. user wants either MAX_PSP or FAST_PSP */
2610 	/* 3. but current psm is not in PWR_SAVE */
2611 	/* 4. CNTL state machine is not doing SCANning */
2612 	/* 5. no TX SUCCESS event for the past 1-sec period */
2613 	PowerMode = pAd->StaCfg.WindowsPowerMode;
2614 
2615 	if (INFRA_ON(pAd) &&
2616 	    (PowerMode != Ndis802_11PowerModeCAM) &&
2617 	    (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2618 /*              (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */
2619 	    (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
2620 	    RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2621 	    /*&&
2622 	       (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2623 	       (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2624 	    ) {
2625 		NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2626 		pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2627 		RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
2628 		if (!
2629 		    (pAd->CommonCfg.bAPSDCapable
2630 		     && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
2631 			RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2632 		} else {
2633 			RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2634 		}
2635 	}
2636 }
2637 
2638 /* IRQL = PASSIVE_LEVEL */
2639 /* IRQL = DISPATCH_LEVEL */
MlmeSetPsmBit(struct rt_rtmp_adapter * pAd,u16 psm)2640 void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm)
2641 {
2642 	AUTO_RSP_CFG_STRUC csr4;
2643 
2644 	pAd->StaCfg.Psm = psm;
2645 	RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2646 	csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0;
2647 	RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2648 
2649 	DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2650 }
2651 
2652 /*
2653 	==========================================================================
2654 	Description:
2655 		This routine calculates TxPER, RxPER of the past N-sec period. And
2656 		according to the calculation result, ChannelQuality is calculated here
2657 		to decide if current AP is still doing the job.
2658 
2659 		If ChannelQuality is not good, a ROAMing attempt may be tried later.
2660 	Output:
2661 		StaCfg.ChannelQuality - 0..100
2662 
2663 	IRQL = DISPATCH_LEVEL
2664 
2665 	NOTE: This routine decide channle quality based on RX CRC error ratio.
2666 		Caller should make sure a function call to NICUpdateRawCounters(pAd)
2667 		is performed right before this routine, so that this routine can decide
2668 		channel quality based on the most up-to-date information
2669 	==========================================================================
2670  */
MlmeCalculateChannelQuality(struct rt_rtmp_adapter * pAd,struct rt_mac_table_entry * pMacEntry,unsigned long Now32)2671 void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd,
2672 				 struct rt_mac_table_entry *pMacEntry, unsigned long Now32)
2673 {
2674 	unsigned long TxOkCnt, TxCnt, TxPER, TxPRR;
2675 	unsigned long RxCnt, RxPER;
2676 	u8 NorRssi;
2677 	char MaxRssi;
2678 	struct rt_rssi_sample *pRssiSample = NULL;
2679 	u32 OneSecTxNoRetryOkCount = 0;
2680 	u32 OneSecTxRetryOkCount = 0;
2681 	u32 OneSecTxFailCount = 0;
2682 	u32 OneSecRxOkCnt = 0;
2683 	u32 OneSecRxFcsErrCnt = 0;
2684 	unsigned long ChannelQuality = 0;	/* 0..100, Channel Quality Indication for Roaming */
2685 	unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime;
2686 
2687 	if (pAd->OpMode == OPMODE_STA) {
2688 		pRssiSample = &pAd->StaCfg.RssiSample;
2689 		OneSecTxNoRetryOkCount =
2690 		    pAd->RalinkCounters.OneSecTxNoRetryOkCount;
2691 		OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2692 		OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2693 		OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2694 		OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
2695 	}
2696 
2697 	MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
2698 			      pRssiSample->LastRssi1, pRssiSample->LastRssi2);
2699 
2700 	/* */
2701 	/* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */
2702 	/* */
2703 	TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2704 	TxCnt = TxOkCnt + OneSecTxFailCount;
2705 	if (TxCnt < 5) {
2706 		TxPER = 0;
2707 		TxPRR = 0;
2708 	} else {
2709 		TxPER = (OneSecTxFailCount * 100) / TxCnt;
2710 		TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2711 	}
2712 
2713 	/* */
2714 	/* calculate RX PER - don't take RxPER into consideration if too few sample */
2715 	/* */
2716 	RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2717 	if (RxCnt < 5)
2718 		RxPER = 0;
2719 	else
2720 		RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
2721 
2722 	/* */
2723 	/* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */
2724 	/* */
2725 	if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) &&	/* no heavy traffic */
2726 	    ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) {
2727 		DBGPRINT(RT_DEBUG_TRACE,
2728 			 ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2729 			  BeaconLostTime, TxOkCnt));
2730 		ChannelQuality = 0;
2731 	} else {
2732 		/* Normalize Rssi */
2733 		if (MaxRssi > -40)
2734 			NorRssi = 100;
2735 		else if (MaxRssi < -90)
2736 			NorRssi = 0;
2737 		else
2738 			NorRssi = (MaxRssi + 90) * 2;
2739 
2740 		/* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER        (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */
2741 		ChannelQuality = (RSSI_WEIGHTING * NorRssi +
2742 				  TX_WEIGHTING * (100 - TxPRR) +
2743 				  RX_WEIGHTING * (100 - RxPER)) / 100;
2744 	}
2745 
2746 	if (pAd->OpMode == OPMODE_STA)
2747 		pAd->Mlme.ChannelQuality =
2748 		    (ChannelQuality > 100) ? 100 : ChannelQuality;
2749 
2750 }
2751 
2752 /* IRQL = DISPATCH_LEVEL */
MlmeSetTxPreamble(struct rt_rtmp_adapter * pAd,u16 TxPreamble)2753 void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble)
2754 {
2755 	AUTO_RSP_CFG_STRUC csr4;
2756 
2757 	/* */
2758 	/* Always use Long preamble before verifiation short preamble functionality works well. */
2759 	/* Todo: remove the following line if short preamble functionality works */
2760 	/* */
2761 	/*TxPreamble = Rt802_11PreambleLong; */
2762 
2763 	RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2764 	if (TxPreamble == Rt802_11PreambleLong) {
2765 		DBGPRINT(RT_DEBUG_TRACE,
2766 			 ("MlmeSetTxPreamble (= long PREAMBLE)\n"));
2767 		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2768 		csr4.field.AutoResponderPreamble = 0;
2769 	} else {
2770 		/* NOTE: 1Mbps should always use long preamble */
2771 		DBGPRINT(RT_DEBUG_TRACE,
2772 			 ("MlmeSetTxPreamble (= short PREAMBLE)\n"));
2773 		OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2774 		csr4.field.AutoResponderPreamble = 1;
2775 	}
2776 
2777 	RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2778 }
2779 
2780 /*
2781     ==========================================================================
2782     Description:
2783         Update basic rate bitmap
2784     ==========================================================================
2785  */
2786 
UpdateBasicRateBitmap(struct rt_rtmp_adapter * pAdapter)2787 void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter)
2788 {
2789 	int i, j;
2790 	/* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
2791 	u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2792 	u8 *sup_p = pAdapter->CommonCfg.SupRate;
2793 	u8 *ext_p = pAdapter->CommonCfg.ExtRate;
2794 	unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2795 
2796 	/* if A mode, always use fix BasicRateBitMap */
2797 	/*if (pAdapter->CommonCfg.Channel == PHY_11A) */
2798 	if (pAdapter->CommonCfg.Channel > 14)
2799 		pAdapter->CommonCfg.BasicRateBitmap = 0x150;	/* 6, 12, 24M */
2800 	/* End of if */
2801 
2802 	if (pAdapter->CommonCfg.BasicRateBitmap > 4095) {
2803 		/* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2804 		return;
2805 	}
2806 	/* End of if */
2807 	for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2808 		sup_p[i] &= 0x7f;
2809 		ext_p[i] &= 0x7f;
2810 	}			/* End of for */
2811 
2812 	for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2813 		if (bitmap & (1 << i)) {
2814 			for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2815 				if (sup_p[j] == rate[i])
2816 					sup_p[j] |= 0x80;
2817 				/* End of if */
2818 			}	/* End of for */
2819 
2820 			for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2821 				if (ext_p[j] == rate[i])
2822 					ext_p[j] |= 0x80;
2823 				/* End of if */
2824 			}	/* End of for */
2825 		}		/* End of if */
2826 	}			/* End of for */
2827 }				/* End of UpdateBasicRateBitmap */
2828 
2829 /* IRQL = PASSIVE_LEVEL */
2830 /* IRQL = DISPATCH_LEVEL */
2831 /* bLinkUp is to identify the initial link speed. */
2832 /* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */
MlmeUpdateTxRates(struct rt_rtmp_adapter * pAd,IN BOOLEAN bLinkUp,u8 apidx)2833 void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx)
2834 {
2835 	int i, num;
2836 	u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2837 	u8 MinSupport = RATE_54;
2838 	unsigned long BasicRateBitmap = 0;
2839 	u8 CurrBasicRate = RATE_1;
2840 	u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2841 	PHTTRANSMIT_SETTING pHtPhy = NULL;
2842 	PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2843 	PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2844 	BOOLEAN *auto_rate_cur_p;
2845 	u8 HtMcs = MCS_AUTO;
2846 
2847 	/* find max desired rate */
2848 	UpdateBasicRateBitmap(pAd);
2849 
2850 	num = 0;
2851 	auto_rate_cur_p = NULL;
2852 	for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2853 		switch (pAd->CommonCfg.DesireRate[i] & 0x7f) {
2854 		case 2:
2855 			Rate = RATE_1;
2856 			num++;
2857 			break;
2858 		case 4:
2859 			Rate = RATE_2;
2860 			num++;
2861 			break;
2862 		case 11:
2863 			Rate = RATE_5_5;
2864 			num++;
2865 			break;
2866 		case 22:
2867 			Rate = RATE_11;
2868 			num++;
2869 			break;
2870 		case 12:
2871 			Rate = RATE_6;
2872 			num++;
2873 			break;
2874 		case 18:
2875 			Rate = RATE_9;
2876 			num++;
2877 			break;
2878 		case 24:
2879 			Rate = RATE_12;
2880 			num++;
2881 			break;
2882 		case 36:
2883 			Rate = RATE_18;
2884 			num++;
2885 			break;
2886 		case 48:
2887 			Rate = RATE_24;
2888 			num++;
2889 			break;
2890 		case 72:
2891 			Rate = RATE_36;
2892 			num++;
2893 			break;
2894 		case 96:
2895 			Rate = RATE_48;
2896 			num++;
2897 			break;
2898 		case 108:
2899 			Rate = RATE_54;
2900 			num++;
2901 			break;
2902 			/*default: Rate = RATE_1;   break; */
2903 		}
2904 		if (MaxDesire < Rate)
2905 			MaxDesire = Rate;
2906 	}
2907 
2908 /*=========================================================================== */
2909 /*=========================================================================== */
2910 	{
2911 		pHtPhy = &pAd->StaCfg.HTPhyMode;
2912 		pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2913 		pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2914 
2915 		auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2916 		HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2917 
2918 		if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2919 		    (pAd->CommonCfg.PhyMode == PHY_11B) &&
2920 		    (MaxDesire > RATE_11)) {
2921 			MaxDesire = RATE_11;
2922 		}
2923 	}
2924 
2925 	pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2926 	pMinHtPhy->word = 0;
2927 	pMaxHtPhy->word = 0;
2928 	pHtPhy->word = 0;
2929 
2930 	/* Auto rate switching is enabled only if more than one DESIRED RATES are */
2931 	/* specified; otherwise disabled */
2932 	if (num <= 1) {
2933 		/*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2934 		/*pAd->CommonCfg.bAutoTxRateSwitch      = FALSE; */
2935 		*auto_rate_cur_p = FALSE;
2936 	} else {
2937 		/*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2938 		/*pAd->CommonCfg.bAutoTxRateSwitch      = TRUE; */
2939 		*auto_rate_cur_p = TRUE;
2940 	}
2941 
2942 	if (HtMcs != MCS_AUTO) {
2943 		/*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2944 		/*pAd->CommonCfg.bAutoTxRateSwitch      = FALSE; */
2945 		*auto_rate_cur_p = FALSE;
2946 	} else {
2947 		/*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2948 		/*pAd->CommonCfg.bAutoTxRateSwitch      = TRUE; */
2949 		*auto_rate_cur_p = TRUE;
2950 	}
2951 
2952 	if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
2953 		pSupRate = &pAd->StaActive.SupRate[0];
2954 		pExtRate = &pAd->StaActive.ExtRate[0];
2955 		SupRateLen = pAd->StaActive.SupRateLen;
2956 		ExtRateLen = pAd->StaActive.ExtRateLen;
2957 	} else {
2958 		pSupRate = &pAd->CommonCfg.SupRate[0];
2959 		pExtRate = &pAd->CommonCfg.ExtRate[0];
2960 		SupRateLen = pAd->CommonCfg.SupRateLen;
2961 		ExtRateLen = pAd->CommonCfg.ExtRateLen;
2962 	}
2963 
2964 	/* find max supported rate */
2965 	for (i = 0; i < SupRateLen; i++) {
2966 		switch (pSupRate[i] & 0x7f) {
2967 		case 2:
2968 			Rate = RATE_1;
2969 			if (pSupRate[i] & 0x80)
2970 				BasicRateBitmap |= 0x0001;
2971 			break;
2972 		case 4:
2973 			Rate = RATE_2;
2974 			if (pSupRate[i] & 0x80)
2975 				BasicRateBitmap |= 0x0002;
2976 			break;
2977 		case 11:
2978 			Rate = RATE_5_5;
2979 			if (pSupRate[i] & 0x80)
2980 				BasicRateBitmap |= 0x0004;
2981 			break;
2982 		case 22:
2983 			Rate = RATE_11;
2984 			if (pSupRate[i] & 0x80)
2985 				BasicRateBitmap |= 0x0008;
2986 			break;
2987 		case 12:
2988 			Rate = RATE_6;	/*if (pSupRate[i] & 0x80) */
2989 			BasicRateBitmap |= 0x0010;
2990 			break;
2991 		case 18:
2992 			Rate = RATE_9;
2993 			if (pSupRate[i] & 0x80)
2994 				BasicRateBitmap |= 0x0020;
2995 			break;
2996 		case 24:
2997 			Rate = RATE_12;	/*if (pSupRate[i] & 0x80) */
2998 			BasicRateBitmap |= 0x0040;
2999 			break;
3000 		case 36:
3001 			Rate = RATE_18;
3002 			if (pSupRate[i] & 0x80)
3003 				BasicRateBitmap |= 0x0080;
3004 			break;
3005 		case 48:
3006 			Rate = RATE_24;	/*if (pSupRate[i] & 0x80) */
3007 			BasicRateBitmap |= 0x0100;
3008 			break;
3009 		case 72:
3010 			Rate = RATE_36;
3011 			if (pSupRate[i] & 0x80)
3012 				BasicRateBitmap |= 0x0200;
3013 			break;
3014 		case 96:
3015 			Rate = RATE_48;
3016 			if (pSupRate[i] & 0x80)
3017 				BasicRateBitmap |= 0x0400;
3018 			break;
3019 		case 108:
3020 			Rate = RATE_54;
3021 			if (pSupRate[i] & 0x80)
3022 				BasicRateBitmap |= 0x0800;
3023 			break;
3024 		default:
3025 			Rate = RATE_1;
3026 			break;
3027 		}
3028 		if (MaxSupport < Rate)
3029 			MaxSupport = Rate;
3030 
3031 		if (MinSupport > Rate)
3032 			MinSupport = Rate;
3033 	}
3034 
3035 	for (i = 0; i < ExtRateLen; i++) {
3036 		switch (pExtRate[i] & 0x7f) {
3037 		case 2:
3038 			Rate = RATE_1;
3039 			if (pExtRate[i] & 0x80)
3040 				BasicRateBitmap |= 0x0001;
3041 			break;
3042 		case 4:
3043 			Rate = RATE_2;
3044 			if (pExtRate[i] & 0x80)
3045 				BasicRateBitmap |= 0x0002;
3046 			break;
3047 		case 11:
3048 			Rate = RATE_5_5;
3049 			if (pExtRate[i] & 0x80)
3050 				BasicRateBitmap |= 0x0004;
3051 			break;
3052 		case 22:
3053 			Rate = RATE_11;
3054 			if (pExtRate[i] & 0x80)
3055 				BasicRateBitmap |= 0x0008;
3056 			break;
3057 		case 12:
3058 			Rate = RATE_6;	/*if (pExtRate[i] & 0x80) */
3059 			BasicRateBitmap |= 0x0010;
3060 			break;
3061 		case 18:
3062 			Rate = RATE_9;
3063 			if (pExtRate[i] & 0x80)
3064 				BasicRateBitmap |= 0x0020;
3065 			break;
3066 		case 24:
3067 			Rate = RATE_12;	/*if (pExtRate[i] & 0x80) */
3068 			BasicRateBitmap |= 0x0040;
3069 			break;
3070 		case 36:
3071 			Rate = RATE_18;
3072 			if (pExtRate[i] & 0x80)
3073 				BasicRateBitmap |= 0x0080;
3074 			break;
3075 		case 48:
3076 			Rate = RATE_24;	/*if (pExtRate[i] & 0x80) */
3077 			BasicRateBitmap |= 0x0100;
3078 			break;
3079 		case 72:
3080 			Rate = RATE_36;
3081 			if (pExtRate[i] & 0x80)
3082 				BasicRateBitmap |= 0x0200;
3083 			break;
3084 		case 96:
3085 			Rate = RATE_48;
3086 			if (pExtRate[i] & 0x80)
3087 				BasicRateBitmap |= 0x0400;
3088 			break;
3089 		case 108:
3090 			Rate = RATE_54;
3091 			if (pExtRate[i] & 0x80)
3092 				BasicRateBitmap |= 0x0800;
3093 			break;
3094 		default:
3095 			Rate = RATE_1;
3096 			break;
3097 		}
3098 		if (MaxSupport < Rate)
3099 			MaxSupport = Rate;
3100 
3101 		if (MinSupport > Rate)
3102 			MinSupport = Rate;
3103 	}
3104 
3105 	RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3106 
3107 	/* bug fix */
3108 	/* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */
3109 
3110 	/* calculate the exptected ACK rate for each TX rate. This info is used to caculate */
3111 	/* the DURATION field of outgoing uniicast DATA/MGMT frame */
3112 	for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
3113 		if (BasicRateBitmap & (0x01 << i))
3114 			CurrBasicRate = (u8)i;
3115 		pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3116 	}
3117 
3118 	DBGPRINT(RT_DEBUG_TRACE,
3119 		 ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3120 		  RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3121 	/* max tx rate = min {max desire rate, max supported rate} */
3122 	if (MaxSupport < MaxDesire)
3123 		pAd->CommonCfg.MaxTxRate = MaxSupport;
3124 	else
3125 		pAd->CommonCfg.MaxTxRate = MaxDesire;
3126 
3127 	pAd->CommonCfg.MinTxRate = MinSupport;
3128 	/* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */
3129 	/* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */
3130 	/* on average RSSI */
3131 	/*       1. RSSI >= -70db, start at 54 Mbps (short distance) */
3132 	/*       2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */
3133 	/*       3. -75 > RSSI, start at 11 Mbps (long distance) */
3134 	if (*auto_rate_cur_p) {
3135 		short dbm = 0;
3136 
3137 		dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3138 
3139 		if (bLinkUp == TRUE)
3140 			pAd->CommonCfg.TxRate = RATE_24;
3141 		else
3142 			pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3143 
3144 		if (dbm < -75)
3145 			pAd->CommonCfg.TxRate = RATE_11;
3146 		else if (dbm < -70)
3147 			pAd->CommonCfg.TxRate = RATE_24;
3148 
3149 		/* should never exceed MaxTxRate (consider 11B-only mode) */
3150 		if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3151 			pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3152 
3153 		pAd->CommonCfg.TxRateIndex = 0;
3154 	} else {
3155 		pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3156 		pHtPhy->field.MCS =
3157 		    (pAd->CommonCfg.MaxTxRate >
3158 		     3) ? (pAd->CommonCfg.MaxTxRate -
3159 			   4) : pAd->CommonCfg.MaxTxRate;
3160 		pHtPhy->field.MODE =
3161 		    (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3162 
3163 		pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC =
3164 		    pHtPhy->field.STBC;
3165 		pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI =
3166 		    pHtPhy->field.ShortGI;
3167 		pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS =
3168 		    pHtPhy->field.MCS;
3169 		pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE =
3170 		    pHtPhy->field.MODE;
3171 	}
3172 
3173 	if (pAd->CommonCfg.TxRate <= RATE_11) {
3174 		pMaxHtPhy->field.MODE = MODE_CCK;
3175 		pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3176 		pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3177 	} else {
3178 		pMaxHtPhy->field.MODE = MODE_OFDM;
3179 		pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3180 		if (pAd->CommonCfg.MinTxRate >= RATE_6
3181 		    && (pAd->CommonCfg.MinTxRate <= RATE_54)) {
3182 			pMinHtPhy->field.MCS =
3183 			    OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
3184 		} else {
3185 			pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3186 		}
3187 	}
3188 
3189 	pHtPhy->word = (pMaxHtPhy->word);
3190 	if (bLinkUp && (pAd->OpMode == OPMODE_STA)) {
3191 		pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3192 		pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word =
3193 		    pMaxHtPhy->word;
3194 		pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word =
3195 		    pMinHtPhy->word;
3196 	} else {
3197 		switch (pAd->CommonCfg.PhyMode) {
3198 		case PHY_11BG_MIXED:
3199 		case PHY_11B:
3200 		case PHY_11BGN_MIXED:
3201 			pAd->CommonCfg.MlmeRate = RATE_1;
3202 			pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3203 			pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3204 
3205 /*#ifdef        WIFI_TEST */
3206 			pAd->CommonCfg.RtsRate = RATE_11;
3207 /*#else */
3208 /*                              pAd->CommonCfg.RtsRate = RATE_1; */
3209 /*#endif */
3210 			break;
3211 		case PHY_11G:
3212 		case PHY_11A:
3213 		case PHY_11AGN_MIXED:
3214 		case PHY_11GN_MIXED:
3215 		case PHY_11N_2_4G:
3216 		case PHY_11AN_MIXED:
3217 		case PHY_11N_5G:
3218 			pAd->CommonCfg.MlmeRate = RATE_6;
3219 			pAd->CommonCfg.RtsRate = RATE_6;
3220 			pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3221 			pAd->CommonCfg.MlmeTransmit.field.MCS =
3222 			    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3223 			break;
3224 		case PHY_11ABG_MIXED:
3225 		case PHY_11ABGN_MIXED:
3226 			if (pAd->CommonCfg.Channel <= 14) {
3227 				pAd->CommonCfg.MlmeRate = RATE_1;
3228 				pAd->CommonCfg.RtsRate = RATE_1;
3229 				pAd->CommonCfg.MlmeTransmit.field.MODE =
3230 				    MODE_CCK;
3231 				pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3232 			} else {
3233 				pAd->CommonCfg.MlmeRate = RATE_6;
3234 				pAd->CommonCfg.RtsRate = RATE_6;
3235 				pAd->CommonCfg.MlmeTransmit.field.MODE =
3236 				    MODE_OFDM;
3237 				pAd->CommonCfg.MlmeTransmit.field.MCS =
3238 				    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3239 			}
3240 			break;
3241 		default:	/* error */
3242 			pAd->CommonCfg.MlmeRate = RATE_6;
3243 			pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3244 			pAd->CommonCfg.MlmeTransmit.field.MCS =
3245 			    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3246 			pAd->CommonCfg.RtsRate = RATE_1;
3247 			break;
3248 		}
3249 		/* */
3250 		/* Keep Basic Mlme Rate. */
3251 		/* */
3252 		pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word =
3253 		    pAd->CommonCfg.MlmeTransmit.word;
3254 		if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3255 			pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3256 			    OfdmRateToRxwiMCS[RATE_24];
3257 		else
3258 			pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3259 			    RATE_1;
3260 		pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3261 	}
3262 
3263 	DBGPRINT(RT_DEBUG_TRACE,
3264 		 (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3265 		  RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
3266 		  RateIdToMbps[pAd->CommonCfg.MaxTxRate],
3267 		  RateIdToMbps[pAd->CommonCfg.MinTxRate],
3268 		  /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3269 		  *auto_rate_cur_p));
3270 	DBGPRINT(RT_DEBUG_TRACE,
3271 		 (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3272 		  RateIdToMbps[pAd->CommonCfg.TxRate],
3273 		  RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3274 	DBGPRINT(RT_DEBUG_TRACE,
3275 		 ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3276 		  pAd->CommonCfg.MlmeTransmit.word,
3277 		  pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
3278 		  pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
3279 		  pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word));
3280 }
3281 
3282 /*
3283 	==========================================================================
3284 	Description:
3285 		This function update HT Rate setting.
3286 		Input Wcid value is valid for 2 case :
3287 		1. it's used for Station in infra mode that copy AP rate to Mactable.
3288 		2. OR Station	in adhoc mode to copy peer's HT rate to Mactable.
3289 
3290  IRQL = DISPATCH_LEVEL
3291 
3292 	==========================================================================
3293  */
MlmeUpdateHtTxRates(struct rt_rtmp_adapter * pAd,u8 apidx)3294 void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx)
3295 {
3296 	u8 StbcMcs;		/*j, StbcMcs, bitmask; */
3297 	char i;			/* 3*3 */
3298 	struct rt_ht_capability *pRtHtCap = NULL;
3299 	struct rt_ht_phy_info *pActiveHtPhy = NULL;
3300 	unsigned long BasicMCS;
3301 	u8 j, bitmask;
3302 	struct rt_ht_phy_info *pDesireHtPhy = NULL;
3303 	PHTTRANSMIT_SETTING pHtPhy = NULL;
3304 	PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3305 	PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3306 	BOOLEAN *auto_rate_cur_p;
3307 
3308 	DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n"));
3309 
3310 	auto_rate_cur_p = NULL;
3311 
3312 	{
3313 		pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3314 		pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3315 		pHtPhy = &pAd->StaCfg.HTPhyMode;
3316 		pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3317 		pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3318 
3319 		auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3320 	}
3321 
3322 	if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
3323 		if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3324 			return;
3325 
3326 		pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3327 		pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3328 		StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3329 		BasicMCS =
3330 		    pAd->MlmeAux.AddHtInfo.MCSSet[0] +
3331 		    (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3332 		if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3333 		    && (pAd->Antenna.field.TxPath == 2))
3334 			pMaxHtPhy->field.STBC = STBC_USE;
3335 		else
3336 			pMaxHtPhy->field.STBC = STBC_NONE;
3337 	} else {
3338 		if (pDesireHtPhy->bHtEnable == FALSE)
3339 			return;
3340 
3341 		pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3342 		StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3343 		BasicMCS =
3344 		    pAd->CommonCfg.AddHTInfo.MCSSet[0] +
3345 		    (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3346 		if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3347 		    && (pAd->Antenna.field.TxPath == 2))
3348 			pMaxHtPhy->field.STBC = STBC_USE;
3349 		else
3350 			pMaxHtPhy->field.STBC = STBC_NONE;
3351 	}
3352 
3353 	/* Decide MAX ht rate. */
3354 	if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3355 		pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3356 	else
3357 		pMaxHtPhy->field.MODE = MODE_HTMIX;
3358 
3359 	if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth)
3360 	    && (pRtHtCap->ChannelWidth))
3361 		pMaxHtPhy->field.BW = BW_40;
3362 	else
3363 		pMaxHtPhy->field.BW = BW_20;
3364 
3365 	if (pMaxHtPhy->field.BW == BW_20)
3366 		pMaxHtPhy->field.ShortGI =
3367 		    (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->
3368 		     ShortGIfor20);
3369 	else
3370 		pMaxHtPhy->field.ShortGI =
3371 		    (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->
3372 		     ShortGIfor40);
3373 
3374 	if (pDesireHtPhy->MCSSet[4] != 0) {
3375 		pMaxHtPhy->field.MCS = 32;
3376 	}
3377 
3378 	for (i = 23; i >= 0; i--)	/* 3*3 */
3379 	{
3380 		j = i / 8;
3381 		bitmask = (1 << (i - (j * 8)));
3382 
3383 		if ((pActiveHtPhy->MCSSet[j] & bitmask)
3384 		    && (pDesireHtPhy->MCSSet[j] & bitmask)) {
3385 			pMaxHtPhy->field.MCS = i;
3386 			break;
3387 		}
3388 
3389 		if (i == 0)
3390 			break;
3391 	}
3392 
3393 	/* Copy MIN ht rate.  rt2860??? */
3394 	pMinHtPhy->field.BW = BW_20;
3395 	pMinHtPhy->field.MCS = 0;
3396 	pMinHtPhy->field.STBC = 0;
3397 	pMinHtPhy->field.ShortGI = 0;
3398 	/*If STA assigns fixed rate. update to fixed here. */
3399 	if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) {
3400 		if (pDesireHtPhy->MCSSet[4] != 0) {
3401 			pMaxHtPhy->field.MCS = 32;
3402 			pMinHtPhy->field.MCS = 32;
3403 			DBGPRINT(RT_DEBUG_TRACE,
3404 				 ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3405 				  pMinHtPhy->field.MCS));
3406 		}
3407 
3408 		for (i = 23; (char)i >= 0; i--)	/* 3*3 */
3409 		{
3410 			j = i / 8;
3411 			bitmask = (1 << (i - (j * 8)));
3412 			if ((pDesireHtPhy->MCSSet[j] & bitmask)
3413 			    && (pActiveHtPhy->MCSSet[j] & bitmask)) {
3414 				pMaxHtPhy->field.MCS = i;
3415 				pMinHtPhy->field.MCS = i;
3416 				break;
3417 			}
3418 			if (i == 0)
3419 				break;
3420 		}
3421 	}
3422 
3423 	/* Decide ht rate */
3424 	pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3425 	pHtPhy->field.BW = pMaxHtPhy->field.BW;
3426 	pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3427 	pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3428 	pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3429 
3430 	/* use default now. rt2860 */
3431 	if (pDesireHtPhy->MCSSet[0] != 0xff)
3432 		*auto_rate_cur_p = FALSE;
3433 	else
3434 		*auto_rate_cur_p = TRUE;
3435 
3436 	DBGPRINT(RT_DEBUG_TRACE,
3437 		 (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n",
3438 		  pAd->CommonCfg.DesiredHtPhy.AmsduSize));
3439 	DBGPRINT(RT_DEBUG_TRACE,
3440 		 ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n",
3441 		  pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW,
3442 		  pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3443 	DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n"));
3444 }
3445 
BATableInit(struct rt_rtmp_adapter * pAd,struct rt_ba_table * Tab)3446 void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab)
3447 {
3448 	int i;
3449 
3450 	Tab->numAsOriginator = 0;
3451 	Tab->numAsRecipient = 0;
3452 	Tab->numDoneOriginator = 0;
3453 	NdisAllocateSpinLock(&pAd->BATabLock);
3454 	for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
3455 		Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3456 		NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3457 	}
3458 	for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
3459 		Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3460 	}
3461 }
3462 
3463 /* IRQL = DISPATCH_LEVEL */
MlmeRadioOff(struct rt_rtmp_adapter * pAd)3464 void MlmeRadioOff(struct rt_rtmp_adapter *pAd)
3465 {
3466 	RTMP_MLME_RADIO_OFF(pAd);
3467 }
3468 
3469 /* IRQL = DISPATCH_LEVEL */
MlmeRadioOn(struct rt_rtmp_adapter * pAd)3470 void MlmeRadioOn(struct rt_rtmp_adapter *pAd)
3471 {
3472 	RTMP_MLME_RADIO_ON(pAd);
3473 }
3474 
3475 /* =========================================================================================== */
3476 /* bss_table.c */
3477 /* =========================================================================================== */
3478 
3479 /*! \brief initialize BSS table
3480  *	\param p_tab pointer to the table
3481  *	\return none
3482  *	\pre
3483  *	\post
3484 
3485  IRQL = PASSIVE_LEVEL
3486  IRQL = DISPATCH_LEVEL
3487 
3488  */
BssTableInit(struct rt_bss_table * Tab)3489 void BssTableInit(struct rt_bss_table *Tab)
3490 {
3491 	int i;
3492 
3493 	Tab->BssNr = 0;
3494 	Tab->BssOverlapNr = 0;
3495 	for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) {
3496 		NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry));
3497 		Tab->BssEntry[i].Rssi = -127;	/* initial the rssi as a minimum value */
3498 	}
3499 }
3500 
3501 /*! \brief search the BSS table by SSID
3502  *	\param p_tab pointer to the bss table
3503  *	\param ssid SSID string
3504  *	\return index of the table, BSS_NOT_FOUND if not in the table
3505  *	\pre
3506  *	\post
3507  *	\note search by sequential search
3508 
3509  IRQL = DISPATCH_LEVEL
3510 
3511  */
BssTableSearch(struct rt_bss_table * Tab,u8 * pBssid,u8 Channel)3512 unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel)
3513 {
3514 	u8 i;
3515 
3516 	for (i = 0; i < Tab->BssNr; i++) {
3517 		/* */
3518 		/* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3519 		/* We should distinguish this case. */
3520 		/* */
3521 		if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3522 		     ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3523 		    MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) {
3524 			return i;
3525 		}
3526 	}
3527 	return (unsigned long)BSS_NOT_FOUND;
3528 }
3529 
BssSsidTableSearch(struct rt_bss_table * Tab,u8 * pBssid,u8 * pSsid,u8 SsidLen,u8 Channel)3530 unsigned long BssSsidTableSearch(struct rt_bss_table *Tab,
3531 			 u8 *pBssid,
3532 			 u8 *pSsid, u8 SsidLen, u8 Channel)
3533 {
3534 	u8 i;
3535 
3536 	for (i = 0; i < Tab->BssNr; i++) {
3537 		/* */
3538 		/* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3539 		/* We should distinguish this case. */
3540 		/* */
3541 		if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3542 		     ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3543 		    MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3544 		    SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3545 			       Tab->BssEntry[i].SsidLen)) {
3546 			return i;
3547 		}
3548 	}
3549 	return (unsigned long)BSS_NOT_FOUND;
3550 }
3551 
BssTableSearchWithSSID(struct rt_bss_table * Tab,u8 * Bssid,u8 * pSsid,u8 SsidLen,u8 Channel)3552 unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab,
3553 			     u8 *Bssid,
3554 			     u8 *pSsid,
3555 			     u8 SsidLen, u8 Channel)
3556 {
3557 	u8 i;
3558 
3559 	for (i = 0; i < Tab->BssNr; i++) {
3560 		if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3561 		     ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3562 		    MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3563 		    (SSID_EQUAL
3564 		     (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3565 		      Tab->BssEntry[i].SsidLen)
3566 		     || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen))
3567 		     ||
3568 		     (NdisEqualMemory
3569 		      (Tab->BssEntry[i].Ssid, ZeroSsid,
3570 		       Tab->BssEntry[i].SsidLen)))) {
3571 			return i;
3572 		}
3573 	}
3574 	return (unsigned long)BSS_NOT_FOUND;
3575 }
3576 
BssSsidTableSearchBySSID(struct rt_bss_table * Tab,u8 * pSsid,u8 SsidLen)3577 unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab,
3578 			       u8 *pSsid, u8 SsidLen)
3579 {
3580 	u8 i;
3581 
3582 	for (i = 0; i < Tab->BssNr; i++) {
3583 		if (SSID_EQUAL
3584 		    (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3585 		     Tab->BssEntry[i].SsidLen)) {
3586 			return i;
3587 		}
3588 	}
3589 	return (unsigned long)BSS_NOT_FOUND;
3590 }
3591 
3592 /* IRQL = DISPATCH_LEVEL */
BssTableDeleteEntry(struct rt_bss_table * Tab,u8 * pBssid,u8 Channel)3593 void BssTableDeleteEntry(struct rt_bss_table *Tab,
3594 			 u8 *pBssid, u8 Channel)
3595 {
3596 	u8 i, j;
3597 
3598 	for (i = 0; i < Tab->BssNr; i++) {
3599 		if ((Tab->BssEntry[i].Channel == Channel) &&
3600 		    (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) {
3601 			for (j = i; j < Tab->BssNr - 1; j++) {
3602 				NdisMoveMemory(&(Tab->BssEntry[j]),
3603 					       &(Tab->BssEntry[j + 1]),
3604 					       sizeof(struct rt_bss_entry));
3605 			}
3606 			NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]),
3607 				       sizeof(struct rt_bss_entry));
3608 			Tab->BssNr -= 1;
3609 			return;
3610 		}
3611 	}
3612 }
3613 
3614 /*
3615 	========================================================================
3616 	Routine Description:
3617 		Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3618 
3619 	Arguments:
3620 	// IRQL = DISPATCH_LEVEL
3621 	========================================================================
3622 */
BATableDeleteORIEntry(struct rt_rtmp_adapter * pAd,struct rt_ba_ori_entry * pBAORIEntry)3623 void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd,
3624 			   struct rt_ba_ori_entry *pBAORIEntry)
3625 {
3626 
3627 	if (pBAORIEntry->ORI_BA_Status != Originator_NONE) {
3628 		NdisAcquireSpinLock(&pAd->BATabLock);
3629 		if (pBAORIEntry->ORI_BA_Status == Originator_Done) {
3630 			pAd->BATable.numAsOriginator -= 1;
3631 			DBGPRINT(RT_DEBUG_TRACE,
3632 				 ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3633 				  pAd->BATable.numAsRecipient));
3634 			/* Erase Bitmap flag. */
3635 		}
3636 		pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID)));	/* If STA mode,  erase flag here */
3637 		pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;	/* If STA mode,  erase flag here */
3638 		pBAORIEntry->ORI_BA_Status = Originator_NONE;
3639 		pBAORIEntry->Token = 1;
3640 		/* Not clear Sequence here. */
3641 		NdisReleaseSpinLock(&pAd->BATabLock);
3642 	}
3643 }
3644 
3645 /*! \brief
3646  *	\param
3647  *	\return
3648  *	\pre
3649  *	\post
3650 
3651  IRQL = DISPATCH_LEVEL
3652 
3653  */
BssEntrySet(struct rt_rtmp_adapter * pAd,struct rt_bss_entry * pBss,u8 * pBssid,char Ssid[],u8 SsidLen,u8 BssType,u16 BeaconPeriod,struct rt_cf_parm * pCfParm,u16 AtimWin,u16 CapabilityInfo,u8 SupRate[],u8 SupRateLen,u8 ExtRate[],u8 ExtRateLen,struct rt_ht_capability_ie * pHtCapability,struct rt_add_ht_info_ie * pAddHtInfo,u8 HtCapabilityLen,u8 AddHtInfoLen,u8 NewExtChanOffset,u8 Channel,char Rssi,IN LARGE_INTEGER TimeStamp,u8 CkipFlag,struct rt_edca_parm * pEdcaParm,struct rt_qos_capability_parm * pQosCapability,struct rt_qbss_load_parm * pQbssLoad,u16 LengthVIE,struct rt_ndis_802_11_variable_ies * pVIE)3654 void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * pCfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo,	/* AP might use this additional ht info IE */
3655 		 u8 HtCapabilityLen,
3656 		 u8 AddHtInfoLen,
3657 		 u8 NewExtChanOffset,
3658 		 u8 Channel,
3659 		 char Rssi,
3660 		 IN LARGE_INTEGER TimeStamp,
3661 		 u8 CkipFlag,
3662 		 struct rt_edca_parm *pEdcaParm,
3663 		 struct rt_qos_capability_parm *pQosCapability,
3664 		 struct rt_qbss_load_parm *pQbssLoad,
3665 		 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
3666 {
3667 	COPY_MAC_ADDR(pBss->Bssid, pBssid);
3668 	/* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */
3669 	pBss->Hidden = 1;
3670 	if (SsidLen > 0) {
3671 		/* For hidden SSID AP, it might send beacon with SSID len equal to 0 */
3672 		/* Or send beacon /probe response with SSID len matching real SSID length, */
3673 		/* but SSID is all zero. such as "00-00-00-00" with length 4. */
3674 		/* We have to prevent this case overwrite correct table */
3675 		if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) {
3676 			NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3677 			NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3678 			pBss->SsidLen = SsidLen;
3679 			pBss->Hidden = 0;
3680 		}
3681 	} else
3682 		pBss->SsidLen = 0;
3683 	pBss->BssType = BssType;
3684 	pBss->BeaconPeriod = BeaconPeriod;
3685 	if (BssType == BSS_INFRA) {
3686 		if (pCfParm->bValid) {
3687 			pBss->CfpCount = pCfParm->CfpCount;
3688 			pBss->CfpPeriod = pCfParm->CfpPeriod;
3689 			pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3690 			pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3691 		}
3692 	} else {
3693 		pBss->AtimWin = AtimWin;
3694 	}
3695 
3696 	pBss->CapabilityInfo = CapabilityInfo;
3697 	/* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */
3698 	/* Combine with AuthMode, they will decide the connection methods. */
3699 	pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3700 	ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3701 	if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3702 		NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3703 	else
3704 		NdisMoveMemory(pBss->SupRate, SupRate,
3705 			       MAX_LEN_OF_SUPPORTED_RATES);
3706 	pBss->SupRateLen = SupRateLen;
3707 	ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3708 	NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3709 	pBss->NewExtChanOffset = NewExtChanOffset;
3710 	pBss->ExtRateLen = ExtRateLen;
3711 	pBss->Channel = Channel;
3712 	pBss->CentralChannel = Channel;
3713 	pBss->Rssi = Rssi;
3714 	/* Update CkipFlag. if not exists, the value is 0x0 */
3715 	pBss->CkipFlag = CkipFlag;
3716 
3717 	/* New for microsoft Fixed IEs */
3718 	NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3719 	pBss->FixIEs.BeaconInterval = BeaconPeriod;
3720 	pBss->FixIEs.Capabilities = CapabilityInfo;
3721 
3722 	/* New for microsoft Variable IEs */
3723 	if (LengthVIE != 0) {
3724 		pBss->VarIELen = LengthVIE;
3725 		NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3726 	} else {
3727 		pBss->VarIELen = 0;
3728 	}
3729 
3730 	pBss->AddHtInfoLen = 0;
3731 	pBss->HtCapabilityLen = 0;
3732 	if (HtCapabilityLen > 0) {
3733 		pBss->HtCapabilityLen = HtCapabilityLen;
3734 		NdisMoveMemory(&pBss->HtCapability, pHtCapability,
3735 			       HtCapabilityLen);
3736 		if (AddHtInfoLen > 0) {
3737 			pBss->AddHtInfoLen = AddHtInfoLen;
3738 			NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo,
3739 				       AddHtInfoLen);
3740 
3741 			if ((pAddHtInfo->ControlChan > 2)
3742 			    && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
3743 				EXTCHA_BELOW)
3744 			    && (pHtCapability->HtCapInfo.ChannelWidth ==
3745 				BW_40)) {
3746 				pBss->CentralChannel =
3747 				    pAddHtInfo->ControlChan - 2;
3748 			} else
3749 			    if ((pAddHtInfo->AddHtInfo.ExtChanOffset ==
3750 				 EXTCHA_ABOVE)
3751 				&& (pHtCapability->HtCapInfo.ChannelWidth ==
3752 				    BW_40)) {
3753 				pBss->CentralChannel =
3754 				    pAddHtInfo->ControlChan + 2;
3755 			}
3756 		}
3757 	}
3758 
3759 	BssCipherParse(pBss);
3760 
3761 	/* new for QOS */
3762 	if (pEdcaParm)
3763 		NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm));
3764 	else
3765 		pBss->EdcaParm.bValid = FALSE;
3766 	if (pQosCapability)
3767 		NdisMoveMemory(&pBss->QosCapability, pQosCapability,
3768 			       sizeof(struct rt_qos_capability_parm));
3769 	else
3770 		pBss->QosCapability.bValid = FALSE;
3771 	if (pQbssLoad)
3772 		NdisMoveMemory(&pBss->QbssLoad, pQbssLoad,
3773 			       sizeof(struct rt_qbss_load_parm));
3774 	else
3775 		pBss->QbssLoad.bValid = FALSE;
3776 
3777 	{
3778 		struct rt_eid * pEid;
3779 		u16 Length = 0;
3780 
3781 		NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3782 		NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3783 		pEid = (struct rt_eid *) pVIE;
3784 		while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) {
3785 			switch (pEid->Eid) {
3786 			case IE_WPA:
3787 				if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) {
3788 					if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3789 						pBss->WpaIE.IELen = 0;
3790 						break;
3791 					}
3792 					pBss->WpaIE.IELen = pEid->Len + 2;
3793 					NdisMoveMemory(pBss->WpaIE.IE, pEid,
3794 						       pBss->WpaIE.IELen);
3795 				}
3796 				break;
3797 			case IE_RSN:
3798 				if (NdisEqualMemory
3799 				    (pEid->Octet + 2, RSN_OUI, 3)) {
3800 					if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3801 						pBss->RsnIE.IELen = 0;
3802 						break;
3803 					}
3804 					pBss->RsnIE.IELen = pEid->Len + 2;
3805 					NdisMoveMemory(pBss->RsnIE.IE, pEid,
3806 						       pBss->RsnIE.IELen);
3807 				}
3808 				break;
3809 			}
3810 			Length = Length + 2 + (u16)pEid->Len;	/* Eid[1] + Len[1]+ content[Len] */
3811 			pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len);
3812 		}
3813 	}
3814 }
3815 
3816 /*!
3817  *	\brief insert an entry into the bss table
3818  *	\param p_tab The BSS table
3819  *	\param Bssid BSSID
3820  *	\param ssid SSID
3821  *	\param ssid_len Length of SSID
3822  *	\param bss_type
3823  *	\param beacon_period
3824  *	\param timestamp
3825  *	\param p_cf
3826  *	\param atim_win
3827  *	\param cap
3828  *	\param rates
3829  *	\param rates_len
3830  *	\param channel_idx
3831  *	\return none
3832  *	\pre
3833  *	\post
3834  *	\note If SSID is identical, the old entry will be replaced by the new one
3835 
3836  IRQL = DISPATCH_LEVEL
3837 
3838  */
BssTableSetEntry(struct rt_rtmp_adapter * pAd,struct rt_bss_table * Tab,u8 * pBssid,char Ssid[],u8 SsidLen,u8 BssType,u16 BeaconPeriod,struct rt_cf_parm * CfParm,u16 AtimWin,u16 CapabilityInfo,u8 SupRate[],u8 SupRateLen,u8 ExtRate[],u8 ExtRateLen,struct rt_ht_capability_ie * pHtCapability,struct rt_add_ht_info_ie * pAddHtInfo,u8 HtCapabilityLen,u8 AddHtInfoLen,u8 NewExtChanOffset,u8 ChannelNo,char Rssi,IN LARGE_INTEGER TimeStamp,u8 CkipFlag,struct rt_edca_parm * pEdcaParm,struct rt_qos_capability_parm * pQosCapability,struct rt_qbss_load_parm * pQbssLoad,u16 LengthVIE,struct rt_ndis_802_11_variable_ies * pVIE)3839 unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *Tab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo,	/* AP might use this additional ht info IE */
3840 		       u8 HtCapabilityLen,
3841 		       u8 AddHtInfoLen,
3842 		       u8 NewExtChanOffset,
3843 		       u8 ChannelNo,
3844 		       char Rssi,
3845 		       IN LARGE_INTEGER TimeStamp,
3846 		       u8 CkipFlag,
3847 		       struct rt_edca_parm *pEdcaParm,
3848 		       struct rt_qos_capability_parm *pQosCapability,
3849 		       struct rt_qbss_load_parm *pQbssLoad,
3850 		       u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
3851 {
3852 	unsigned long Idx;
3853 
3854 	Idx =
3855 	    BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen,
3856 				   ChannelNo);
3857 	if (Idx == BSS_NOT_FOUND) {
3858 		if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) {
3859 			/* */
3860 			/* It may happen when BSS Table was full. */
3861 			/* The desired AP will not be added into BSS Table */
3862 			/* In this case, if we found the desired AP then overwrite BSS Table. */
3863 			/* */
3864 			if (!OPSTATUS_TEST_FLAG
3865 			    (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
3866 				if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid)
3867 				    || SSID_EQUAL(pAd->MlmeAux.Ssid,
3868 						  pAd->MlmeAux.SsidLen, Ssid,
3869 						  SsidLen)) {
3870 					Idx = Tab->BssOverlapNr;
3871 					BssEntrySet(pAd, &Tab->BssEntry[Idx],
3872 						    pBssid, Ssid, SsidLen,
3873 						    BssType, BeaconPeriod,
3874 						    CfParm, AtimWin,
3875 						    CapabilityInfo, SupRate,
3876 						    SupRateLen, ExtRate,
3877 						    ExtRateLen, pHtCapability,
3878 						    pAddHtInfo, HtCapabilityLen,
3879 						    AddHtInfoLen,
3880 						    NewExtChanOffset, ChannelNo,
3881 						    Rssi, TimeStamp, CkipFlag,
3882 						    pEdcaParm, pQosCapability,
3883 						    pQbssLoad, LengthVIE, pVIE);
3884 					Tab->BssOverlapNr =
3885 					    (Tab->BssOverlapNr++) %
3886 					    MAX_LEN_OF_BSS_TABLE;
3887 				}
3888 				return Idx;
3889 			} else {
3890 				return BSS_NOT_FOUND;
3891 			}
3892 		}
3893 		Idx = Tab->BssNr;
3894 		BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen,
3895 			    BssType, BeaconPeriod, CfParm, AtimWin,
3896 			    CapabilityInfo, SupRate, SupRateLen, ExtRate,
3897 			    ExtRateLen, pHtCapability, pAddHtInfo,
3898 			    HtCapabilityLen, AddHtInfoLen, NewExtChanOffset,
3899 			    ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm,
3900 			    pQosCapability, pQbssLoad, LengthVIE, pVIE);
3901 		Tab->BssNr++;
3902 	} else {
3903 		/* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
3904 		if ((SSID_EQUAL
3905 		     (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid,
3906 		      Tab->BssEntry[Idx].SsidLen))
3907 		    ||
3908 		    (NdisEqualMemory
3909 		     (Tab->BssEntry[Idx].Ssid, ZeroSsid,
3910 		      Tab->BssEntry[Idx].SsidLen))) {
3911 			BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid,
3912 				    SsidLen, BssType, BeaconPeriod, CfParm,
3913 				    AtimWin, CapabilityInfo, SupRate,
3914 				    SupRateLen, ExtRate, ExtRateLen,
3915 				    pHtCapability, pAddHtInfo, HtCapabilityLen,
3916 				    AddHtInfoLen, NewExtChanOffset, ChannelNo,
3917 				    Rssi, TimeStamp, CkipFlag, pEdcaParm,
3918 				    pQosCapability, pQbssLoad, LengthVIE, pVIE);
3919 		}
3920 	}
3921 
3922 	return Idx;
3923 }
3924 
3925 /* IRQL = DISPATCH_LEVEL */
BssTableSsidSort(struct rt_rtmp_adapter * pAd,struct rt_bss_table * OutTab,char Ssid[],u8 SsidLen)3926 void BssTableSsidSort(struct rt_rtmp_adapter *pAd,
3927 		      struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen)
3928 {
3929 	int i;
3930 	BssTableInit(OutTab);
3931 
3932 	for (i = 0; i < pAd->ScanTab.BssNr; i++) {
3933 		struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i];
3934 		BOOLEAN bIsHiddenApIncluded = FALSE;
3935 
3936 		if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3937 		     (pAd->MlmeAux.Channel > 14) &&
3938 		     RadarChannelCheck(pAd, pInBss->Channel))
3939 		    ) {
3940 			if (pInBss->Hidden)
3941 				bIsHiddenApIncluded = TRUE;
3942 		}
3943 
3944 		if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3945 		    (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen)
3946 		     || bIsHiddenApIncluded)) {
3947 			struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3948 
3949 			/* 2.4G/5G N only mode */
3950 			if ((pInBss->HtCapabilityLen == 0) &&
3951 			    ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
3952 			     || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
3953 				DBGPRINT(RT_DEBUG_TRACE,
3954 					 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3955 				continue;
3956 			}
3957 			/* New for WPA2 */
3958 			/* Check the Authmode first */
3959 			if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
3960 				/* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
3961 				if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
3962 				    && (pAd->StaCfg.AuthMode !=
3963 					pInBss->AuthModeAux))
3964 					/* None matched */
3965 					continue;
3966 
3967 				/* Check cipher suite, AP must have more secured cipher than station setting */
3968 				if ((pAd->StaCfg.AuthMode ==
3969 				     Ndis802_11AuthModeWPA)
3970 				    || (pAd->StaCfg.AuthMode ==
3971 					Ndis802_11AuthModeWPAPSK)) {
3972 					/* If it's not mixed mode, we should only let BSS pass with the same encryption */
3973 					if (pInBss->WPA.bMixMode == FALSE)
3974 						if (pAd->StaCfg.WepStatus !=
3975 						    pInBss->WPA.GroupCipher)
3976 							continue;
3977 
3978 					/* check group cipher */
3979 					if ((pAd->StaCfg.WepStatus <
3980 					     pInBss->WPA.GroupCipher)
3981 					    && (pInBss->WPA.GroupCipher !=
3982 						Ndis802_11GroupWEP40Enabled)
3983 					    && (pInBss->WPA.GroupCipher !=
3984 						Ndis802_11GroupWEP104Enabled))
3985 						continue;
3986 
3987 					/* check pairwise cipher, skip if none matched */
3988 					/* If profile set to AES, let it pass without question. */
3989 					/* If profile set to TKIP, we must find one mateched */
3990 					if ((pAd->StaCfg.WepStatus ==
3991 					     Ndis802_11Encryption2Enabled)
3992 					    && (pAd->StaCfg.WepStatus !=
3993 						pInBss->WPA.PairCipher)
3994 					    && (pAd->StaCfg.WepStatus !=
3995 						pInBss->WPA.PairCipherAux))
3996 						continue;
3997 				} else
3998 				    if ((pAd->StaCfg.AuthMode ==
3999 					 Ndis802_11AuthModeWPA2)
4000 					|| (pAd->StaCfg.AuthMode ==
4001 					    Ndis802_11AuthModeWPA2PSK)) {
4002 					/* If it's not mixed mode, we should only let BSS pass with the same encryption */
4003 					if (pInBss->WPA2.bMixMode == FALSE)
4004 						if (pAd->StaCfg.WepStatus !=
4005 						    pInBss->WPA2.GroupCipher)
4006 							continue;
4007 
4008 					/* check group cipher */
4009 					if ((pAd->StaCfg.WepStatus <
4010 					     pInBss->WPA.GroupCipher)
4011 					    && (pInBss->WPA2.GroupCipher !=
4012 						Ndis802_11GroupWEP40Enabled)
4013 					    && (pInBss->WPA2.GroupCipher !=
4014 						Ndis802_11GroupWEP104Enabled))
4015 						continue;
4016 
4017 					/* check pairwise cipher, skip if none matched */
4018 					/* If profile set to AES, let it pass without question. */
4019 					/* If profile set to TKIP, we must find one mateched */
4020 					if ((pAd->StaCfg.WepStatus ==
4021 					     Ndis802_11Encryption2Enabled)
4022 					    && (pAd->StaCfg.WepStatus !=
4023 						pInBss->WPA2.PairCipher)
4024 					    && (pAd->StaCfg.WepStatus !=
4025 						pInBss->WPA2.PairCipherAux))
4026 						continue;
4027 				}
4028 			}
4029 			/* Bss Type matched, SSID matched. */
4030 			/* We will check wepstatus for qualification Bss */
4031 			else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) {
4032 				DBGPRINT(RT_DEBUG_TRACE,
4033 					 ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4034 					  pAd->StaCfg.WepStatus,
4035 					  pInBss->WepStatus));
4036 				/* */
4037 				/* For the SESv2 case, we will not qualify WepStatus. */
4038 				/* */
4039 				if (!pInBss->bSES)
4040 					continue;
4041 			}
4042 			/* Since the AP is using hidden SSID, and we are trying to connect to ANY */
4043 			/* It definitely will fail. So, skip it. */
4044 			/* CCX also require not even try to connect it! */
4045 			if (SsidLen == 0)
4046 				continue;
4047 
4048 			/* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4049 			/* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4050 			if ((pInBss->CentralChannel != pInBss->Channel) &&
4051 			    (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4052 			     BW_40)) {
4053 				if (RTMPCheckChannel
4054 				    (pAd, pInBss->CentralChannel,
4055 				     pInBss->Channel) == FALSE) {
4056 					pAd->CommonCfg.RegTransmitSetting.field.
4057 					    BW = BW_20;
4058 					SetCommonHT(pAd);
4059 					pAd->CommonCfg.RegTransmitSetting.field.
4060 					    BW = BW_40;
4061 				} else {
4062 					if (pAd->CommonCfg.DesiredHtPhy.
4063 					    ChannelWidth == BAND_WIDTH_20) {
4064 						SetCommonHT(pAd);
4065 					}
4066 				}
4067 			}
4068 			/* copy matching BSS from InTab to OutTab */
4069 			NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
4070 
4071 			OutTab->BssNr++;
4072 		} else if ((pInBss->BssType == pAd->StaCfg.BssType)
4073 			   && (SsidLen == 0)) {
4074 			struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4075 
4076 			/* 2.4G/5G N only mode */
4077 			if ((pInBss->HtCapabilityLen == 0) &&
4078 			    ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
4079 			     || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
4080 				DBGPRINT(RT_DEBUG_TRACE,
4081 					 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4082 				continue;
4083 			}
4084 			/* New for WPA2 */
4085 			/* Check the Authmode first */
4086 			if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
4087 				/* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
4088 				if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
4089 				    && (pAd->StaCfg.AuthMode !=
4090 					pInBss->AuthModeAux))
4091 					/* None matched */
4092 					continue;
4093 
4094 				/* Check cipher suite, AP must have more secured cipher than station setting */
4095 				if ((pAd->StaCfg.AuthMode ==
4096 				     Ndis802_11AuthModeWPA)
4097 				    || (pAd->StaCfg.AuthMode ==
4098 					Ndis802_11AuthModeWPAPSK)) {
4099 					/* If it's not mixed mode, we should only let BSS pass with the same encryption */
4100 					if (pInBss->WPA.bMixMode == FALSE)
4101 						if (pAd->StaCfg.WepStatus !=
4102 						    pInBss->WPA.GroupCipher)
4103 							continue;
4104 
4105 					/* check group cipher */
4106 					if (pAd->StaCfg.WepStatus <
4107 					    pInBss->WPA.GroupCipher)
4108 						continue;
4109 
4110 					/* check pairwise cipher, skip if none matched */
4111 					/* If profile set to AES, let it pass without question. */
4112 					/* If profile set to TKIP, we must find one mateched */
4113 					if ((pAd->StaCfg.WepStatus ==
4114 					     Ndis802_11Encryption2Enabled)
4115 					    && (pAd->StaCfg.WepStatus !=
4116 						pInBss->WPA.PairCipher)
4117 					    && (pAd->StaCfg.WepStatus !=
4118 						pInBss->WPA.PairCipherAux))
4119 						continue;
4120 				} else
4121 				    if ((pAd->StaCfg.AuthMode ==
4122 					 Ndis802_11AuthModeWPA2)
4123 					|| (pAd->StaCfg.AuthMode ==
4124 					    Ndis802_11AuthModeWPA2PSK)) {
4125 					/* If it's not mixed mode, we should only let BSS pass with the same encryption */
4126 					if (pInBss->WPA2.bMixMode == FALSE)
4127 						if (pAd->StaCfg.WepStatus !=
4128 						    pInBss->WPA2.GroupCipher)
4129 							continue;
4130 
4131 					/* check group cipher */
4132 					if (pAd->StaCfg.WepStatus <
4133 					    pInBss->WPA2.GroupCipher)
4134 						continue;
4135 
4136 					/* check pairwise cipher, skip if none matched */
4137 					/* If profile set to AES, let it pass without question. */
4138 					/* If profile set to TKIP, we must find one mateched */
4139 					if ((pAd->StaCfg.WepStatus ==
4140 					     Ndis802_11Encryption2Enabled)
4141 					    && (pAd->StaCfg.WepStatus !=
4142 						pInBss->WPA2.PairCipher)
4143 					    && (pAd->StaCfg.WepStatus !=
4144 						pInBss->WPA2.PairCipherAux))
4145 						continue;
4146 				}
4147 			}
4148 			/* Bss Type matched, SSID matched. */
4149 			/* We will check wepstatus for qualification Bss */
4150 			else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4151 				continue;
4152 
4153 			/* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4154 			/* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4155 			if ((pInBss->CentralChannel != pInBss->Channel) &&
4156 			    (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4157 			     BW_40)) {
4158 				if (RTMPCheckChannel
4159 				    (pAd, pInBss->CentralChannel,
4160 				     pInBss->Channel) == FALSE) {
4161 					pAd->CommonCfg.RegTransmitSetting.field.
4162 					    BW = BW_20;
4163 					SetCommonHT(pAd);
4164 					pAd->CommonCfg.RegTransmitSetting.field.
4165 					    BW = BW_40;
4166 				}
4167 			}
4168 			/* copy matching BSS from InTab to OutTab */
4169 			NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
4170 
4171 			OutTab->BssNr++;
4172 		}
4173 
4174 		if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4175 			break;
4176 	}
4177 
4178 	BssTableSortByRssi(OutTab);
4179 }
4180 
4181 /* IRQL = DISPATCH_LEVEL */
BssTableSortByRssi(struct rt_bss_table * OutTab)4182 void BssTableSortByRssi(struct rt_bss_table *OutTab)
4183 {
4184 	int i, j;
4185 	struct rt_bss_entry TmpBss;
4186 
4187 	for (i = 0; i < OutTab->BssNr - 1; i++) {
4188 		for (j = i + 1; j < OutTab->BssNr; j++) {
4189 			if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) {
4190 				NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j],
4191 					       sizeof(struct rt_bss_entry));
4192 				NdisMoveMemory(&OutTab->BssEntry[j],
4193 					       &OutTab->BssEntry[i],
4194 					       sizeof(struct rt_bss_entry));
4195 				NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss,
4196 					       sizeof(struct rt_bss_entry));
4197 			}
4198 		}
4199 	}
4200 }
4201 
BssCipherParse(struct rt_bss_entry * pBss)4202 void BssCipherParse(struct rt_bss_entry *pBss)
4203 {
4204 	struct rt_eid * pEid;
4205 	u8 *pTmp;
4206 	struct rt_rsn_ie_header * pRsnHeader;
4207 	struct rt_cipher_suite_struct * pCipher;
4208 	struct rt_akm_suite * pAKM;
4209 	u16 Count;
4210 	int Length;
4211 	NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4212 
4213 	/* */
4214 	/* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */
4215 	/* */
4216 	if (pBss->Privacy) {
4217 		pBss->WepStatus = Ndis802_11WEPEnabled;
4218 	} else {
4219 		pBss->WepStatus = Ndis802_11WEPDisabled;
4220 	}
4221 	/* Set default to disable & open authentication before parsing variable IE */
4222 	pBss->AuthMode = Ndis802_11AuthModeOpen;
4223 	pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4224 
4225 	/* Init WPA setting */
4226 	pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4227 	pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4228 	pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4229 	pBss->WPA.RsnCapability = 0;
4230 	pBss->WPA.bMixMode = FALSE;
4231 
4232 	/* Init WPA2 setting */
4233 	pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4234 	pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4235 	pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4236 	pBss->WPA2.RsnCapability = 0;
4237 	pBss->WPA2.bMixMode = FALSE;
4238 
4239 	Length = (int)pBss->VarIELen;
4240 
4241 	while (Length > 0) {
4242 		/* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */
4243 		pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length;
4244 		pEid = (struct rt_eid *) pTmp;
4245 		switch (pEid->Eid) {
4246 		case IE_WPA:
4247 			if (NdisEqualMemory(pEid->Octet, SES_OUI, 3)
4248 			    && (pEid->Len == 7)) {
4249 				pBss->bSES = TRUE;
4250 				break;
4251 			} else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) !=
4252 				   1) {
4253 				/* if unsupported vendor specific IE */
4254 				break;
4255 			}
4256 			/* Skip OUI, version, and multicast suite */
4257 			/* This part should be improved in the future when AP supported multiple cipher suite. */
4258 			/* For now, it's OK since almost all APs have fixed cipher suite supported. */
4259 			/* pTmp = (u8 *)pEid->Octet; */
4260 			pTmp += 11;
4261 
4262 			/* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
4263 			/*      Value      Meaning */
4264 			/*      0                       None */
4265 			/*      1                       WEP-40 */
4266 			/*      2                       Tkip */
4267 			/*      3                       WRAP */
4268 			/*      4                       AES */
4269 			/*      5                       WEP-104 */
4270 			/* Parse group cipher */
4271 			switch (*pTmp) {
4272 			case 1:
4273 				pBss->WPA.GroupCipher =
4274 				    Ndis802_11GroupWEP40Enabled;
4275 				break;
4276 			case 5:
4277 				pBss->WPA.GroupCipher =
4278 				    Ndis802_11GroupWEP104Enabled;
4279 				break;
4280 			case 2:
4281 				pBss->WPA.GroupCipher =
4282 				    Ndis802_11Encryption2Enabled;
4283 				break;
4284 			case 4:
4285 				pBss->WPA.GroupCipher =
4286 				    Ndis802_11Encryption3Enabled;
4287 				break;
4288 			default:
4289 				break;
4290 			}
4291 			/* number of unicast suite */
4292 			pTmp += 1;
4293 
4294 			/* skip all unicast cipher suites */
4295 			/*Count = *(u16 *)pTmp; */
4296 			Count = (pTmp[1] << 8) + pTmp[0];
4297 			pTmp += sizeof(u16);
4298 
4299 			/* Parsing all unicast cipher suite */
4300 			while (Count > 0) {
4301 				/* Skip OUI */
4302 				pTmp += 3;
4303 				TmpCipher = Ndis802_11WEPDisabled;
4304 				switch (*pTmp) {
4305 				case 1:
4306 				case 5:	/* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4307 					TmpCipher =
4308 					    Ndis802_11Encryption1Enabled;
4309 					break;
4310 				case 2:
4311 					TmpCipher =
4312 					    Ndis802_11Encryption2Enabled;
4313 					break;
4314 				case 4:
4315 					TmpCipher =
4316 					    Ndis802_11Encryption3Enabled;
4317 					break;
4318 				default:
4319 					break;
4320 				}
4321 				if (TmpCipher > pBss->WPA.PairCipher) {
4322 					/* Move the lower cipher suite to PairCipherAux */
4323 					pBss->WPA.PairCipherAux =
4324 					    pBss->WPA.PairCipher;
4325 					pBss->WPA.PairCipher = TmpCipher;
4326 				} else {
4327 					pBss->WPA.PairCipherAux = TmpCipher;
4328 				}
4329 				pTmp++;
4330 				Count--;
4331 			}
4332 
4333 			/* 4. get AKM suite counts */
4334 			/*Count = *(u16 *)pTmp; */
4335 			Count = (pTmp[1] << 8) + pTmp[0];
4336 			pTmp += sizeof(u16);
4337 			pTmp += 3;
4338 
4339 			switch (*pTmp) {
4340 			case 1:
4341 				/* Set AP support WPA-enterprise mode */
4342 				if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4343 					pBss->AuthMode = Ndis802_11AuthModeWPA;
4344 				else
4345 					pBss->AuthModeAux =
4346 					    Ndis802_11AuthModeWPA;
4347 				break;
4348 			case 2:
4349 				/* Set AP support WPA-PSK mode */
4350 				if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4351 					pBss->AuthMode =
4352 					    Ndis802_11AuthModeWPAPSK;
4353 				else
4354 					pBss->AuthModeAux =
4355 					    Ndis802_11AuthModeWPAPSK;
4356 				break;
4357 			default:
4358 				break;
4359 			}
4360 			pTmp += 1;
4361 
4362 			/* Fixed for WPA-None */
4363 			if (pBss->BssType == BSS_ADHOC) {
4364 				pBss->AuthMode = Ndis802_11AuthModeWPANone;
4365 				pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4366 				pBss->WepStatus = pBss->WPA.GroupCipher;
4367 				/* Patched bugs for old driver */
4368 				if (pBss->WPA.PairCipherAux ==
4369 				    Ndis802_11WEPDisabled)
4370 					pBss->WPA.PairCipherAux =
4371 					    pBss->WPA.GroupCipher;
4372 			} else
4373 				pBss->WepStatus = pBss->WPA.PairCipher;
4374 
4375 			/* Check the Pair & Group, if different, turn on mixed mode flag */
4376 			if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4377 				pBss->WPA.bMixMode = TRUE;
4378 
4379 			break;
4380 
4381 		case IE_RSN:
4382 			pRsnHeader = (struct rt_rsn_ie_header *) pTmp;
4383 
4384 			/* 0. Version must be 1 */
4385 			if (le2cpu16(pRsnHeader->Version) != 1)
4386 				break;
4387 			pTmp += sizeof(struct rt_rsn_ie_header);
4388 
4389 			/* 1. Check group cipher */
4390 			pCipher = (struct rt_cipher_suite_struct *) pTmp;
4391 			if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4392 				break;
4393 
4394 			/* Parse group cipher */
4395 			switch (pCipher->Type) {
4396 			case 1:
4397 				pBss->WPA2.GroupCipher =
4398 				    Ndis802_11GroupWEP40Enabled;
4399 				break;
4400 			case 5:
4401 				pBss->WPA2.GroupCipher =
4402 				    Ndis802_11GroupWEP104Enabled;
4403 				break;
4404 			case 2:
4405 				pBss->WPA2.GroupCipher =
4406 				    Ndis802_11Encryption2Enabled;
4407 				break;
4408 			case 4:
4409 				pBss->WPA2.GroupCipher =
4410 				    Ndis802_11Encryption3Enabled;
4411 				break;
4412 			default:
4413 				break;
4414 			}
4415 			/* set to correct offset for next parsing */
4416 			pTmp += sizeof(struct rt_cipher_suite_struct);
4417 
4418 			/* 2. Get pairwise cipher counts */
4419 			/*Count = *(u16 *)pTmp; */
4420 			Count = (pTmp[1] << 8) + pTmp[0];
4421 			pTmp += sizeof(u16);
4422 
4423 			/* 3. Get pairwise cipher */
4424 			/* Parsing all unicast cipher suite */
4425 			while (Count > 0) {
4426 				/* Skip OUI */
4427 				pCipher = (struct rt_cipher_suite_struct *) pTmp;
4428 				TmpCipher = Ndis802_11WEPDisabled;
4429 				switch (pCipher->Type) {
4430 				case 1:
4431 				case 5:	/* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4432 					TmpCipher =
4433 					    Ndis802_11Encryption1Enabled;
4434 					break;
4435 				case 2:
4436 					TmpCipher =
4437 					    Ndis802_11Encryption2Enabled;
4438 					break;
4439 				case 4:
4440 					TmpCipher =
4441 					    Ndis802_11Encryption3Enabled;
4442 					break;
4443 				default:
4444 					break;
4445 				}
4446 				if (TmpCipher > pBss->WPA2.PairCipher) {
4447 					/* Move the lower cipher suite to PairCipherAux */
4448 					pBss->WPA2.PairCipherAux =
4449 					    pBss->WPA2.PairCipher;
4450 					pBss->WPA2.PairCipher = TmpCipher;
4451 				} else {
4452 					pBss->WPA2.PairCipherAux = TmpCipher;
4453 				}
4454 				pTmp += sizeof(struct rt_cipher_suite_struct);
4455 				Count--;
4456 			}
4457 
4458 			/* 4. get AKM suite counts */
4459 			/*Count = *(u16 *)pTmp; */
4460 			Count = (pTmp[1] << 8) + pTmp[0];
4461 			pTmp += sizeof(u16);
4462 
4463 			/* 5. Get AKM ciphers */
4464 			/* Parsing all AKM ciphers */
4465 			while (Count > 0) {
4466 				pAKM = (struct rt_akm_suite *) pTmp;
4467 				if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4468 					break;
4469 
4470 				switch (pAKM->Type) {
4471 				case 1:
4472 					/* Set AP support WPA-enterprise mode */
4473 					if (pBss->AuthMode ==
4474 					    Ndis802_11AuthModeOpen)
4475 						pBss->AuthMode =
4476 						    Ndis802_11AuthModeWPA2;
4477 					else
4478 						pBss->AuthModeAux =
4479 						    Ndis802_11AuthModeWPA2;
4480 					break;
4481 				case 2:
4482 					/* Set AP support WPA-PSK mode */
4483 					if (pBss->AuthMode ==
4484 					    Ndis802_11AuthModeOpen)
4485 						pBss->AuthMode =
4486 						    Ndis802_11AuthModeWPA2PSK;
4487 					else
4488 						pBss->AuthModeAux =
4489 						    Ndis802_11AuthModeWPA2PSK;
4490 					break;
4491 				default:
4492 					if (pBss->AuthMode ==
4493 					    Ndis802_11AuthModeOpen)
4494 						pBss->AuthMode =
4495 						    Ndis802_11AuthModeMax;
4496 					else
4497 						pBss->AuthModeAux =
4498 						    Ndis802_11AuthModeMax;
4499 					break;
4500 				}
4501 				pTmp += (Count * sizeof(struct rt_akm_suite));
4502 				Count--;
4503 			}
4504 
4505 			/* Fixed for WPA-None */
4506 			if (pBss->BssType == BSS_ADHOC) {
4507 				pBss->AuthMode = Ndis802_11AuthModeWPANone;
4508 				pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4509 				pBss->WPA.PairCipherAux =
4510 				    pBss->WPA2.PairCipherAux;
4511 				pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4512 				pBss->WepStatus = pBss->WPA.GroupCipher;
4513 				/* Patched bugs for old driver */
4514 				if (pBss->WPA.PairCipherAux ==
4515 				    Ndis802_11WEPDisabled)
4516 					pBss->WPA.PairCipherAux =
4517 					    pBss->WPA.GroupCipher;
4518 			}
4519 			pBss->WepStatus = pBss->WPA2.PairCipher;
4520 
4521 			/* 6. Get RSN capability */
4522 			/*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */
4523 			pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0];
4524 			pTmp += sizeof(u16);
4525 
4526 			/* Check the Pair & Group, if different, turn on mixed mode flag */
4527 			if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4528 				pBss->WPA2.bMixMode = TRUE;
4529 
4530 			break;
4531 		default:
4532 			break;
4533 		}
4534 		Length -= (pEid->Len + 2);
4535 	}
4536 }
4537 
4538 /* =========================================================================================== */
4539 /* mac_table.c */
4540 /* =========================================================================================== */
4541 
4542 /*! \brief generates a random mac address value for IBSS BSSID
4543  *	\param Addr the bssid location
4544  *	\return none
4545  *	\pre
4546  *	\post
4547  */
MacAddrRandomBssid(struct rt_rtmp_adapter * pAd,u8 * pAddr)4548 void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr)
4549 {
4550 	int i;
4551 
4552 	for (i = 0; i < MAC_ADDR_LEN; i++) {
4553 		pAddr[i] = RandomByte(pAd);
4554 	}
4555 
4556 	pAddr[0] = (pAddr[0] & 0xfe) | 0x02;	/* the first 2 bits must be 01xxxxxxxx */
4557 }
4558 
4559 /*! \brief init the management mac frame header
4560  *	\param p_hdr mac header
4561  *	\param subtype subtype of the frame
4562  *	\param p_ds destination address, don't care if it is a broadcast address
4563  *	\return none
4564  *	\pre the station has the following information in the pAd->StaCfg
4565  *	 - bssid
4566  *	 - station address
4567  *	\post
4568  *	\note this function initializes the following field
4569 
4570 	IRQL = PASSIVE_LEVEL
4571 	IRQL = DISPATCH_LEVEL
4572 
4573  */
MgtMacHeaderInit(struct rt_rtmp_adapter * pAd,struct rt_header_802_11 * pHdr80211,u8 SubType,u8 ToDs,u8 * pDA,u8 * pBssid)4574 void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd,
4575 		      struct rt_header_802_11 * pHdr80211,
4576 		      u8 SubType,
4577 		      u8 ToDs, u8 *pDA, u8 *pBssid)
4578 {
4579 	NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
4580 
4581 	pHdr80211->FC.Type = BTYPE_MGMT;
4582 	pHdr80211->FC.SubType = SubType;
4583 /*      if (SubType == SUBTYPE_ACK)     // sample, no use, it will conflict with ACTION frame sub type */
4584 /*              pHdr80211->FC.Type = BTYPE_CNTL; */
4585 	pHdr80211->FC.ToDs = ToDs;
4586 	COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4587 	COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4588 	COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4589 }
4590 
4591 /* =========================================================================================== */
4592 /* mem_mgmt.c */
4593 /* =========================================================================================== */
4594 
4595 /*!***************************************************************************
4596  * This routine build an outgoing frame, and fill all information specified
4597  * in argument list to the frame body. The actual frame size is the summation
4598  * of all arguments.
4599  * input params:
4600  *		Buffer - pointer to a pre-allocated memory segment
4601  *		args - a list of <int arg_size, arg> pairs.
4602  *		NOTE NOTE NOTE! the last argument must be NULL, otherwise this
4603  *						   function will FAIL!
4604  * return:
4605  *		Size of the buffer
4606  * usage:
4607  *		MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4608 
4609  IRQL = PASSIVE_LEVEL
4610 	IRQL = DISPATCH_LEVEL
4611 
4612  ****************************************************************************/
MakeOutgoingFrame(u8 * Buffer,unsigned long * FrameLen,...)4613 unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...)
4614 {
4615 	u8 *p;
4616 	int leng;
4617 	unsigned long TotLeng;
4618 	va_list Args;
4619 
4620 	/* calculates the total length */
4621 	TotLeng = 0;
4622 	va_start(Args, FrameLen);
4623 	do {
4624 		leng = va_arg(Args, int);
4625 		if (leng == END_OF_ARGS) {
4626 			break;
4627 		}
4628 		p = va_arg(Args, void *);
4629 		NdisMoveMemory(&Buffer[TotLeng], p, leng);
4630 		TotLeng = TotLeng + leng;
4631 	} while (TRUE);
4632 
4633 	va_end(Args);		/* clean up */
4634 	*FrameLen = TotLeng;
4635 	return TotLeng;
4636 }
4637 
4638 /* =========================================================================================== */
4639 /* mlme_queue.c */
4640 /* =========================================================================================== */
4641 
4642 /*! \brief	Initialize The MLME Queue, used by MLME Functions
4643  *	\param	*Queue	   The MLME Queue
4644  *	\return Always	   Return NDIS_STATE_SUCCESS in this implementation
4645  *	\pre
4646  *	\post
4647  *	\note	Because this is done only once (at the init stage), no need to be locked
4648 
4649  IRQL = PASSIVE_LEVEL
4650 
4651  */
MlmeQueueInit(struct rt_mlme_queue * Queue)4652 int MlmeQueueInit(struct rt_mlme_queue *Queue)
4653 {
4654 	int i;
4655 
4656 	NdisAllocateSpinLock(&Queue->Lock);
4657 
4658 	Queue->Num = 0;
4659 	Queue->Head = 0;
4660 	Queue->Tail = 0;
4661 
4662 	for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) {
4663 		Queue->Entry[i].Occupied = FALSE;
4664 		Queue->Entry[i].MsgLen = 0;
4665 		NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4666 	}
4667 
4668 	return NDIS_STATUS_SUCCESS;
4669 }
4670 
4671 /*! \brief	 Enqueue a message for other threads, if they want to send messages to MLME thread
4672  *	\param	*Queue	  The MLME Queue
4673  *	\param	 Machine  The State Machine Id
4674  *	\param	 MsgType  The Message Type
4675  *	\param	 MsgLen   The Message length
4676  *	\param	*Msg	  The message pointer
4677  *	\return  TRUE if enqueue is successful, FALSE if the queue is full
4678  *	\pre
4679  *	\post
4680  *	\note	 The message has to be initialized
4681 
4682 	IRQL = PASSIVE_LEVEL
4683 	IRQL = DISPATCH_LEVEL
4684 
4685  */
MlmeEnqueue(struct rt_rtmp_adapter * pAd,unsigned long Machine,unsigned long MsgType,unsigned long MsgLen,void * Msg)4686 BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd,
4687 		    unsigned long Machine,
4688 		    unsigned long MsgType, unsigned long MsgLen, void * Msg)
4689 {
4690 	int Tail;
4691 	struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
4692 
4693 	/* Do nothing if the driver is starting halt state. */
4694 	/* This might happen when timer already been fired before cancel timer with mlmehalt */
4695 	if (RTMP_TEST_FLAG
4696 	    (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4697 		return FALSE;
4698 
4699 	/* First check the size, it MUST not exceed the mlme queue size */
4700 	if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4701 		DBGPRINT_ERR("MlmeEnqueue: msg too large, size = %ld \n", MsgLen);
4702 		return FALSE;
4703 	}
4704 
4705 	if (MlmeQueueFull(Queue)) {
4706 		return FALSE;
4707 	}
4708 
4709 	NdisAcquireSpinLock(&(Queue->Lock));
4710 	Tail = Queue->Tail;
4711 	Queue->Tail++;
4712 	Queue->Num++;
4713 	if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
4714 		Queue->Tail = 0;
4715 	}
4716 
4717 	Queue->Entry[Tail].Wcid = RESERVED_WCID;
4718 	Queue->Entry[Tail].Occupied = TRUE;
4719 	Queue->Entry[Tail].Machine = Machine;
4720 	Queue->Entry[Tail].MsgType = MsgType;
4721 	Queue->Entry[Tail].MsgLen = MsgLen;
4722 
4723 	if (Msg != NULL) {
4724 		NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4725 	}
4726 
4727 	NdisReleaseSpinLock(&(Queue->Lock));
4728 	return TRUE;
4729 }
4730 
4731 /*! \brief	 This function is used when Recv gets a MLME message
4732  *	\param	*Queue			 The MLME Queue
4733  *	\param	 TimeStampHigh	 The upper 32 bit of timestamp
4734  *	\param	 TimeStampLow	 The lower 32 bit of timestamp
4735  *	\param	 Rssi			 The receiving RSSI strength
4736  *	\param	 MsgLen			 The length of the message
4737  *	\param	*Msg			 The message pointer
4738  *	\return  TRUE if everything ok, FALSE otherwise (like Queue Full)
4739  *	\pre
4740  *	\post
4741 
4742  IRQL = DISPATCH_LEVEL
4743 
4744  */
MlmeEnqueueForRecv(struct rt_rtmp_adapter * pAd,unsigned long Wcid,unsigned long TimeStampHigh,unsigned long TimeStampLow,u8 Rssi0,u8 Rssi1,u8 Rssi2,unsigned long MsgLen,void * Msg,u8 Signal)4745 BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd,
4746 			   unsigned long Wcid,
4747 			   unsigned long TimeStampHigh,
4748 			   unsigned long TimeStampLow,
4749 			   u8 Rssi0,
4750 			   u8 Rssi1,
4751 			   u8 Rssi2,
4752 			   unsigned long MsgLen, void * Msg, u8 Signal)
4753 {
4754 	int Tail, Machine;
4755 	struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg;
4756 	int MsgType;
4757 	struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
4758 
4759 	/* Do nothing if the driver is starting halt state. */
4760 	/* This might happen when timer already been fired before cancel timer with mlmehalt */
4761 	if (RTMP_TEST_FLAG
4762 	    (pAd,
4763 	     fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) {
4764 		DBGPRINT_ERR("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n");
4765 		return FALSE;
4766 	}
4767 	/* First check the size, it MUST not exceed the mlme queue size */
4768 	if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4769 		DBGPRINT_ERR("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen);
4770 		return FALSE;
4771 	}
4772 
4773 	if (MlmeQueueFull(Queue)) {
4774 		return FALSE;
4775 	}
4776 
4777 	{
4778 		if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) {
4779 			DBGPRINT_ERR("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType);
4780 			return FALSE;
4781 		}
4782 	}
4783 
4784 	/* OK, we got all the informations, it is time to put things into queue */
4785 	NdisAcquireSpinLock(&(Queue->Lock));
4786 	Tail = Queue->Tail;
4787 	Queue->Tail++;
4788 	Queue->Num++;
4789 	if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
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 = (u8)Wcid;
4803 
4804 	Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4805 
4806 	if (Msg != NULL) {
4807 		NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4808 	}
4809 
4810 	NdisReleaseSpinLock(&(Queue->Lock));
4811 
4812 	RTMP_MLME_HANDLER(pAd);
4813 
4814 	return TRUE;
4815 }
4816 
4817 /*! \brief	 Dequeue a message from the MLME Queue
4818  *	\param	*Queue	  The MLME Queue
4819  *	\param	*Elem	  The message dequeued from MLME Queue
4820  *	\return  TRUE if the Elem contains something, FALSE otherwise
4821  *	\pre
4822  *	\post
4823 
4824  IRQL = DISPATCH_LEVEL
4825 
4826  */
MlmeDequeue(struct rt_mlme_queue * Queue,struct rt_mlme_queue_elem ** Elem)4827 BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem)
4828 {
4829 	NdisAcquireSpinLock(&(Queue->Lock));
4830 	*Elem = &(Queue->Entry[Queue->Head]);
4831 	Queue->Num--;
4832 	Queue->Head++;
4833 	if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) {
4834 		Queue->Head = 0;
4835 	}
4836 	NdisReleaseSpinLock(&(Queue->Lock));
4837 	return TRUE;
4838 }
4839 
4840 /* IRQL = DISPATCH_LEVEL */
MlmeRestartStateMachine(struct rt_rtmp_adapter * pAd)4841 void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd)
4842 {
4843 #ifdef RTMP_MAC_PCI
4844 	struct rt_mlme_queue_elem *Elem = NULL;
4845 #endif /* RTMP_MAC_PCI // */
4846 	BOOLEAN Cancelled;
4847 
4848 	DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4849 
4850 #ifdef RTMP_MAC_PCI
4851 	NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4852 	if (pAd->Mlme.bRunning) {
4853 		NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4854 		return;
4855 	} else {
4856 		pAd->Mlme.bRunning = TRUE;
4857 	}
4858 	NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4859 
4860 	/* Remove all Mlme queues elements */
4861 	while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
4862 		/*From message type, determine which state machine I should drive */
4863 		if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
4864 			/* free MLME element */
4865 			Elem->Occupied = FALSE;
4866 			Elem->MsgLen = 0;
4867 
4868 		} else {
4869 			DBGPRINT_ERR("MlmeRestartStateMachine: MlmeQueue empty\n");
4870 		}
4871 	}
4872 #endif /* RTMP_MAC_PCI // */
4873 
4874 	{
4875 		/* Cancel all timer events */
4876 		/* Be careful to cancel new added timer */
4877 		RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4878 		RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4879 		RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4880 		RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4881 		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4882 		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4883 
4884 	}
4885 
4886 	/* Change back to original channel in case of doing scan */
4887 	AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4888 	AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4889 
4890 	/* Resume MSDU which is turned off durning scan */
4891 	RTMPResumeMsduTransmission(pAd);
4892 
4893 	{
4894 		/* Set all state machines back IDLE */
4895 		pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4896 		pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4897 		pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4898 		pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4899 		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4900 		pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4901 	}
4902 
4903 #ifdef RTMP_MAC_PCI
4904 	/* Remove running state */
4905 	NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4906 	pAd->Mlme.bRunning = FALSE;
4907 	NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4908 #endif /* RTMP_MAC_PCI // */
4909 }
4910 
4911 /*! \brief	test if the MLME Queue is empty
4912  *	\param	*Queue	  The MLME Queue
4913  *	\return TRUE if the Queue is empty, FALSE otherwise
4914  *	\pre
4915  *	\post
4916 
4917  IRQL = DISPATCH_LEVEL
4918 
4919  */
MlmeQueueEmpty(struct rt_mlme_queue * Queue)4920 BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue)
4921 {
4922 	BOOLEAN Ans;
4923 
4924 	NdisAcquireSpinLock(&(Queue->Lock));
4925 	Ans = (Queue->Num == 0);
4926 	NdisReleaseSpinLock(&(Queue->Lock));
4927 
4928 	return Ans;
4929 }
4930 
4931 /*! \brief	 test if the MLME Queue is full
4932  *	\param	 *Queue		 The MLME Queue
4933  *	\return  TRUE if the Queue is empty, FALSE otherwise
4934  *	\pre
4935  *	\post
4936 
4937  IRQL = PASSIVE_LEVEL
4938  IRQL = DISPATCH_LEVEL
4939 
4940  */
MlmeQueueFull(struct rt_mlme_queue * Queue)4941 BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue)
4942 {
4943 	BOOLEAN Ans;
4944 
4945 	NdisAcquireSpinLock(&(Queue->Lock));
4946 	Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE
4947 	       || Queue->Entry[Queue->Tail].Occupied);
4948 	NdisReleaseSpinLock(&(Queue->Lock));
4949 
4950 	return Ans;
4951 }
4952 
4953 /*! \brief	 The destructor of MLME Queue
4954  *	\param
4955  *	\return
4956  *	\pre
4957  *	\post
4958  *	\note	Clear Mlme Queue, Set Queue->Num to Zero.
4959 
4960  IRQL = PASSIVE_LEVEL
4961 
4962  */
MlmeQueueDestroy(struct rt_mlme_queue * pQueue)4963 void MlmeQueueDestroy(struct rt_mlme_queue *pQueue)
4964 {
4965 	NdisAcquireSpinLock(&(pQueue->Lock));
4966 	pQueue->Num = 0;
4967 	pQueue->Head = 0;
4968 	pQueue->Tail = 0;
4969 	NdisReleaseSpinLock(&(pQueue->Lock));
4970 	NdisFreeSpinLock(&(pQueue->Lock));
4971 }
4972 
4973 /*! \brief	 To substitute the message type if the message is coming from external
4974  *	\param	pFrame		   The frame received
4975  *	\param	*Machine	   The state machine
4976  *	\param	*MsgType	   the message type for the state machine
4977  *	\return TRUE if the substitution is successful, FALSE otherwise
4978  *	\pre
4979  *	\post
4980 
4981  IRQL = DISPATCH_LEVEL
4982 
4983  */
MsgTypeSubst(struct rt_rtmp_adapter * pAd,struct rt_frame_802_11 * pFrame,int * Machine,int * MsgType)4984 BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd,
4985 		     struct rt_frame_802_11 * pFrame,
4986 		     int * Machine, int * MsgType)
4987 {
4988 	u16 Seq, Alg;
4989 	u8 EAPType;
4990 	u8 *pData;
4991 
4992 	/* Pointer to start of data frames including SNAP header */
4993 	pData = (u8 *)pFrame + LENGTH_802_11;
4994 
4995 	/* The only data type will pass to this function is EAPOL frame */
4996 	if (pFrame->Hdr.FC.Type == BTYPE_DATA) {
4997 		{
4998 			*Machine = WPA_STATE_MACHINE;
4999 			EAPType =
5000 			    *((u8 *) pFrame + LENGTH_802_11 +
5001 			      LENGTH_802_1_H + 1);
5002 			return (WpaMsgTypeSubst(EAPType, (int *) MsgType));
5003 		}
5004 	}
5005 
5006 	switch (pFrame->Hdr.FC.SubType) {
5007 	case SUBTYPE_ASSOC_REQ:
5008 		*Machine = ASSOC_STATE_MACHINE;
5009 		*MsgType = MT2_PEER_ASSOC_REQ;
5010 		break;
5011 	case SUBTYPE_ASSOC_RSP:
5012 		*Machine = ASSOC_STATE_MACHINE;
5013 		*MsgType = MT2_PEER_ASSOC_RSP;
5014 		break;
5015 	case SUBTYPE_REASSOC_REQ:
5016 		*Machine = ASSOC_STATE_MACHINE;
5017 		*MsgType = MT2_PEER_REASSOC_REQ;
5018 		break;
5019 	case SUBTYPE_REASSOC_RSP:
5020 		*Machine = ASSOC_STATE_MACHINE;
5021 		*MsgType = MT2_PEER_REASSOC_RSP;
5022 		break;
5023 	case SUBTYPE_PROBE_REQ:
5024 		*Machine = SYNC_STATE_MACHINE;
5025 		*MsgType = MT2_PEER_PROBE_REQ;
5026 		break;
5027 	case SUBTYPE_PROBE_RSP:
5028 		*Machine = SYNC_STATE_MACHINE;
5029 		*MsgType = MT2_PEER_PROBE_RSP;
5030 		break;
5031 	case SUBTYPE_BEACON:
5032 		*Machine = SYNC_STATE_MACHINE;
5033 		*MsgType = MT2_PEER_BEACON;
5034 		break;
5035 	case SUBTYPE_ATIM:
5036 		*Machine = SYNC_STATE_MACHINE;
5037 		*MsgType = MT2_PEER_ATIM;
5038 		break;
5039 	case SUBTYPE_DISASSOC:
5040 		*Machine = ASSOC_STATE_MACHINE;
5041 		*MsgType = MT2_PEER_DISASSOC_REQ;
5042 		break;
5043 	case SUBTYPE_AUTH:
5044 		/* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
5045 		NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16));
5046 		NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16));
5047 		if (Seq == 1 || Seq == 3) {
5048 			*Machine = AUTH_RSP_STATE_MACHINE;
5049 			*MsgType = MT2_PEER_AUTH_ODD;
5050 		} else if (Seq == 2 || Seq == 4) {
5051 			if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) {
5052 				*Machine = AUTH_STATE_MACHINE;
5053 				*MsgType = MT2_PEER_AUTH_EVEN;
5054 			}
5055 		} else {
5056 			return FALSE;
5057 		}
5058 		break;
5059 	case SUBTYPE_DEAUTH:
5060 		*Machine = AUTH_RSP_STATE_MACHINE;
5061 		*MsgType = MT2_PEER_DEAUTH;
5062 		break;
5063 	case SUBTYPE_ACTION:
5064 		*Machine = ACTION_STATE_MACHINE;
5065 		/*  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
5066 		if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) {
5067 			*MsgType = MT2_ACT_INVALID;
5068 		} else {
5069 			*MsgType = (pFrame->Octet[0] & 0x7F);
5070 		}
5071 		break;
5072 	default:
5073 		return FALSE;
5074 		break;
5075 	}
5076 
5077 	return TRUE;
5078 }
5079 
5080 /* =========================================================================================== */
5081 /* state_machine.c */
5082 /* =========================================================================================== */
5083 
5084 /*! \brief Initialize the state machine.
5085  *	\param *S			pointer to the state machine
5086  *	\param	Trans		State machine transition function
5087  *	\param	StNr		number of states
5088  *	\param	MsgNr		number of messages
5089  *	\param	DefFunc		default function, when there is invalid state/message combination
5090  *	\param	InitState	initial state of the state machine
5091  *	\param	Base		StateMachine base, internal use only
5092  *	\pre p_sm should be a legal pointer
5093  *	\post
5094 
5095  IRQL = PASSIVE_LEVEL
5096 
5097  */
StateMachineInit(struct rt_state_machine * S,IN STATE_MACHINE_FUNC Trans[],unsigned long StNr,unsigned long MsgNr,IN STATE_MACHINE_FUNC DefFunc,unsigned long InitState,unsigned long Base)5098 void StateMachineInit(struct rt_state_machine *S,
5099 		      IN STATE_MACHINE_FUNC Trans[],
5100 		      unsigned long StNr,
5101 		      unsigned long MsgNr,
5102 		      IN STATE_MACHINE_FUNC DefFunc,
5103 		      unsigned long InitState, unsigned long Base)
5104 {
5105 	unsigned long i, j;
5106 
5107 	/* set number of states and messages */
5108 	S->NrState = StNr;
5109 	S->NrMsg = MsgNr;
5110 	S->Base = Base;
5111 
5112 	S->TransFunc = Trans;
5113 
5114 	/* init all state transition to default function */
5115 	for (i = 0; i < StNr; i++) {
5116 		for (j = 0; j < MsgNr; j++) {
5117 			S->TransFunc[i * MsgNr + j] = DefFunc;
5118 		}
5119 	}
5120 
5121 	/* set the starting state */
5122 	S->CurrState = InitState;
5123 }
5124 
5125 /*! \brief This function fills in the function pointer into the cell in the state machine
5126  *	\param *S	pointer to the state machine
5127  *	\param St	state
5128  *	\param Msg	incoming message
5129  *	\param f	the function to be executed when (state, message) combination occurs at the state machine
5130  *	\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
5131  *	\post
5132 
5133  IRQL = PASSIVE_LEVEL
5134 
5135  */
StateMachineSetAction(struct rt_state_machine * S,unsigned long St,unsigned long Msg,IN STATE_MACHINE_FUNC Func)5136 void StateMachineSetAction(struct rt_state_machine *S,
5137 			   unsigned long St,
5138 			   unsigned long Msg, IN STATE_MACHINE_FUNC Func)
5139 {
5140 	unsigned long MsgIdx;
5141 
5142 	MsgIdx = Msg - S->Base;
5143 
5144 	if (St < S->NrState && MsgIdx < S->NrMsg) {
5145 		/* boundary checking before setting the action */
5146 		S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5147 	}
5148 }
5149 
5150 /*! \brief	 This function does the state transition
5151  *	\param	 *Adapter the NIC adapter pointer
5152  *	\param	 *S	  the state machine
5153  *	\param	 *Elem	  the message to be executed
5154  *	\return   None
5155 
5156  IRQL = DISPATCH_LEVEL
5157 
5158  */
StateMachinePerformAction(struct rt_rtmp_adapter * pAd,struct rt_state_machine * S,struct rt_mlme_queue_elem * Elem)5159 void StateMachinePerformAction(struct rt_rtmp_adapter *pAd,
5160 			       struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem)
5161 {
5162 	(*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))
5163 	    (pAd, Elem);
5164 }
5165 
5166 /*
5167 	==========================================================================
5168 	Description:
5169 		The drop function, when machine executes this, the message is simply
5170 		ignored. This function does nothing, the message is freed in
5171 		StateMachinePerformAction()
5172 	==========================================================================
5173  */
Drop(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)5174 void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
5175 {
5176 }
5177 
5178 /* =========================================================================================== */
5179 /* lfsr.c */
5180 /* =========================================================================================== */
5181 
5182 /*
5183 	==========================================================================
5184 	Description:
5185 
5186 	IRQL = PASSIVE_LEVEL
5187 
5188 	==========================================================================
5189  */
LfsrInit(struct rt_rtmp_adapter * pAd,unsigned long Seed)5190 void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed)
5191 {
5192 	if (Seed == 0)
5193 		pAd->Mlme.ShiftReg = 1;
5194 	else
5195 		pAd->Mlme.ShiftReg = Seed;
5196 }
5197 
5198 /*
5199 	==========================================================================
5200 	Description:
5201 	==========================================================================
5202  */
RandomByte(struct rt_rtmp_adapter * pAd)5203 u8 RandomByte(struct rt_rtmp_adapter *pAd)
5204 {
5205 	unsigned long i;
5206 	u8 R, Result;
5207 
5208 	R = 0;
5209 
5210 	if (pAd->Mlme.ShiftReg == 0)
5211 		NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg);
5212 
5213 	for (i = 0; i < 8; i++) {
5214 		if (pAd->Mlme.ShiftReg & 0x00000001) {
5215 			pAd->Mlme.ShiftReg =
5216 			    ((pAd->Mlme.
5217 			      ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5218 			Result = 1;
5219 		} else {
5220 			pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5221 			Result = 0;
5222 		}
5223 		R = (R << 1) | Result;
5224 	}
5225 
5226 	return R;
5227 }
5228 
5229 /*
5230 	========================================================================
5231 
5232 	Routine Description:
5233 		Verify the support rate for different PHY type
5234 
5235 	Arguments:
5236 		pAd 				Pointer to our adapter
5237 
5238 	Return Value:
5239 		None
5240 
5241 	IRQL = PASSIVE_LEVEL
5242 
5243 	========================================================================
5244 */
RTMPCheckRates(struct rt_rtmp_adapter * pAd,IN u8 SupRate[],IN u8 * SupRateLen)5245 void RTMPCheckRates(struct rt_rtmp_adapter *pAd,
5246 		    IN u8 SupRate[], IN u8 * SupRateLen)
5247 {
5248 	u8 RateIdx, i, j;
5249 	u8 NewRate[12], NewRateLen;
5250 
5251 	NewRateLen = 0;
5252 
5253 	if (pAd->CommonCfg.PhyMode == PHY_11B)
5254 		RateIdx = 4;
5255 	else
5256 		RateIdx = 12;
5257 
5258 	/* Check for support rates exclude basic rate bit */
5259 	for (i = 0; i < *SupRateLen; i++)
5260 		for (j = 0; j < RateIdx; j++)
5261 			if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5262 				NewRate[NewRateLen++] = SupRate[i];
5263 
5264 	*SupRateLen = NewRateLen;
5265 	NdisMoveMemory(SupRate, NewRate, NewRateLen);
5266 }
5267 
RTMPCheckChannel(struct rt_rtmp_adapter * pAd,u8 CentralChannel,u8 Channel)5268 BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd,
5269 			 u8 CentralChannel, u8 Channel)
5270 {
5271 	u8 k;
5272 	u8 UpperChannel = 0, LowerChannel = 0;
5273 	u8 NoEffectChannelinList = 0;
5274 
5275 	/* Find upper and lower channel according to 40MHz current operation. */
5276 	if (CentralChannel < Channel) {
5277 		UpperChannel = Channel;
5278 		if (CentralChannel > 2)
5279 			LowerChannel = CentralChannel - 2;
5280 		else
5281 			return FALSE;
5282 	} else if (CentralChannel > Channel) {
5283 		UpperChannel = CentralChannel + 2;
5284 		LowerChannel = Channel;
5285 	}
5286 
5287 	for (k = 0; k < pAd->ChannelListNum; k++) {
5288 		if (pAd->ChannelList[k].Channel == UpperChannel) {
5289 			NoEffectChannelinList++;
5290 		}
5291 		if (pAd->ChannelList[k].Channel == LowerChannel) {
5292 			NoEffectChannelinList++;
5293 		}
5294 	}
5295 
5296 	DBGPRINT(RT_DEBUG_TRACE,
5297 		 ("Total Channel in Channel List = [%d]\n",
5298 		  NoEffectChannelinList));
5299 	if (NoEffectChannelinList == 2)
5300 		return TRUE;
5301 	else
5302 		return FALSE;
5303 }
5304 
5305 /*
5306 	========================================================================
5307 
5308 	Routine Description:
5309 		Verify the support rate for HT phy type
5310 
5311 	Arguments:
5312 		pAd 				Pointer to our adapter
5313 
5314 	Return Value:
5315 		FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
5316 
5317 	IRQL = PASSIVE_LEVEL
5318 
5319 	========================================================================
5320 */
RTMPCheckHt(struct rt_rtmp_adapter * pAd,u8 Wcid,struct rt_ht_capability_ie * pHtCapability,struct rt_add_ht_info_ie * pAddHtInfo)5321 BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd,
5322 		    u8 Wcid,
5323 		    struct rt_ht_capability_ie * pHtCapability,
5324 		    struct rt_add_ht_info_ie * pAddHtInfo)
5325 {
5326 	if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5327 		return FALSE;
5328 
5329 	/* If use AMSDU, set flag. */
5330 	if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
5331 		CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5332 				       fCLIENT_STATUS_AMSDU_INUSED);
5333 	/* Save Peer Capability */
5334 	if (pHtCapability->HtCapInfo.ShortGIfor20)
5335 		CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5336 				       fCLIENT_STATUS_SGI20_CAPABLE);
5337 	if (pHtCapability->HtCapInfo.ShortGIfor40)
5338 		CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5339 				       fCLIENT_STATUS_SGI40_CAPABLE);
5340 	if (pHtCapability->HtCapInfo.TxSTBC)
5341 		CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5342 				       fCLIENT_STATUS_TxSTBC_CAPABLE);
5343 	if (pHtCapability->HtCapInfo.RxSTBC)
5344 		CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5345 				       fCLIENT_STATUS_RxSTBC_CAPABLE);
5346 	if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) {
5347 		CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5348 				       fCLIENT_STATUS_RDG_CAPABLE);
5349 	}
5350 
5351 	if (Wcid < MAX_LEN_OF_MAC_TABLE) {
5352 		pAd->MacTab.Content[Wcid].MpduDensity =
5353 		    pHtCapability->HtCapParm.MpduDensity;
5354 	}
5355 	/* Will check ChannelWidth for MCSSet[4] below */
5356 	pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
5357 	switch (pAd->CommonCfg.RxStream) {
5358 	case 1:
5359 		pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5360 		pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5361 		pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5362 		pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5363 		break;
5364 	case 2:
5365 		pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5366 		pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5367 		pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5368 		pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5369 		break;
5370 	case 3:
5371 		pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5372 		pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5373 		pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5374 		pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5375 		break;
5376 	}
5377 
5378 	pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth =
5379 	    pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.
5380 	    ChannelWidth;
5381 
5382 	DBGPRINT(RT_DEBUG_TRACE,
5383 		 ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5384 		  pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth,
5385 		  pAddHtInfo->AddHtInfo.RecomWidth,
5386 		  pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5387 		  pAd->NicConfig2.field.BW40MAvailForA,
5388 		  pAd->NicConfig2.field.BW40MAvailForG,
5389 		  pAd->CommonCfg.PhyMode));
5390 
5391 	pAd->MlmeAux.HtCapability.HtCapInfo.GF =
5392 	    pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF;
5393 
5394 	/* Send Assoc Req with my HT capability. */
5395 	pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =
5396 	    pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5397 	pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =
5398 	    pAd->CommonCfg.DesiredHtPhy.MimoPs;
5399 	pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =
5400 	    (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->
5401 							  HtCapInfo.
5402 							  ShortGIfor20);
5403 	pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =
5404 	    (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->
5405 							  HtCapInfo.
5406 							  ShortGIfor40);
5407 	pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =
5408 	    (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo.
5409 						    RxSTBC);
5410 	pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =
5411 	    (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo.
5412 						    TxSTBC);
5413 	pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor =
5414 	    pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5415 	pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity =
5416 	    pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5417 	pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC =
5418 	    pHtCapability->ExtHtCapInfo.PlusHTC;
5419 	pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC =
5420 	    pHtCapability->ExtHtCapInfo.PlusHTC;
5421 	if (pAd->CommonCfg.bRdg) {
5422 		pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport =
5423 		    pHtCapability->ExtHtCapInfo.RDGSupport;
5424 		pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5425 	}
5426 
5427 	if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
5428 		pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;	/* BW20 can't transmit MCS32 */
5429 
5430 	COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5431 	return TRUE;
5432 }
5433 
5434 /*
5435 	========================================================================
5436 
5437 	Routine Description:
5438 		Verify the support rate for different PHY type
5439 
5440 	Arguments:
5441 		pAd 				Pointer to our adapter
5442 
5443 	Return Value:
5444 		None
5445 
5446 	IRQL = PASSIVE_LEVEL
5447 
5448 	========================================================================
5449 */
RTMPUpdateMlmeRate(struct rt_rtmp_adapter * pAd)5450 void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd)
5451 {
5452 	u8 MinimumRate;
5453 	u8 ProperMlmeRate;	/*= RATE_54; */
5454 	u8 i, j, RateIdx = 12;	/*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
5455 	BOOLEAN bMatch = FALSE;
5456 
5457 	switch (pAd->CommonCfg.PhyMode) {
5458 	case PHY_11B:
5459 		ProperMlmeRate = RATE_11;
5460 		MinimumRate = RATE_1;
5461 		break;
5462 	case PHY_11BG_MIXED:
5463 	case PHY_11ABGN_MIXED:
5464 	case PHY_11BGN_MIXED:
5465 		if ((pAd->MlmeAux.SupRateLen == 4) &&
5466 		    (pAd->MlmeAux.ExtRateLen == 0))
5467 			/* B only AP */
5468 			ProperMlmeRate = RATE_11;
5469 		else
5470 			ProperMlmeRate = RATE_24;
5471 
5472 		if (pAd->MlmeAux.Channel <= 14)
5473 			MinimumRate = RATE_1;
5474 		else
5475 			MinimumRate = RATE_6;
5476 		break;
5477 	case PHY_11A:
5478 	case PHY_11N_2_4G:	/* rt2860 need to check mlmerate for 802.11n */
5479 	case PHY_11GN_MIXED:
5480 	case PHY_11AGN_MIXED:
5481 	case PHY_11AN_MIXED:
5482 	case PHY_11N_5G:
5483 		ProperMlmeRate = RATE_24;
5484 		MinimumRate = RATE_6;
5485 		break;
5486 	case PHY_11ABG_MIXED:
5487 		ProperMlmeRate = RATE_24;
5488 		if (pAd->MlmeAux.Channel <= 14)
5489 			MinimumRate = RATE_1;
5490 		else
5491 			MinimumRate = RATE_6;
5492 		break;
5493 	default:		/* error */
5494 		ProperMlmeRate = RATE_1;
5495 		MinimumRate = RATE_1;
5496 		break;
5497 	}
5498 
5499 	for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) {
5500 		for (j = 0; j < RateIdx; j++) {
5501 			if ((pAd->MlmeAux.SupRate[i] & 0x7f) ==
5502 			    RateIdTo500Kbps[j]) {
5503 				if (j == ProperMlmeRate) {
5504 					bMatch = TRUE;
5505 					break;
5506 				}
5507 			}
5508 		}
5509 
5510 		if (bMatch)
5511 			break;
5512 	}
5513 
5514 	if (bMatch == FALSE) {
5515 		for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) {
5516 			for (j = 0; j < RateIdx; j++) {
5517 				if ((pAd->MlmeAux.ExtRate[i] & 0x7f) ==
5518 				    RateIdTo500Kbps[j]) {
5519 					if (j == ProperMlmeRate) {
5520 						bMatch = TRUE;
5521 						break;
5522 					}
5523 				}
5524 			}
5525 
5526 			if (bMatch)
5527 				break;
5528 		}
5529 	}
5530 
5531 	if (bMatch == FALSE) {
5532 		ProperMlmeRate = MinimumRate;
5533 	}
5534 
5535 	pAd->CommonCfg.MlmeRate = MinimumRate;
5536 	pAd->CommonCfg.RtsRate = ProperMlmeRate;
5537 	if (pAd->CommonCfg.MlmeRate >= RATE_6) {
5538 		pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
5539 		pAd->CommonCfg.MlmeTransmit.field.MCS =
5540 		    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5541 		pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5542 		    MODE_OFDM;
5543 		pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5544 		    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5545 	} else {
5546 		pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5547 		pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
5548 		pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5549 		    MODE_CCK;
5550 		pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5551 		    pAd->CommonCfg.MlmeRate;
5552 	}
5553 
5554 	DBGPRINT(RT_DEBUG_TRACE,
5555 		 ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n",
5556 		  pAd->CommonCfg.MlmeTransmit.word));
5557 }
5558 
RTMPMaxRssi(struct rt_rtmp_adapter * pAd,char Rssi0,char Rssi1,char Rssi2)5559 char RTMPMaxRssi(struct rt_rtmp_adapter *pAd,
5560 		 char Rssi0, char Rssi1, char Rssi2)
5561 {
5562 	char larger = -127;
5563 
5564 	if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) {
5565 		larger = Rssi0;
5566 	}
5567 
5568 	if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) {
5569 		larger = max(Rssi0, Rssi1);
5570 	}
5571 
5572 	if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) {
5573 		larger = max(larger, Rssi2);
5574 	}
5575 
5576 	if (larger == -127)
5577 		larger = 0;
5578 
5579 	return larger;
5580 }
5581 
5582 /*
5583     ========================================================================
5584     Routine Description:
5585         Periodic evaluate antenna link status
5586 
5587     Arguments:
5588         pAd         - Adapter pointer
5589 
5590     Return Value:
5591         None
5592 
5593     ========================================================================
5594 */
AsicEvaluateRxAnt(struct rt_rtmp_adapter * pAd)5595 void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd)
5596 {
5597 	u8 BBPR3 = 0;
5598 
5599 	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5600 			   fRTMP_ADAPTER_HALT_IN_PROGRESS |
5601 			   fRTMP_ADAPTER_RADIO_OFF |
5602 			   fRTMP_ADAPTER_NIC_NOT_EXIST |
5603 			   fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5604 	    OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5605 #ifdef RT30xx
5606 	    || (pAd->EepromAccess)
5607 #endif /* RT30xx // */
5608 #ifdef RT3090
5609 	    || (pAd->bPCIclkOff == TRUE)
5610 #endif /* RT3090 // */
5611 	    )
5612 		return;
5613 
5614 	{
5615 		/*if (pAd->StaCfg.Psm == PWR_SAVE) */
5616 		/*      return; */
5617 
5618 		{
5619 
5620 			if (pAd->StaCfg.Psm == PWR_SAVE)
5621 				return;
5622 
5623 			RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5624 			BBPR3 &= (~0x18);
5625 			if (pAd->Antenna.field.RxPath == 3) {
5626 				BBPR3 |= (0x10);
5627 			} else if (pAd->Antenna.field.RxPath == 2) {
5628 				BBPR3 |= (0x8);
5629 			} else if (pAd->Antenna.field.RxPath == 1) {
5630 				BBPR3 |= (0x0);
5631 			}
5632 			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5633 #ifdef RTMP_MAC_PCI
5634 			pAd->StaCfg.BBPR3 = BBPR3;
5635 #endif /* RTMP_MAC_PCI // */
5636 			if (OPSTATUS_TEST_FLAG
5637 			    (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5638 			    ) {
5639 				unsigned long TxTotalCnt =
5640 				    pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5641 				    pAd->RalinkCounters.OneSecTxRetryOkCount +
5642 				    pAd->RalinkCounters.OneSecTxFailCount;
5643 
5644 				/* dynamic adjust antenna evaluation period according to the traffic */
5645 				if (TxTotalCnt > 50) {
5646 					RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5647 						     20);
5648 					pAd->Mlme.bLowThroughput = FALSE;
5649 				} else {
5650 					RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5651 						     300);
5652 					pAd->Mlme.bLowThroughput = TRUE;
5653 				}
5654 			}
5655 		}
5656 
5657 	}
5658 
5659 }
5660 
5661 /*
5662     ========================================================================
5663     Routine Description:
5664         After evaluation, check antenna link status
5665 
5666     Arguments:
5667         pAd         - Adapter pointer
5668 
5669     Return Value:
5670         None
5671 
5672     ========================================================================
5673 */
AsicRxAntEvalTimeout(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)5674 void AsicRxAntEvalTimeout(void *SystemSpecific1,
5675 			  void *FunctionContext,
5676 			  void *SystemSpecific2, void *SystemSpecific3)
5677 {
5678 	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
5679 	u8 BBPR3 = 0;
5680 	char larger = -127, rssi0, rssi1, rssi2;
5681 
5682 	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5683 			   fRTMP_ADAPTER_HALT_IN_PROGRESS |
5684 			   fRTMP_ADAPTER_RADIO_OFF |
5685 			   fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5686 	    OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5687 #ifdef RT30xx
5688 	    || (pAd->EepromAccess)
5689 #endif /* RT30xx // */
5690 #ifdef RT3090
5691 	    || (pAd->bPCIclkOff == TRUE)
5692 #endif /* RT3090 // */
5693 	    )
5694 		return;
5695 
5696 	{
5697 		/*if (pAd->StaCfg.Psm == PWR_SAVE) */
5698 		/*      return; */
5699 		{
5700 			if (pAd->StaCfg.Psm == PWR_SAVE)
5701 				return;
5702 
5703 			/* if the traffic is low, use average rssi as the criteria */
5704 			if (pAd->Mlme.bLowThroughput == TRUE) {
5705 				rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5706 				rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5707 				rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
5708 			} else {
5709 				rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5710 				rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5711 				rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5712 			}
5713 
5714 			if (pAd->Antenna.field.RxPath == 3) {
5715 				larger = max(rssi0, rssi1);
5716 
5717 				if (larger > (rssi2 + 20))
5718 					pAd->Mlme.RealRxPath = 2;
5719 				else
5720 					pAd->Mlme.RealRxPath = 3;
5721 			} else if (pAd->Antenna.field.RxPath == 2) {
5722 				if (rssi0 > (rssi1 + 20))
5723 					pAd->Mlme.RealRxPath = 1;
5724 				else
5725 					pAd->Mlme.RealRxPath = 2;
5726 			}
5727 
5728 			RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5729 			BBPR3 &= (~0x18);
5730 			if (pAd->Mlme.RealRxPath == 3) {
5731 				BBPR3 |= (0x10);
5732 			} else if (pAd->Mlme.RealRxPath == 2) {
5733 				BBPR3 |= (0x8);
5734 			} else if (pAd->Mlme.RealRxPath == 1) {
5735 				BBPR3 |= (0x0);
5736 			}
5737 			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5738 #ifdef RTMP_MAC_PCI
5739 			pAd->StaCfg.BBPR3 = BBPR3;
5740 #endif /* RTMP_MAC_PCI // */
5741 		}
5742 	}
5743 
5744 }
5745 
APSDPeriodicExec(void * SystemSpecific1,void * FunctionContext,void * SystemSpecific2,void * SystemSpecific3)5746 void APSDPeriodicExec(void *SystemSpecific1,
5747 		      void *FunctionContext,
5748 		      void *SystemSpecific2, void *SystemSpecific3)
5749 {
5750 	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
5751 
5752 	if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5753 		return;
5754 
5755 	pAd->CommonCfg.TriggerTimerCount++;
5756 
5757 /* Driver should not send trigger frame, it should be send by application layer */
5758 /*
5759 	if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5760 		&& (pAd->CommonCfg.bNeedSendTriggerFrame ||
5761 		(((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5762 	{
5763 		DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5764 		RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5765 		pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5766 		pAd->CommonCfg.TriggerTimerCount = 0;
5767 		pAd->CommonCfg.bInServicePeriod = TRUE;
5768 	}*/
5769 }
5770 
5771 /*
5772     ========================================================================
5773     Routine Description:
5774         Set/reset MAC registers according to bPiggyBack parameter
5775 
5776     Arguments:
5777         pAd         - Adapter pointer
5778         bPiggyBack  - Enable / Disable Piggy-Back
5779 
5780     Return Value:
5781         None
5782 
5783     ========================================================================
5784 */
RTMPSetPiggyBack(struct rt_rtmp_adapter * pAd,IN BOOLEAN bPiggyBack)5785 void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack)
5786 {
5787 	TX_LINK_CFG_STRUC TxLinkCfg;
5788 
5789 	RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5790 
5791 	TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5792 	RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5793 }
5794 
5795 /*
5796     ========================================================================
5797     Routine Description:
5798         check if this entry need to switch rate automatically
5799 
5800     Arguments:
5801         pAd
5802         pEntry
5803 
5804     Return Value:
5805         TURE
5806         FALSE
5807 
5808     ========================================================================
5809 */
RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter * pAd,struct rt_mac_table_entry * pEntry)5810 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd,
5811 					   struct rt_mac_table_entry *pEntry)
5812 {
5813 	BOOLEAN result = TRUE;
5814 
5815 	{
5816 		/* only associated STA counts */
5817 		if (pEntry && (pEntry->ValidAsCLI)
5818 		    && (pEntry->Sst == SST_ASSOC)) {
5819 			result = pAd->StaCfg.bAutoTxRateSwitch;
5820 		} else
5821 			result = FALSE;
5822 	}
5823 
5824 	return result;
5825 }
5826 
RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter * pAd)5827 BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd)
5828 {
5829 	{
5830 		if (pAd->StaCfg.bAutoTxRateSwitch)
5831 			return TRUE;
5832 	}
5833 	return FALSE;
5834 }
5835 
5836 /*
5837     ========================================================================
5838     Routine Description:
5839         check if this entry need to fix tx legacy rate
5840 
5841     Arguments:
5842         pAd
5843         pEntry
5844 
5845     Return Value:
5846         TURE
5847         FALSE
5848 
5849     ========================================================================
5850 */
RTMPStaFixedTxMode(struct rt_rtmp_adapter * pAd,struct rt_mac_table_entry * pEntry)5851 u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
5852 {
5853 	u8 tx_mode = FIXED_TXMODE_HT;
5854 
5855 	{
5856 		tx_mode =
5857 		    (u8)pAd->StaCfg.DesiredTransmitSetting.field.
5858 		    FixedTxMode;
5859 	}
5860 
5861 	return tx_mode;
5862 }
5863 
5864 /*
5865     ========================================================================
5866     Routine Description:
5867         Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5868 
5869     Arguments:
5870         pAd
5871         pEntry
5872 
5873     Return Value:
5874         TURE
5875         FALSE
5876 
5877     ========================================================================
5878 */
RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode,struct rt_mac_table_entry * pEntry)5879 void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry)
5880 {
5881 	HTTRANSMIT_SETTING TransmitSetting;
5882 
5883 	if (fixed_tx_mode == FIXED_TXMODE_HT)
5884 		return;
5885 
5886 	TransmitSetting.word = 0;
5887 
5888 	TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5889 	TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5890 
5891 	if (fixed_tx_mode == FIXED_TXMODE_CCK) {
5892 		TransmitSetting.field.MODE = MODE_CCK;
5893 		/* CCK mode allow MCS 0~3 */
5894 		if (TransmitSetting.field.MCS > MCS_3)
5895 			TransmitSetting.field.MCS = MCS_3;
5896 	} else {
5897 		TransmitSetting.field.MODE = MODE_OFDM;
5898 		/* OFDM mode allow MCS 0~7 */
5899 		if (TransmitSetting.field.MCS > MCS_7)
5900 			TransmitSetting.field.MCS = MCS_7;
5901 	}
5902 
5903 	if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) {
5904 		pEntry->HTPhyMode.word = TransmitSetting.word;
5905 		DBGPRINT(RT_DEBUG_TRACE,
5906 			 ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5907 			  pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE),
5908 			  pEntry->HTPhyMode.field.MCS));
5909 	}
5910 }
5911 
5912 /*
5913 	==========================================================================
5914 	Description:
5915 		dynamic tune BBP R66 to find a balance between sensibility and
5916 		noise isolation
5917 
5918 	IRQL = DISPATCH_LEVEL
5919 
5920 	==========================================================================
5921  */
AsicStaBbpTuning(struct rt_rtmp_adapter * pAd)5922 void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd)
5923 {
5924 	u8 OrigR66Value = 0, R66;	/*, R66UpperBound = 0x30, R66LowerBound = 0x30; */
5925 	char Rssi;
5926 
5927 	/* 2860C did not support Fase CCA, therefore can't tune */
5928 	if (pAd->MACVersion == 0x28600100)
5929 		return;
5930 
5931 	/* */
5932 	/* work as a STA */
5933 	/* */
5934 	if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)	/* no R66 tuning when SCANNING */
5935 		return;
5936 
5937 	if ((pAd->OpMode == OPMODE_STA)
5938 	    && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5939 	    )
5940 	    && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
5941 #ifdef RTMP_MAC_PCI
5942 	    && (pAd->bPCIclkOff == FALSE)
5943 #endif /* RTMP_MAC_PCI // */
5944 	    ) {
5945 		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5946 		R66 = OrigR66Value;
5947 
5948 		if (pAd->Antenna.field.RxPath > 1)
5949 			Rssi =
5950 			    (pAd->StaCfg.RssiSample.AvgRssi0 +
5951 			     pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
5952 		else
5953 			Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5954 
5955 		if (pAd->LatchRfRegs.Channel <= 14) {	/*BG band */
5956 #ifdef RT30xx
5957 			/* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */
5958 			/* Otherwise, it will have some throughput side effect when low RSSI */
5959 
5960 			if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
5961 			    || IS_RT3390(pAd)) {
5962 				if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5963 					R66 =
5964 					    0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20;
5965 					if (OrigR66Value != R66) {
5966 						RTMP_BBP_IO_WRITE8_BY_REG_ID
5967 						    (pAd, BBP_R66, R66);
5968 					}
5969 				} else {
5970 					R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
5971 					if (OrigR66Value != R66) {
5972 						RTMP_BBP_IO_WRITE8_BY_REG_ID
5973 						    (pAd, BBP_R66, R66);
5974 					}
5975 				}
5976 			} else
5977 #endif /* RT30xx // */
5978 			{
5979 				if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5980 					R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
5981 					if (OrigR66Value != R66) {
5982 						RTMP_BBP_IO_WRITE8_BY_REG_ID
5983 						    (pAd, BBP_R66, R66);
5984 					}
5985 				} else {
5986 					R66 = 0x2E + GET_LNA_GAIN(pAd);
5987 					if (OrigR66Value != R66) {
5988 						RTMP_BBP_IO_WRITE8_BY_REG_ID
5989 						    (pAd, BBP_R66, R66);
5990 					}
5991 				}
5992 			}
5993 		} else {	/*A band */
5994 			if (pAd->CommonCfg.BBPCurrentBW == BW_20) {
5995 				if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5996 					R66 =
5997 					    0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 +
5998 					    0x10;
5999 					if (OrigR66Value != R66) {
6000 						RTMP_BBP_IO_WRITE8_BY_REG_ID
6001 						    (pAd, BBP_R66, R66);
6002 					}
6003 				} else {
6004 					R66 =
6005 					    0x32 + (GET_LNA_GAIN(pAd) * 5) / 3;
6006 					if (OrigR66Value != R66) {
6007 						RTMP_BBP_IO_WRITE8_BY_REG_ID
6008 						    (pAd, BBP_R66, R66);
6009 					}
6010 				}
6011 			} else {
6012 				if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6013 					R66 =
6014 					    0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 +
6015 					    0x10;
6016 					if (OrigR66Value != R66) {
6017 						RTMP_BBP_IO_WRITE8_BY_REG_ID
6018 						    (pAd, BBP_R66, R66);
6019 					}
6020 				} else {
6021 					R66 =
6022 					    0x3A + (GET_LNA_GAIN(pAd) * 5) / 3;
6023 					if (OrigR66Value != R66) {
6024 						RTMP_BBP_IO_WRITE8_BY_REG_ID
6025 						    (pAd, BBP_R66, R66);
6026 					}
6027 				}
6028 			}
6029 		}
6030 
6031 	}
6032 }
6033 
RTMPSetAGCInitValue(struct rt_rtmp_adapter * pAd,u8 BandWidth)6034 void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth)
6035 {
6036 	u8 R66 = 0x30;
6037 
6038 	if (pAd->LatchRfRegs.Channel <= 14) {	/* BG band */
6039 #ifdef RT30xx
6040 		/* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6041 
6042 		if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
6043 		    || IS_RT3390(pAd)) {
6044 			R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
6045 			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6046 		} else
6047 #endif /* RT30xx // */
6048 		{
6049 			R66 = 0x2E + GET_LNA_GAIN(pAd);
6050 			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6051 		}
6052 	} else {		/*A band */
6053 		{
6054 			if (BandWidth == BW_20) {
6055 				R66 =
6056 				    (u8)(0x32 +
6057 					     (GET_LNA_GAIN(pAd) * 5) / 3);
6058 				RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6059 			} else {
6060 				R66 =
6061 				    (u8)(0x3A +
6062 					     (GET_LNA_GAIN(pAd) * 5) / 3);
6063 				RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6064 			}
6065 		}
6066 	}
6067 
6068 }
6069