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 	cmm_sync.c
29 
30 	Abstract:
31 
32 	Revision History:
33 	Who			When			What
34 	--------	----------		----------------------------------------------
35 	John Chang	2004-09-01      modified for rt2561/2661
36 */
37 #include "../rt_config.h"
38 
39 /* 2.4 Ghz channel plan index in the TxPower arrays. */
40 #define	BG_BAND_REGION_0_START	0	/* 1,2,3,4,5,6,7,8,9,10,11 */
41 #define	BG_BAND_REGION_0_SIZE	11
42 #define	BG_BAND_REGION_1_START	0	/* 1,2,3,4,5,6,7,8,9,10,11,12,13 */
43 #define	BG_BAND_REGION_1_SIZE	13
44 #define	BG_BAND_REGION_2_START	9	/* 10,11 */
45 #define	BG_BAND_REGION_2_SIZE	2
46 #define	BG_BAND_REGION_3_START	9	/* 10,11,12,13 */
47 #define	BG_BAND_REGION_3_SIZE	4
48 #define	BG_BAND_REGION_4_START	13	/* 14 */
49 #define	BG_BAND_REGION_4_SIZE	1
50 #define	BG_BAND_REGION_5_START	0	/* 1,2,3,4,5,6,7,8,9,10,11,12,13,14 */
51 #define	BG_BAND_REGION_5_SIZE	14
52 #define	BG_BAND_REGION_6_START	2	/* 3,4,5,6,7,8,9 */
53 #define	BG_BAND_REGION_6_SIZE	7
54 #define	BG_BAND_REGION_7_START	4	/* 5,6,7,8,9,10,11,12,13 */
55 #define	BG_BAND_REGION_7_SIZE	9
56 #define	BG_BAND_REGION_31_START	0	/* 1,2,3,4,5,6,7,8,9,10,11,12,13,14 */
57 #define	BG_BAND_REGION_31_SIZE	14
58 
59 /* 5 Ghz channel plan index in the TxPower arrays. */
60 u8 A_BAND_REGION_0_CHANNEL_LIST[] =
61     { 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 };
62 u8 A_BAND_REGION_1_CHANNEL_LIST[] =
63     { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128,
64 132, 136, 140 };
65 u8 A_BAND_REGION_2_CHANNEL_LIST[] = { 36, 40, 44, 48, 52, 56, 60, 64 };
66 u8 A_BAND_REGION_3_CHANNEL_LIST[] = { 52, 56, 60, 64, 149, 153, 157, 161 };
67 u8 A_BAND_REGION_4_CHANNEL_LIST[] = { 149, 153, 157, 161, 165 };
68 u8 A_BAND_REGION_5_CHANNEL_LIST[] = { 149, 153, 157, 161 };
69 u8 A_BAND_REGION_6_CHANNEL_LIST[] = { 36, 40, 44, 48 };
70 u8 A_BAND_REGION_7_CHANNEL_LIST[] =
71     { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128,
72 132, 136, 140, 149, 153, 157, 161, 165, 169, 173 };
73 u8 A_BAND_REGION_8_CHANNEL_LIST[] = { 52, 56, 60, 64 };
74 u8 A_BAND_REGION_9_CHANNEL_LIST[] =
75     { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140,
76 149, 153, 157, 161, 165 };
77 u8 A_BAND_REGION_10_CHANNEL_LIST[] =
78     { 36, 40, 44, 48, 149, 153, 157, 161, 165 };
79 u8 A_BAND_REGION_11_CHANNEL_LIST[] =
80     { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153,
81 157, 161 };
82 u8 A_BAND_REGION_12_CHANNEL_LIST[] =
83     { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128,
84 132, 136, 140 };
85 u8 A_BAND_REGION_13_CHANNEL_LIST[] =
86     { 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
87 149, 153, 157, 161 };
88 u8 A_BAND_REGION_14_CHANNEL_LIST[] =
89     { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
90 153, 157, 161, 165 };
91 u8 A_BAND_REGION_15_CHANNEL_LIST[] = { 149, 153, 157, 161, 165, 169, 173 };
92 
93 /*BaSizeArray follows the 802.11n definition as MaxRxFactor.  2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8. */
94 u8 BaSizeArray[4] = { 8, 16, 32, 64 };
95 
96 /*
97 	==========================================================================
98 	Description:
99 		Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type,
100 		and 3) PHY-mode user selected.
101 		The outcome is used by driver when doing site survey.
102 
103 	IRQL = PASSIVE_LEVEL
104 	IRQL = DISPATCH_LEVEL
105 
106 	==========================================================================
107  */
BuildChannelList(struct rt_rtmp_adapter * pAd)108 void BuildChannelList(struct rt_rtmp_adapter *pAd)
109 {
110 	u8 i, j, index = 0, num = 0;
111 	u8 *pChannelList = NULL;
112 
113 	NdisZeroMemory(pAd->ChannelList,
114 		       MAX_NUM_OF_CHANNELS * sizeof(struct rt_channel_tx_power));
115 
116 	/* if not 11a-only mode, channel list starts from 2.4Ghz band */
117 	if ((pAd->CommonCfg.PhyMode != PHY_11A)
118 	    && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED)
119 	    && (pAd->CommonCfg.PhyMode != PHY_11N_5G)
120 	    ) {
121 		switch (pAd->CommonCfg.CountryRegion & 0x7f) {
122 		case REGION_0_BG_BAND:	/* 1 -11 */
123 			NdisMoveMemory(&pAd->ChannelList[index],
124 				       &pAd->TxPower[BG_BAND_REGION_0_START],
125 				       sizeof(struct rt_channel_tx_power) *
126 				       BG_BAND_REGION_0_SIZE);
127 			index += BG_BAND_REGION_0_SIZE;
128 			break;
129 		case REGION_1_BG_BAND:	/* 1 - 13 */
130 			NdisMoveMemory(&pAd->ChannelList[index],
131 				       &pAd->TxPower[BG_BAND_REGION_1_START],
132 				       sizeof(struct rt_channel_tx_power) *
133 				       BG_BAND_REGION_1_SIZE);
134 			index += BG_BAND_REGION_1_SIZE;
135 			break;
136 		case REGION_2_BG_BAND:	/* 10 - 11 */
137 			NdisMoveMemory(&pAd->ChannelList[index],
138 				       &pAd->TxPower[BG_BAND_REGION_2_START],
139 				       sizeof(struct rt_channel_tx_power) *
140 				       BG_BAND_REGION_2_SIZE);
141 			index += BG_BAND_REGION_2_SIZE;
142 			break;
143 		case REGION_3_BG_BAND:	/* 10 - 13 */
144 			NdisMoveMemory(&pAd->ChannelList[index],
145 				       &pAd->TxPower[BG_BAND_REGION_3_START],
146 				       sizeof(struct rt_channel_tx_power) *
147 				       BG_BAND_REGION_3_SIZE);
148 			index += BG_BAND_REGION_3_SIZE;
149 			break;
150 		case REGION_4_BG_BAND:	/* 14 */
151 			NdisMoveMemory(&pAd->ChannelList[index],
152 				       &pAd->TxPower[BG_BAND_REGION_4_START],
153 				       sizeof(struct rt_channel_tx_power) *
154 				       BG_BAND_REGION_4_SIZE);
155 			index += BG_BAND_REGION_4_SIZE;
156 			break;
157 		case REGION_5_BG_BAND:	/* 1 - 14 */
158 			NdisMoveMemory(&pAd->ChannelList[index],
159 				       &pAd->TxPower[BG_BAND_REGION_5_START],
160 				       sizeof(struct rt_channel_tx_power) *
161 				       BG_BAND_REGION_5_SIZE);
162 			index += BG_BAND_REGION_5_SIZE;
163 			break;
164 		case REGION_6_BG_BAND:	/* 3 - 9 */
165 			NdisMoveMemory(&pAd->ChannelList[index],
166 				       &pAd->TxPower[BG_BAND_REGION_6_START],
167 				       sizeof(struct rt_channel_tx_power) *
168 				       BG_BAND_REGION_6_SIZE);
169 			index += BG_BAND_REGION_6_SIZE;
170 			break;
171 		case REGION_7_BG_BAND:	/* 5 - 13 */
172 			NdisMoveMemory(&pAd->ChannelList[index],
173 				       &pAd->TxPower[BG_BAND_REGION_7_START],
174 				       sizeof(struct rt_channel_tx_power) *
175 				       BG_BAND_REGION_7_SIZE);
176 			index += BG_BAND_REGION_7_SIZE;
177 			break;
178 		case REGION_31_BG_BAND:	/* 1 - 14 */
179 			NdisMoveMemory(&pAd->ChannelList[index],
180 				       &pAd->TxPower[BG_BAND_REGION_31_START],
181 				       sizeof(struct rt_channel_tx_power) *
182 				       BG_BAND_REGION_31_SIZE);
183 			index += BG_BAND_REGION_31_SIZE;
184 			break;
185 		default:	/* Error. should never happen */
186 			break;
187 		}
188 		for (i = 0; i < index; i++)
189 			pAd->ChannelList[i].MaxTxPwr = 20;
190 	}
191 
192 	if ((pAd->CommonCfg.PhyMode == PHY_11A)
193 	    || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED)
194 	    || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED)
195 	    || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED)
196 	    || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED)
197 	    || (pAd->CommonCfg.PhyMode == PHY_11N_5G)
198 	    ) {
199 		switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) {
200 		case REGION_0_A_BAND:
201 			num =
202 			    sizeof(A_BAND_REGION_0_CHANNEL_LIST) /
203 			    sizeof(u8);
204 			pChannelList = A_BAND_REGION_0_CHANNEL_LIST;
205 			break;
206 		case REGION_1_A_BAND:
207 			num =
208 			    sizeof(A_BAND_REGION_1_CHANNEL_LIST) /
209 			    sizeof(u8);
210 			pChannelList = A_BAND_REGION_1_CHANNEL_LIST;
211 			break;
212 		case REGION_2_A_BAND:
213 			num =
214 			    sizeof(A_BAND_REGION_2_CHANNEL_LIST) /
215 			    sizeof(u8);
216 			pChannelList = A_BAND_REGION_2_CHANNEL_LIST;
217 			break;
218 		case REGION_3_A_BAND:
219 			num =
220 			    sizeof(A_BAND_REGION_3_CHANNEL_LIST) /
221 			    sizeof(u8);
222 			pChannelList = A_BAND_REGION_3_CHANNEL_LIST;
223 			break;
224 		case REGION_4_A_BAND:
225 			num =
226 			    sizeof(A_BAND_REGION_4_CHANNEL_LIST) /
227 			    sizeof(u8);
228 			pChannelList = A_BAND_REGION_4_CHANNEL_LIST;
229 			break;
230 		case REGION_5_A_BAND:
231 			num =
232 			    sizeof(A_BAND_REGION_5_CHANNEL_LIST) /
233 			    sizeof(u8);
234 			pChannelList = A_BAND_REGION_5_CHANNEL_LIST;
235 			break;
236 		case REGION_6_A_BAND:
237 			num =
238 			    sizeof(A_BAND_REGION_6_CHANNEL_LIST) /
239 			    sizeof(u8);
240 			pChannelList = A_BAND_REGION_6_CHANNEL_LIST;
241 			break;
242 		case REGION_7_A_BAND:
243 			num =
244 			    sizeof(A_BAND_REGION_7_CHANNEL_LIST) /
245 			    sizeof(u8);
246 			pChannelList = A_BAND_REGION_7_CHANNEL_LIST;
247 			break;
248 		case REGION_8_A_BAND:
249 			num =
250 			    sizeof(A_BAND_REGION_8_CHANNEL_LIST) /
251 			    sizeof(u8);
252 			pChannelList = A_BAND_REGION_8_CHANNEL_LIST;
253 			break;
254 		case REGION_9_A_BAND:
255 			num =
256 			    sizeof(A_BAND_REGION_9_CHANNEL_LIST) /
257 			    sizeof(u8);
258 			pChannelList = A_BAND_REGION_9_CHANNEL_LIST;
259 			break;
260 
261 		case REGION_10_A_BAND:
262 			num =
263 			    sizeof(A_BAND_REGION_10_CHANNEL_LIST) /
264 			    sizeof(u8);
265 			pChannelList = A_BAND_REGION_10_CHANNEL_LIST;
266 			break;
267 
268 		case REGION_11_A_BAND:
269 			num =
270 			    sizeof(A_BAND_REGION_11_CHANNEL_LIST) /
271 			    sizeof(u8);
272 			pChannelList = A_BAND_REGION_11_CHANNEL_LIST;
273 			break;
274 		case REGION_12_A_BAND:
275 			num =
276 			    sizeof(A_BAND_REGION_12_CHANNEL_LIST) /
277 			    sizeof(u8);
278 			pChannelList = A_BAND_REGION_12_CHANNEL_LIST;
279 			break;
280 		case REGION_13_A_BAND:
281 			num =
282 			    sizeof(A_BAND_REGION_13_CHANNEL_LIST) /
283 			    sizeof(u8);
284 			pChannelList = A_BAND_REGION_13_CHANNEL_LIST;
285 			break;
286 		case REGION_14_A_BAND:
287 			num =
288 			    sizeof(A_BAND_REGION_14_CHANNEL_LIST) /
289 			    sizeof(u8);
290 			pChannelList = A_BAND_REGION_14_CHANNEL_LIST;
291 			break;
292 		case REGION_15_A_BAND:
293 			num =
294 			    sizeof(A_BAND_REGION_15_CHANNEL_LIST) /
295 			    sizeof(u8);
296 			pChannelList = A_BAND_REGION_15_CHANNEL_LIST;
297 			break;
298 		default:	/* Error. should never happen */
299 			DBGPRINT(RT_DEBUG_WARN,
300 				 ("countryregion=%d not support",
301 				  pAd->CommonCfg.CountryRegionForABand));
302 			break;
303 		}
304 
305 		if (num != 0) {
306 			u8 RadarCh[15] =
307 			    { 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124,
308 		    128, 132, 136, 140 };
309 			for (i = 0; i < num; i++) {
310 				for (j = 0; j < MAX_NUM_OF_CHANNELS; j++) {
311 					if (pChannelList[i] ==
312 					    pAd->TxPower[j].Channel)
313 						NdisMoveMemory(&pAd->
314 							       ChannelList[index
315 									   + i],
316 							       &pAd->TxPower[j],
317 							       sizeof
318 							       (struct rt_channel_tx_power));
319 				}
320 				for (j = 0; j < 15; j++) {
321 					if (pChannelList[i] == RadarCh[j])
322 						pAd->ChannelList[index +
323 								 i].DfsReq =
324 						    TRUE;
325 				}
326 				pAd->ChannelList[index + i].MaxTxPwr = 20;
327 			}
328 			index += num;
329 		}
330 	}
331 
332 	pAd->ChannelListNum = index;
333 	DBGPRINT(RT_DEBUG_TRACE,
334 		 ("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n",
335 		  pAd->CommonCfg.CountryRegion,
336 		  pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType,
337 		  pAd->CommonCfg.PhyMode, pAd->ChannelListNum));
338 #ifdef DBG
339 	for (i = 0; i < pAd->ChannelListNum; i++) {
340 		DBGPRINT_RAW(RT_DEBUG_TRACE,
341 			     ("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ",
342 			      pAd->ChannelList[i].Channel,
343 			      pAd->ChannelList[i].Power,
344 			      pAd->ChannelList[i].Power2));
345 	}
346 #endif
347 }
348 
349 /*
350 	==========================================================================
351 	Description:
352 		This routine return the first channel number according to the country
353 		code selection and RF IC selection (signal band or dual band). It is called
354 		whenever driver need to start a site survey of all supported channels.
355 	Return:
356 		ch - the first channel number of current country code setting
357 
358 	IRQL = PASSIVE_LEVEL
359 
360 	==========================================================================
361  */
FirstChannel(struct rt_rtmp_adapter * pAd)362 u8 FirstChannel(struct rt_rtmp_adapter *pAd)
363 {
364 	return pAd->ChannelList[0].Channel;
365 }
366 
367 /*
368 	==========================================================================
369 	Description:
370 		This routine returns the next channel number. This routine is called
371 		during driver need to start a site survey of all supported channels.
372 	Return:
373 		next_channel - the next channel number valid in current country code setting.
374 	Note:
375 		return 0 if no more next channel
376 	==========================================================================
377  */
NextChannel(struct rt_rtmp_adapter * pAd,u8 channel)378 u8 NextChannel(struct rt_rtmp_adapter *pAd, u8 channel)
379 {
380 	int i;
381 	u8 next_channel = 0;
382 
383 	for (i = 0; i < (pAd->ChannelListNum - 1); i++)
384 		if (channel == pAd->ChannelList[i].Channel) {
385 			next_channel = pAd->ChannelList[i + 1].Channel;
386 			break;
387 		}
388 	return next_channel;
389 }
390 
391 /*
392 	==========================================================================
393 	Description:
394 		This routine is for Cisco Compatible Extensions 2.X
395 		Spec31. AP Control of Client Transmit Power
396 	Return:
397 		None
398 	Note:
399 	   Required by Aironet dBm(mW)
400 		   0dBm(1mW),   1dBm(5mW), 13dBm(20mW), 15dBm(30mW),
401 		  17dBm(50mw), 20dBm(100mW)
402 
403 	   We supported
404 		   3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%),
405 		  14dBm(75%),   15dBm(100%)
406 
407 		The client station's actual transmit power shall be within +/- 5dB of
408 		the minimum value or next lower value.
409 	==========================================================================
410  */
ChangeToCellPowerLimit(struct rt_rtmp_adapter * pAd,u8 AironetCellPowerLimit)411 void ChangeToCellPowerLimit(struct rt_rtmp_adapter *pAd,
412 			    u8 AironetCellPowerLimit)
413 {
414 	/*valud 0xFF means that hasn't found power limit information */
415 	/*from the AP's Beacon/Probe response. */
416 	if (AironetCellPowerLimit == 0xFF)
417 		return;
418 
419 	if (AironetCellPowerLimit < 6)	/*Used Lowest Power Percentage. */
420 		pAd->CommonCfg.TxPowerPercentage = 6;
421 	else if (AironetCellPowerLimit < 9)
422 		pAd->CommonCfg.TxPowerPercentage = 10;
423 	else if (AironetCellPowerLimit < 12)
424 		pAd->CommonCfg.TxPowerPercentage = 25;
425 	else if (AironetCellPowerLimit < 14)
426 		pAd->CommonCfg.TxPowerPercentage = 50;
427 	else if (AironetCellPowerLimit < 15)
428 		pAd->CommonCfg.TxPowerPercentage = 75;
429 	else
430 		pAd->CommonCfg.TxPowerPercentage = 100;	/*else used maximum */
431 
432 	if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault)
433 		pAd->CommonCfg.TxPowerPercentage =
434 		    pAd->CommonCfg.TxPowerDefault;
435 
436 }
437 
ConvertToRssi(struct rt_rtmp_adapter * pAd,char Rssi,u8 RssiNumber)438 char ConvertToRssi(struct rt_rtmp_adapter *pAd, char Rssi, u8 RssiNumber)
439 {
440 	u8 RssiOffset, LNAGain;
441 
442 	/* Rssi equals to zero should be an invalid value */
443 	if (Rssi == 0)
444 		return -99;
445 
446 	LNAGain = GET_LNA_GAIN(pAd);
447 	if (pAd->LatchRfRegs.Channel > 14) {
448 		if (RssiNumber == 0)
449 			RssiOffset = pAd->ARssiOffset0;
450 		else if (RssiNumber == 1)
451 			RssiOffset = pAd->ARssiOffset1;
452 		else
453 			RssiOffset = pAd->ARssiOffset2;
454 	} else {
455 		if (RssiNumber == 0)
456 			RssiOffset = pAd->BGRssiOffset0;
457 		else if (RssiNumber == 1)
458 			RssiOffset = pAd->BGRssiOffset1;
459 		else
460 			RssiOffset = pAd->BGRssiOffset2;
461 	}
462 
463 	return (-12 - RssiOffset - LNAGain - Rssi);
464 }
465 
466 /*
467 	==========================================================================
468 	Description:
469 		Scan next channel
470 	==========================================================================
471  */
ScanNextChannel(struct rt_rtmp_adapter * pAd)472 void ScanNextChannel(struct rt_rtmp_adapter *pAd)
473 {
474 	struct rt_header_802_11 Hdr80211;
475 	u8 *pOutBuffer = NULL;
476 	int NStatus;
477 	unsigned long FrameLen = 0;
478 	u8 SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0;
479 	u16 Status;
480 	struct rt_header_802_11 * pHdr80211;
481 	u32 ScanTimeIn5gChannel = SHORT_CHANNEL_TIME;
482 
483 	{
484 		if (MONITOR_ON(pAd))
485 			return;
486 	}
487 
488 	if (pAd->MlmeAux.Channel == 0) {
489 		if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
490 		    && (INFRA_ON(pAd)
491 			|| (pAd->OpMode == OPMODE_AP))
492 		    ) {
493 			AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel,
494 					  FALSE);
495 			AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
496 			RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
497 			BBPValue &= (~0x18);
498 			BBPValue |= 0x10;
499 			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
500 			DBGPRINT(RT_DEBUG_TRACE,
501 				 ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",
502 				  pAd->CommonCfg.CentralChannel,
503 				  pAd->ScanTab.BssNr));
504 		} else {
505 			AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
506 			AsicLockChannel(pAd, pAd->CommonCfg.Channel);
507 			DBGPRINT(RT_DEBUG_TRACE,
508 				 ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",
509 				  pAd->CommonCfg.Channel, pAd->ScanTab.BssNr));
510 		}
511 
512 		{
513 			/* */
514 			/* To prevent data lost. */
515 			/* Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. */
516 			/* Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done */
517 			/* */
518 			if (OPSTATUS_TEST_FLAG
519 			    (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
520 			    && (INFRA_ON(pAd))) {
521 				NStatus =
522 				    MlmeAllocateMemory(pAd,
523 						       (void *)& pOutBuffer);
524 				if (NStatus == NDIS_STATUS_SUCCESS) {
525 					pHdr80211 = (struct rt_header_802_11 *) pOutBuffer;
526 					MgtMacHeaderInit(pAd, pHdr80211,
527 							 SUBTYPE_NULL_FUNC, 1,
528 							 pAd->CommonCfg.Bssid,
529 							 pAd->CommonCfg.Bssid);
530 					pHdr80211->Duration = 0;
531 					pHdr80211->FC.Type = BTYPE_DATA;
532 					pHdr80211->FC.PwrMgmt =
533 					    (pAd->StaCfg.Psm == PWR_SAVE);
534 
535 					/* Send using priority queue */
536 					MiniportMMRequest(pAd, 0, pOutBuffer,
537 							  sizeof
538 							  (struct rt_header_802_11));
539 					DBGPRINT(RT_DEBUG_TRACE,
540 						 ("MlmeScanReqAction -- Send PSM Data frame\n"));
541 					MlmeFreeMemory(pAd, pOutBuffer);
542 					RTMPusecDelay(5000);
543 				}
544 			}
545 
546 			pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
547 			Status = MLME_SUCCESS;
548 			MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF,
549 				    2, &Status);
550 		}
551 
552 		RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
553 	}
554 #ifdef RTMP_MAC_USB
555 	else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
556 		 && (pAd->OpMode == OPMODE_STA)) {
557 		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
558 		MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE);
559 	}
560 #endif /* RTMP_MAC_USB // */
561 	else {
562 		{
563 			/* BBP and RF are not accessible in PS mode, we has to wake them up first */
564 			if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
565 				AsicForceWakeup(pAd, TRUE);
566 
567 			/* leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON */
568 			if (pAd->StaCfg.Psm == PWR_SAVE)
569 				RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
570 		}
571 
572 		AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE);
573 		AsicLockChannel(pAd, pAd->MlmeAux.Channel);
574 
575 		{
576 			if (pAd->MlmeAux.Channel > 14) {
577 				if ((pAd->CommonCfg.bIEEE80211H == 1)
578 				    && RadarChannelCheck(pAd,
579 							 pAd->MlmeAux.
580 							 Channel)) {
581 					ScanType = SCAN_PASSIVE;
582 					ScanTimeIn5gChannel = MIN_CHANNEL_TIME;
583 				}
584 			}
585 		}
586 
587 		/*Global country domain(ch1-11:active scan, ch12-14 passive scan) */
588 		if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12)
589 		    && ((pAd->CommonCfg.CountryRegion & 0x7f) ==
590 			REGION_31_BG_BAND)) {
591 			ScanType = SCAN_PASSIVE;
592 		}
593 		/* We need to shorten active scan time in order for WZC connect issue */
594 		/* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */
595 		if (ScanType == FAST_SCAN_ACTIVE)
596 			RTMPSetTimer(&pAd->MlmeAux.ScanTimer,
597 				     FAST_ACTIVE_SCAN_TIME);
598 		else		/* must be SCAN_PASSIVE or SCAN_ACTIVE */
599 		{
600 			if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED)
601 			    || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED)
602 			    || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED)
603 			    ) {
604 				if (pAd->MlmeAux.Channel > 14)
605 					RTMPSetTimer(&pAd->MlmeAux.ScanTimer,
606 						     ScanTimeIn5gChannel);
607 				else
608 					RTMPSetTimer(&pAd->MlmeAux.ScanTimer,
609 						     MIN_CHANNEL_TIME);
610 			} else
611 				RTMPSetTimer(&pAd->MlmeAux.ScanTimer,
612 					     MAX_CHANNEL_TIME);
613 		}
614 
615 		if ((ScanType == SCAN_ACTIVE)
616 		    || (ScanType == FAST_SCAN_ACTIVE)
617 		    ) {
618 			NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);	/*Get an unused nonpaged memory */
619 			if (NStatus != NDIS_STATUS_SUCCESS) {
620 				DBGPRINT(RT_DEBUG_TRACE,
621 					 ("SYNC - ScanNextChannel() allocate memory fail\n"));
622 
623 				{
624 					pAd->Mlme.SyncMachine.CurrState =
625 					    SYNC_IDLE;
626 					Status = MLME_FAIL_NO_RESOURCE;
627 					MlmeEnqueue(pAd,
628 						    MLME_CNTL_STATE_MACHINE,
629 						    MT2_SCAN_CONF, 2, &Status);
630 				}
631 
632 				return;
633 			}
634 			/* There is no need to send broadcast probe request if active scan is in effect. */
635 			if ((ScanType == SCAN_ACTIVE)
636 			    || (ScanType == FAST_SCAN_ACTIVE)
637 			    )
638 				SsidLen = pAd->MlmeAux.SsidLen;
639 			else
640 				SsidLen = 0;
641 
642 			MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0,
643 					 BROADCAST_ADDR, BROADCAST_ADDR);
644 			MakeOutgoingFrame(pOutBuffer, &FrameLen,
645 					  sizeof(struct rt_header_802_11), &Hdr80211, 1,
646 					  &SsidIe, 1, &SsidLen, SsidLen,
647 					  pAd->MlmeAux.Ssid, 1, &SupRateIe, 1,
648 					  &pAd->CommonCfg.SupRateLen,
649 					  pAd->CommonCfg.SupRateLen,
650 					  pAd->CommonCfg.SupRate, END_OF_ARGS);
651 
652 			if (pAd->CommonCfg.ExtRateLen) {
653 				unsigned long Tmp;
654 				MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
655 						  1, &ExtRateIe,
656 						  1, &pAd->CommonCfg.ExtRateLen,
657 						  pAd->CommonCfg.ExtRateLen,
658 						  pAd->CommonCfg.ExtRate,
659 						  END_OF_ARGS);
660 				FrameLen += Tmp;
661 			}
662 
663 			if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) {
664 				unsigned long Tmp;
665 				u8 HtLen;
666 				u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 };
667 
668 				if (pAd->bBroadComHT == TRUE) {
669 					HtLen =
670 					    pAd->MlmeAux.HtCapabilityLen + 4;
671 
672 					MakeOutgoingFrame(pOutBuffer + FrameLen,
673 							  &Tmp, 1, &WpaIe, 1,
674 							  &HtLen, 4,
675 							  &BROADCOM[0],
676 							  pAd->MlmeAux.
677 							  HtCapabilityLen,
678 							  &pAd->MlmeAux.
679 							  HtCapability,
680 							  END_OF_ARGS);
681 				} else {
682 					HtLen = pAd->MlmeAux.HtCapabilityLen;
683 
684 					MakeOutgoingFrame(pOutBuffer + FrameLen,
685 							  &Tmp, 1, &HtCapIe, 1,
686 							  &HtLen, HtLen,
687 							  &pAd->CommonCfg.
688 							  HtCapability,
689 							  END_OF_ARGS);
690 				}
691 				FrameLen += Tmp;
692 			}
693 
694 			MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
695 			MlmeFreeMemory(pAd, pOutBuffer);
696 		}
697 		/* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe response */
698 
699 		pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN;
700 	}
701 }
702 
MgtProbReqMacHeaderInit(struct rt_rtmp_adapter * pAd,struct rt_header_802_11 * pHdr80211,u8 SubType,u8 ToDs,u8 * pDA,u8 * pBssid)703 void MgtProbReqMacHeaderInit(struct rt_rtmp_adapter *pAd,
704 			     struct rt_header_802_11 * pHdr80211,
705 			     u8 SubType,
706 			     u8 ToDs, u8 *pDA, u8 *pBssid)
707 {
708 	NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
709 
710 	pHdr80211->FC.Type = BTYPE_MGMT;
711 	pHdr80211->FC.SubType = SubType;
712 	if (SubType == SUBTYPE_ACK)
713 		pHdr80211->FC.Type = BTYPE_CNTL;
714 	pHdr80211->FC.ToDs = ToDs;
715 	COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
716 	COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
717 	COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
718 }
719