linux/drivers/staging/rt2860/common/cmm_sync.c
<<
>>
Prefs
   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. */
  60u8 A_BAND_REGION_0_CHANNEL_LIST[] =
  61    { 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 };
  62u8 A_BAND_REGION_1_CHANNEL_LIST[] =
  63    { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128,
  64132, 136, 140 };
  65u8 A_BAND_REGION_2_CHANNEL_LIST[] = { 36, 40, 44, 48, 52, 56, 60, 64 };
  66u8 A_BAND_REGION_3_CHANNEL_LIST[] = { 52, 56, 60, 64, 149, 153, 157, 161 };
  67u8 A_BAND_REGION_4_CHANNEL_LIST[] = { 149, 153, 157, 161, 165 };
  68u8 A_BAND_REGION_5_CHANNEL_LIST[] = { 149, 153, 157, 161 };
  69u8 A_BAND_REGION_6_CHANNEL_LIST[] = { 36, 40, 44, 48 };
  70u8 A_BAND_REGION_7_CHANNEL_LIST[] =
  71    { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128,
  72132, 136, 140, 149, 153, 157, 161, 165, 169, 173 };
  73u8 A_BAND_REGION_8_CHANNEL_LIST[] = { 52, 56, 60, 64 };
  74u8 A_BAND_REGION_9_CHANNEL_LIST[] =
  75    { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140,
  76149, 153, 157, 161, 165 };
  77u8 A_BAND_REGION_10_CHANNEL_LIST[] =
  78    { 36, 40, 44, 48, 149, 153, 157, 161, 165 };
  79u8 A_BAND_REGION_11_CHANNEL_LIST[] =
  80    { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153,
  81157, 161 };
  82u8 A_BAND_REGION_12_CHANNEL_LIST[] =
  83    { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128,
  84132, 136, 140 };
  85u8 A_BAND_REGION_13_CHANNEL_LIST[] =
  86    { 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
  87149, 153, 157, 161 };
  88u8 A_BAND_REGION_14_CHANNEL_LIST[] =
  89    { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
  90153, 157, 161, 165 };
  91u8 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. */
  94u8 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 */
 108void 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 */
 362u8 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 */
 378u8 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 */
 411void 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
 438char 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 */
 472void 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
 703void 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