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