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