linux/drivers/staging/rt2860/common/spectrum.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        action.c
  29
  30    Abstract:
  31    Handle association related requests either from WSTA or from local MLME
  32
  33    Revision History:
  34    Who          When          What
  35    ---------    ----------    ----------------------------------------------
  36        Fonchi Wu    2008                  created for 802.11h
  37 */
  38
  39#include "../rt_config.h"
  40#include "action.h"
  41
  42/* The regulatory information in the USA (US) */
  43struct rt_dot11_regulatory_information USARegulatoryInfo[] = {
  44/*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
  45        {0, {0, 0, {0}
  46             }
  47         }
  48        ,                       /* Invlid entry */
  49        {1, {4, 16, {36, 40, 44, 48}
  50             }
  51         }
  52        ,
  53        {2, {4, 23, {52, 56, 60, 64}
  54             }
  55         }
  56        ,
  57        {3, {4, 29, {149, 153, 157, 161}
  58             }
  59         }
  60        ,
  61        {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
  62             }
  63         }
  64        ,
  65        {5, {5, 30, {149, 153, 157, 161, 165}
  66             }
  67         }
  68        ,
  69        {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
  70             }
  71         }
  72        ,
  73        {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
  74             }
  75         }
  76        ,
  77        {8, {5, 17, {11, 13, 15, 17, 19}
  78             }
  79         }
  80        ,
  81        {9, {5, 30, {11, 13, 15, 17, 19}
  82             }
  83         }
  84        ,
  85        {10, {2, 20, {21, 25}
  86              }
  87         }
  88        ,
  89        {11, {2, 33, {21, 25}
  90              }
  91         }
  92        ,
  93        {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
  94              }
  95         }
  96};
  97
  98#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
  99
 100/* The regulatory information in Europe */
 101struct rt_dot11_regulatory_information EuropeRegulatoryInfo[] = {
 102/*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
 103        {0, {0, 0, {0}
 104             }
 105         }
 106        ,                       /* Invalid entry */
 107        {1, {4, 20, {36, 40, 44, 48}
 108             }
 109         }
 110        ,
 111        {2, {4, 20, {52, 56, 60, 64}
 112             }
 113         }
 114        ,
 115        {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
 116             }
 117         }
 118        ,
 119        {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
 120             }
 121         }
 122};
 123
 124#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
 125
 126/* The regulatory information in Japan */
 127struct rt_dot11_regulatory_information JapanRegulatoryInfo[] = {
 128/*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
 129        {0, {0, 0, {0}
 130             }
 131         }
 132        ,                       /* Invalid entry */
 133        {1, {4, 22, {34, 38, 42, 46}
 134             }
 135         }
 136        ,
 137        {2, {3, 24, {8, 12, 16}
 138             }
 139         }
 140        ,
 141        {3, {3, 24, {8, 12, 16}
 142             }
 143         }
 144        ,
 145        {4, {3, 24, {8, 12, 16}
 146             }
 147         }
 148        ,
 149        {5, {3, 24, {8, 12, 16}
 150             }
 151         }
 152        ,
 153        {6, {3, 22, {8, 12, 16}
 154             }
 155         }
 156        ,
 157        {7, {4, 24, {184, 188, 192, 196}
 158             }
 159         }
 160        ,
 161        {8, {4, 24, {184, 188, 192, 196}
 162             }
 163         }
 164        ,
 165        {9, {4, 24, {184, 188, 192, 196}
 166             }
 167         }
 168        ,
 169        {10, {4, 24, {184, 188, 192, 196}
 170              }
 171         }
 172        ,
 173        {11, {4, 22, {184, 188, 192, 196}
 174              }
 175         }
 176        ,
 177        {12, {4, 24, {7, 8, 9, 11}
 178              }
 179         }
 180        ,
 181        {13, {4, 24, {7, 8, 9, 11}
 182              }
 183         }
 184        ,
 185        {14, {4, 24, {7, 8, 9, 11}
 186              }
 187         }
 188        ,
 189        {15, {4, 24, {7, 8, 9, 11}
 190              }
 191         }
 192        ,
 193        {16, {6, 24, {183, 184, 185, 187, 188, 189}
 194              }
 195         }
 196        ,
 197        {17, {6, 24, {183, 184, 185, 187, 188, 189}
 198              }
 199         }
 200        ,
 201        {18, {6, 24, {183, 184, 185, 187, 188, 189}
 202              }
 203         }
 204        ,
 205        {19, {6, 24, {183, 184, 185, 187, 188, 189}
 206              }
 207         }
 208        ,
 209        {20, {6, 17, {183, 184, 185, 187, 188, 189}
 210              }
 211         }
 212        ,
 213        {21, {6, 24, {6, 7, 8, 9, 10, 11}
 214              }
 215         }
 216        ,
 217        {22, {6, 24, {6, 7, 8, 9, 10, 11}
 218              }
 219         }
 220        ,
 221        {23, {6, 24, {6, 7, 8, 9, 10, 11}
 222              }
 223         }
 224        ,
 225        {24, {6, 24, {6, 7, 8, 9, 10, 11}
 226              }
 227         }
 228        ,
 229        {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
 230              }
 231         }
 232        ,
 233        {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
 234              }
 235         }
 236        ,
 237        {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
 238              }
 239         }
 240        ,
 241        {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
 242              }
 243         }
 244        ,
 245        {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}
 246              }
 247         }
 248        ,
 249        {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
 250              }
 251         }
 252        ,
 253        {31, {1, 23, {14}
 254              }
 255         }
 256        ,
 257        {32, {4, 22, {52, 56, 60, 64}
 258              }
 259         }
 260};
 261
 262#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
 263
 264char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode)
 265{
 266        struct tx_pwr_cfg {
 267                u8 Mode;
 268                u8 MCS;
 269                u16 req;
 270                u8 shift;
 271                u32 BitMask;
 272        };
 273
 274        u32 Value;
 275        int Idx;
 276        u8 PhyMode;
 277        char CurTxPwr;
 278        u8 TxPwrRef = 0;
 279        char DaltaPwr;
 280        unsigned long TxPwr[5];
 281
 282        struct tx_pwr_cfg TxPwrCfg[] = {
 283                {MODE_CCK, 0, 0, 4, 0x000000f0},
 284                {MODE_CCK, 1, 0, 0, 0x0000000f},
 285                {MODE_CCK, 2, 0, 12, 0x0000f000},
 286                {MODE_CCK, 3, 0, 8, 0x00000f00},
 287
 288                {MODE_OFDM, 0, 0, 20, 0x00f00000},
 289                {MODE_OFDM, 1, 0, 16, 0x000f0000},
 290                {MODE_OFDM, 2, 0, 28, 0xf0000000},
 291                {MODE_OFDM, 3, 0, 24, 0x0f000000},
 292                {MODE_OFDM, 4, 1, 4, 0x000000f0},
 293                {MODE_OFDM, 5, 1, 0, 0x0000000f},
 294                {MODE_OFDM, 6, 1, 12, 0x0000f000},
 295                {MODE_OFDM, 7, 1, 8, 0x00000f00}
 296                , {MODE_HTMIX, 0, 1, 20, 0x00f00000},
 297                {MODE_HTMIX, 1, 1, 16, 0x000f0000},
 298                {MODE_HTMIX, 2, 1, 28, 0xf0000000},
 299                {MODE_HTMIX, 3, 1, 24, 0x0f000000},
 300                {MODE_HTMIX, 4, 2, 4, 0x000000f0},
 301                {MODE_HTMIX, 5, 2, 0, 0x0000000f},
 302                {MODE_HTMIX, 6, 2, 12, 0x0000f000},
 303                {MODE_HTMIX, 7, 2, 8, 0x00000f00},
 304                {MODE_HTMIX, 8, 2, 20, 0x00f00000},
 305                {MODE_HTMIX, 9, 2, 16, 0x000f0000},
 306                {MODE_HTMIX, 10, 2, 28, 0xf0000000},
 307                {MODE_HTMIX, 11, 2, 24, 0x0f000000},
 308                {MODE_HTMIX, 12, 3, 4, 0x000000f0},
 309                {MODE_HTMIX, 13, 3, 0, 0x0000000f},
 310                {MODE_HTMIX, 14, 3, 12, 0x0000f000},
 311                {MODE_HTMIX, 15, 3, 8, 0x00000f00}
 312        };
 313#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(struct tx_pwr_cfg))
 314
 315        CurTxPwr = 19;
 316
 317        /* check Tx Power setting from UI. */
 318        if (pAd->CommonCfg.TxPowerPercentage > 90) ;
 319        else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
 320                CurTxPwr -= 1;
 321        else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
 322                CurTxPwr -= 3;
 323        else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
 324                CurTxPwr -= 6;
 325        else if (pAd->CommonCfg.TxPowerPercentage > 9)  /* reduce Pwr for 9 dB. */
 326                CurTxPwr -= 9;
 327        else                    /* reduce Pwr for 12 dB. */
 328                CurTxPwr -= 12;
 329
 330        if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
 331                if (pAd->CommonCfg.CentralChannel > 14) {
 332                        TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
 333                        TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
 334                        TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
 335                        TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
 336                        TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
 337                } else {
 338                        TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
 339                        TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
 340                        TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
 341                        TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
 342                        TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
 343                }
 344        } else {
 345                if (pAd->CommonCfg.Channel > 14) {
 346                        TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
 347                        TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
 348                        TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
 349                        TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
 350                        TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
 351                } else {
 352                        TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
 353                        TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
 354                        TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
 355                        TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
 356                        TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
 357                }
 358        }
 359
 360        switch (HTTxMode.field.MODE) {
 361        case MODE_CCK:
 362        case MODE_OFDM:
 363                Value = TxPwr[1];
 364                TxPwrRef = (Value & 0x00000f00) >> 8;
 365
 366                break;
 367
 368        case MODE_HTMIX:
 369        case MODE_HTGREENFIELD:
 370                if (pAd->CommonCfg.TxStream == 1) {
 371                        Value = TxPwr[2];
 372                        TxPwrRef = (Value & 0x00000f00) >> 8;
 373                } else if (pAd->CommonCfg.TxStream == 2) {
 374                        Value = TxPwr[3];
 375                        TxPwrRef = (Value & 0x00000f00) >> 8;
 376                }
 377                break;
 378        }
 379
 380        PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD)
 381            ? MODE_HTMIX : HTTxMode.field.MODE;
 382
 383        for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) {
 384                if ((TxPwrCfg[Idx].Mode == PhyMode)
 385                    && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) {
 386                        Value = TxPwr[TxPwrCfg[Idx].req];
 387                        DaltaPwr =
 388                            TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask)
 389                                               >> TxPwrCfg[Idx].shift);
 390                        CurTxPwr -= DaltaPwr;
 391                        break;
 392                }
 393        }
 394
 395        return CurTxPwr;
 396}
 397
 398void MeasureReqTabInit(struct rt_rtmp_adapter *pAd)
 399{
 400        NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
 401
 402        pAd->CommonCfg.pMeasureReqTab =
 403            kmalloc(sizeof(struct rt_measure_req_tab), GFP_ATOMIC);
 404        if (pAd->CommonCfg.pMeasureReqTab)
 405                NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab,
 406                               sizeof(struct rt_measure_req_tab));
 407        else
 408                DBGPRINT(RT_DEBUG_ERROR,
 409                         ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n",
 410                          __func__));
 411
 412        return;
 413}
 414
 415void MeasureReqTabExit(struct rt_rtmp_adapter *pAd)
 416{
 417        NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
 418
 419        if (pAd->CommonCfg.pMeasureReqTab)
 420                kfree(pAd->CommonCfg.pMeasureReqTab);
 421        pAd->CommonCfg.pMeasureReqTab = NULL;
 422
 423        return;
 424}
 425
 426struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
 427{
 428        u32 HashIdx;
 429        struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
 430        struct rt_measure_req_entry *pEntry = NULL;
 431        struct rt_measure_req_entry *pPrevEntry = NULL;
 432
 433        if (pTab == NULL) {
 434                DBGPRINT(RT_DEBUG_ERROR,
 435                         ("%s: pMeasureReqTab doesn't exist.\n", __func__));
 436                return NULL;
 437        }
 438
 439        RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
 440
 441        HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
 442        pEntry = pTab->Hash[HashIdx];
 443
 444        while (pEntry) {
 445                if (pEntry->DialogToken == DialogToken)
 446                        break;
 447                else {
 448                        pPrevEntry = pEntry;
 449                        pEntry = pEntry->pNext;
 450                }
 451        }
 452
 453        RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
 454
 455        return pEntry;
 456}
 457
 458struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
 459{
 460        int i;
 461        unsigned long HashIdx;
 462        struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
 463        struct rt_measure_req_entry *pEntry = NULL, *pCurrEntry;
 464        unsigned long Now;
 465
 466        if (pTab == NULL) {
 467                DBGPRINT(RT_DEBUG_ERROR,
 468                         ("%s: pMeasureReqTab doesn't exist.\n", __func__));
 469                return NULL;
 470        }
 471
 472        pEntry = MeasureReqLookUp(pAd, DialogToken);
 473        if (pEntry == NULL) {
 474                RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
 475                for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) {
 476                        NdisGetSystemUpTime(&Now);
 477                        pEntry = &pTab->Content[i];
 478
 479                        if ((pEntry->Valid == TRUE)
 480                            && RTMP_TIME_AFTER((unsigned long)Now,
 481                                               (unsigned long)(pEntry->
 482                                                               lastTime +
 483                                                               MQ_REQ_AGE_OUT)))
 484                        {
 485                                struct rt_measure_req_entry *pPrevEntry = NULL;
 486                                unsigned long HashIdx =
 487                                    MQ_DIALOGTOKEN_HASH_INDEX(pEntry->
 488                                                              DialogToken);
 489                                struct rt_measure_req_entry *pProbeEntry =
 490                                    pTab->Hash[HashIdx];
 491
 492                                /* update Hash list */
 493                                do {
 494                                        if (pProbeEntry == pEntry) {
 495                                                if (pPrevEntry == NULL) {
 496                                                        pTab->Hash[HashIdx] =
 497                                                            pEntry->pNext;
 498                                                } else {
 499                                                        pPrevEntry->pNext =
 500                                                            pEntry->pNext;
 501                                                }
 502                                                break;
 503                                        }
 504
 505                                        pPrevEntry = pProbeEntry;
 506                                        pProbeEntry = pProbeEntry->pNext;
 507                                } while (pProbeEntry);
 508
 509                                NdisZeroMemory(pEntry,
 510                                               sizeof(struct rt_measure_req_entry));
 511                                pTab->Size--;
 512
 513                                break;
 514                        }
 515
 516                        if (pEntry->Valid == FALSE)
 517                                break;
 518                }
 519
 520                if (i < MAX_MEASURE_REQ_TAB_SIZE) {
 521                        NdisGetSystemUpTime(&Now);
 522                        pEntry->lastTime = Now;
 523                        pEntry->Valid = TRUE;
 524                        pEntry->DialogToken = DialogToken;
 525                        pTab->Size++;
 526                } else {
 527                        pEntry = NULL;
 528                        DBGPRINT(RT_DEBUG_ERROR,
 529                                 ("%s: pMeasureReqTab tab full.\n", __func__));
 530                }
 531
 532                /* add this Neighbor entry into HASH table */
 533                if (pEntry) {
 534                        HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
 535                        if (pTab->Hash[HashIdx] == NULL) {
 536                                pTab->Hash[HashIdx] = pEntry;
 537                        } else {
 538                                pCurrEntry = pTab->Hash[HashIdx];
 539                                while (pCurrEntry->pNext != NULL)
 540                                        pCurrEntry = pCurrEntry->pNext;
 541                                pCurrEntry->pNext = pEntry;
 542                        }
 543                }
 544
 545                RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
 546        }
 547
 548        return pEntry;
 549}
 550
 551void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
 552{
 553        struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
 554        struct rt_measure_req_entry *pEntry = NULL;
 555
 556        if (pTab == NULL) {
 557                DBGPRINT(RT_DEBUG_ERROR,
 558                         ("%s: pMeasureReqTab doesn't exist.\n", __func__));
 559                return;
 560        }
 561        /* if empty, return */
 562        if (pTab->Size == 0) {
 563                DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
 564                return;
 565        }
 566
 567        pEntry = MeasureReqLookUp(pAd, DialogToken);
 568        if (pEntry != NULL) {
 569                struct rt_measure_req_entry *pPrevEntry = NULL;
 570                unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
 571                struct rt_measure_req_entry *pProbeEntry = pTab->Hash[HashIdx];
 572
 573                RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
 574                /* update Hash list */
 575                do {
 576                        if (pProbeEntry == pEntry) {
 577                                if (pPrevEntry == NULL) {
 578                                        pTab->Hash[HashIdx] = pEntry->pNext;
 579                                } else {
 580                                        pPrevEntry->pNext = pEntry->pNext;
 581                                }
 582                                break;
 583                        }
 584
 585                        pPrevEntry = pProbeEntry;
 586                        pProbeEntry = pProbeEntry->pNext;
 587                } while (pProbeEntry);
 588
 589                NdisZeroMemory(pEntry, sizeof(struct rt_measure_req_entry));
 590                pTab->Size--;
 591
 592                RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
 593        }
 594
 595        return;
 596}
 597
 598void TpcReqTabInit(struct rt_rtmp_adapter *pAd)
 599{
 600        NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
 601
 602        pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(struct rt_tpc_req_tab), GFP_ATOMIC);
 603        if (pAd->CommonCfg.pTpcReqTab)
 604                NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(struct rt_tpc_req_tab));
 605        else
 606                DBGPRINT(RT_DEBUG_ERROR,
 607                         ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n",
 608                          __func__));
 609
 610        return;
 611}
 612
 613void TpcReqTabExit(struct rt_rtmp_adapter *pAd)
 614{
 615        NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
 616
 617        if (pAd->CommonCfg.pTpcReqTab)
 618                kfree(pAd->CommonCfg.pTpcReqTab);
 619        pAd->CommonCfg.pTpcReqTab = NULL;
 620
 621        return;
 622}
 623
 624static struct rt_tpc_req_entry *TpcReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
 625{
 626        u32 HashIdx;
 627        struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
 628        struct rt_tpc_req_entry *pEntry = NULL;
 629        struct rt_tpc_req_entry *pPrevEntry = NULL;
 630
 631        if (pTab == NULL) {
 632                DBGPRINT(RT_DEBUG_ERROR,
 633                         ("%s: pTpcReqTab doesn't exist.\n", __func__));
 634                return NULL;
 635        }
 636
 637        RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
 638
 639        HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
 640        pEntry = pTab->Hash[HashIdx];
 641
 642        while (pEntry) {
 643                if (pEntry->DialogToken == DialogToken)
 644                        break;
 645                else {
 646                        pPrevEntry = pEntry;
 647                        pEntry = pEntry->pNext;
 648                }
 649        }
 650
 651        RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
 652
 653        return pEntry;
 654}
 655
 656static struct rt_tpc_req_entry *TpcReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
 657{
 658        int i;
 659        unsigned long HashIdx;
 660        struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
 661        struct rt_tpc_req_entry *pEntry = NULL, *pCurrEntry;
 662        unsigned long Now;
 663
 664        if (pTab == NULL) {
 665                DBGPRINT(RT_DEBUG_ERROR,
 666                         ("%s: pTpcReqTab doesn't exist.\n", __func__));
 667                return NULL;
 668        }
 669
 670        pEntry = TpcReqLookUp(pAd, DialogToken);
 671        if (pEntry == NULL) {
 672                RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
 673                for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) {
 674                        NdisGetSystemUpTime(&Now);
 675                        pEntry = &pTab->Content[i];
 676
 677                        if ((pEntry->Valid == TRUE)
 678                            && RTMP_TIME_AFTER((unsigned long)Now,
 679                                               (unsigned long)(pEntry->
 680                                                               lastTime +
 681                                                               TPC_REQ_AGE_OUT)))
 682                        {
 683                                struct rt_tpc_req_entry *pPrevEntry = NULL;
 684                                unsigned long HashIdx =
 685                                    TPC_DIALOGTOKEN_HASH_INDEX(pEntry->
 686                                                               DialogToken);
 687                                struct rt_tpc_req_entry *pProbeEntry =
 688                                    pTab->Hash[HashIdx];
 689
 690                                /* update Hash list */
 691                                do {
 692                                        if (pProbeEntry == pEntry) {
 693                                                if (pPrevEntry == NULL) {
 694                                                        pTab->Hash[HashIdx] =
 695                                                            pEntry->pNext;
 696                                                } else {
 697                                                        pPrevEntry->pNext =
 698                                                            pEntry->pNext;
 699                                                }
 700                                                break;
 701                                        }
 702
 703                                        pPrevEntry = pProbeEntry;
 704                                        pProbeEntry = pProbeEntry->pNext;
 705                                } while (pProbeEntry);
 706
 707                                NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry));
 708                                pTab->Size--;
 709
 710                                break;
 711                        }
 712
 713                        if (pEntry->Valid == FALSE)
 714                                break;
 715                }
 716
 717                if (i < MAX_TPC_REQ_TAB_SIZE) {
 718                        NdisGetSystemUpTime(&Now);
 719                        pEntry->lastTime = Now;
 720                        pEntry->Valid = TRUE;
 721                        pEntry->DialogToken = DialogToken;
 722                        pTab->Size++;
 723                } else {
 724                        pEntry = NULL;
 725                        DBGPRINT(RT_DEBUG_ERROR,
 726                                 ("%s: pTpcReqTab tab full.\n", __func__));
 727                }
 728
 729                /* add this Neighbor entry into HASH table */
 730                if (pEntry) {
 731                        HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
 732                        if (pTab->Hash[HashIdx] == NULL) {
 733                                pTab->Hash[HashIdx] = pEntry;
 734                        } else {
 735                                pCurrEntry = pTab->Hash[HashIdx];
 736                                while (pCurrEntry->pNext != NULL)
 737                                        pCurrEntry = pCurrEntry->pNext;
 738                                pCurrEntry->pNext = pEntry;
 739                        }
 740                }
 741
 742                RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
 743        }
 744
 745        return pEntry;
 746}
 747
 748static void TpcReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
 749{
 750        struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
 751        struct rt_tpc_req_entry *pEntry = NULL;
 752
 753        if (pTab == NULL) {
 754                DBGPRINT(RT_DEBUG_ERROR,
 755                         ("%s: pTpcReqTab doesn't exist.\n", __func__));
 756                return;
 757        }
 758        /* if empty, return */
 759        if (pTab->Size == 0) {
 760                DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
 761                return;
 762        }
 763
 764        pEntry = TpcReqLookUp(pAd, DialogToken);
 765        if (pEntry != NULL) {
 766                struct rt_tpc_req_entry *pPrevEntry = NULL;
 767                unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
 768                struct rt_tpc_req_entry *pProbeEntry = pTab->Hash[HashIdx];
 769
 770                RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
 771                /* update Hash list */
 772                do {
 773                        if (pProbeEntry == pEntry) {
 774                                if (pPrevEntry == NULL) {
 775                                        pTab->Hash[HashIdx] = pEntry->pNext;
 776                                } else {
 777                                        pPrevEntry->pNext = pEntry->pNext;
 778                                }
 779                                break;
 780                        }
 781
 782                        pPrevEntry = pProbeEntry;
 783                        pProbeEntry = pProbeEntry->pNext;
 784                } while (pProbeEntry);
 785
 786                NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry));
 787                pTab->Size--;
 788
 789                RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
 790        }
 791
 792        return;
 793}
 794
 795/*
 796        ==========================================================================
 797        Description:
 798                Get Current TimeS tamp.
 799
 800        Parametrs:
 801
 802        Return  : Current Time Stamp.
 803        ==========================================================================
 804 */
 805static u64 GetCurrentTimeStamp(struct rt_rtmp_adapter *pAd)
 806{
 807        /* get current time stamp. */
 808        return 0;
 809}
 810
 811/*
 812        ==========================================================================
 813        Description:
 814                Get Current Transmit Power.
 815
 816        Parametrs:
 817
 818        Return  : Current Time Stamp.
 819        ==========================================================================
 820 */
 821static u8 GetCurTxPwr(struct rt_rtmp_adapter *pAd, u8 Wcid)
 822{
 823        return 16;              /* 16 dBm */
 824}
 825
 826/*
 827        ==========================================================================
 828        Description:
 829                Get Current Transmit Power.
 830
 831        Parametrs:
 832
 833        Return  : Current Time Stamp.
 834        ==========================================================================
 835 */
 836void InsertChannelRepIE(struct rt_rtmp_adapter *pAd,
 837                        u8 *pFrameBuf,
 838                        unsigned long *pFrameLen,
 839                        char *pCountry, u8 RegulatoryClass)
 840{
 841        unsigned long TempLen;
 842        u8 Len;
 843        u8 IEId = IE_AP_CHANNEL_REPORT;
 844        u8 *pChListPtr = NULL;
 845
 846        Len = 1;
 847        if (strncmp(pCountry, "US", 2) == 0) {
 848                if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) {
 849                        DBGPRINT(RT_DEBUG_ERROR,
 850                                 ("%s: USA Unknow Requlatory class (%d)\n",
 851                                  __func__, RegulatoryClass));
 852                        return;
 853                }
 854
 855                Len +=
 856                    USARegulatoryInfo[RegulatoryClass].ChannelSet.
 857                    NumberOfChannels;
 858                pChListPtr =
 859                    USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
 860        } else if (strncmp(pCountry, "JP", 2) == 0) {
 861                if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) {
 862                        DBGPRINT(RT_DEBUG_ERROR,
 863                                 ("%s: JP Unknow Requlatory class (%d)\n",
 864                                  __func__, RegulatoryClass));
 865                        return;
 866                }
 867
 868                Len +=
 869                    JapanRegulatoryInfo[RegulatoryClass].ChannelSet.
 870                    NumberOfChannels;
 871                pChListPtr =
 872                    JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
 873        } else {
 874                DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
 875                                          __func__, pCountry));
 876                return;
 877        }
 878
 879        MakeOutgoingFrame(pFrameBuf, &TempLen,
 880                          1, &IEId,
 881                          1, &Len,
 882                          1, &RegulatoryClass,
 883                          Len - 1, pChListPtr, END_OF_ARGS);
 884
 885        *pFrameLen = *pFrameLen + TempLen;
 886
 887        return;
 888}
 889
 890/*
 891        ==========================================================================
 892        Description:
 893                Insert Dialog Token into frame.
 894
 895        Parametrs:
 896                1. frame buffer pointer.
 897                2. frame length.
 898                3. Dialog token.
 899
 900        Return  : None.
 901        ==========================================================================
 902 */
 903void InsertDialogToken(struct rt_rtmp_adapter *pAd,
 904                       u8 *pFrameBuf,
 905                       unsigned long *pFrameLen, u8 DialogToken)
 906{
 907        unsigned long TempLen;
 908        MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS);
 909
 910        *pFrameLen = *pFrameLen + TempLen;
 911
 912        return;
 913}
 914
 915/*
 916        ==========================================================================
 917        Description:
 918                Insert TPC Request IE into frame.
 919
 920        Parametrs:
 921                1. frame buffer pointer.
 922                2. frame length.
 923
 924        Return  : None.
 925        ==========================================================================
 926 */
 927static void InsertTpcReqIE(struct rt_rtmp_adapter *pAd,
 928                           u8 *pFrameBuf, unsigned long *pFrameLen)
 929{
 930        unsigned long TempLen;
 931        unsigned long Len = 0;
 932        u8 ElementID = IE_TPC_REQUEST;
 933
 934        MakeOutgoingFrame(pFrameBuf, &TempLen,
 935                          1, &ElementID, 1, &Len, END_OF_ARGS);
 936
 937        *pFrameLen = *pFrameLen + TempLen;
 938
 939        return;
 940}
 941
 942/*
 943        ==========================================================================
 944        Description:
 945                Insert TPC Report IE into frame.
 946
 947        Parametrs:
 948                1. frame buffer pointer.
 949                2. frame length.
 950                3. Transmit Power.
 951                4. Link Margin.
 952
 953        Return  : None.
 954        ==========================================================================
 955 */
 956void InsertTpcReportIE(struct rt_rtmp_adapter *pAd,
 957                       u8 *pFrameBuf,
 958                       unsigned long *pFrameLen,
 959                       u8 TxPwr, u8 LinkMargin)
 960{
 961        unsigned long TempLen;
 962        unsigned long Len = sizeof(struct rt_tpc_report_info);
 963        u8 ElementID = IE_TPC_REPORT;
 964        struct rt_tpc_report_info TpcReportIE;
 965
 966        TpcReportIE.TxPwr = TxPwr;
 967        TpcReportIE.LinkMargin = LinkMargin;
 968
 969        MakeOutgoingFrame(pFrameBuf, &TempLen,
 970                          1, &ElementID,
 971                          1, &Len, Len, &TpcReportIE, END_OF_ARGS);
 972
 973        *pFrameLen = *pFrameLen + TempLen;
 974
 975        return;
 976}
 977
 978/*
 979        ==========================================================================
 980        Description:
 981                Insert Channel Switch Announcement IE into frame.
 982
 983        Parametrs:
 984                1. frame buffer pointer.
 985                2. frame length.
 986                3. channel switch announcement mode.
 987                4. new selected channel.
 988                5. channel switch announcement count.
 989
 990        Return  : None.
 991        ==========================================================================
 992 */
 993static void InsertChSwAnnIE(struct rt_rtmp_adapter *pAd,
 994                            u8 *pFrameBuf,
 995                            unsigned long *pFrameLen,
 996                            u8 ChSwMode,
 997                            u8 NewChannel, u8 ChSwCnt)
 998{
 999        unsigned long TempLen;
1000        unsigned long Len = sizeof(struct rt_ch_sw_ann_info);
1001        u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
1002        struct rt_ch_sw_ann_info ChSwAnnIE;
1003
1004        ChSwAnnIE.ChSwMode = ChSwMode;
1005        ChSwAnnIE.Channel = NewChannel;
1006        ChSwAnnIE.ChSwCnt = ChSwCnt;
1007
1008        MakeOutgoingFrame(pFrameBuf, &TempLen,
1009                          1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS);
1010
1011        *pFrameLen = *pFrameLen + TempLen;
1012
1013        return;
1014}
1015
1016/*
1017        ==========================================================================
1018        Description:
1019                Insert Measure Request IE into frame.
1020
1021        Parametrs:
1022                1. frame buffer pointer.
1023                2. frame length.
1024                3. Measure Token.
1025                4. Measure Request Mode.
1026                5. Measure Request Type.
1027                6. Measure Channel.
1028                7. Measure Start time.
1029                8. Measure Duration.
1030
1031        Return  : None.
1032        ==========================================================================
1033 */
1034static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd,
1035                               u8 *pFrameBuf,
1036                               unsigned long *pFrameLen,
1037                               u8 Len, struct rt_measure_req_info * pMeasureReqIE)
1038{
1039        unsigned long TempLen;
1040        u8 ElementID = IE_MEASUREMENT_REQUEST;
1041
1042        MakeOutgoingFrame(pFrameBuf, &TempLen,
1043                          1, &ElementID,
1044                          1, &Len,
1045                          sizeof(struct rt_measure_req_info), pMeasureReqIE, END_OF_ARGS);
1046
1047        *pFrameLen = *pFrameLen + TempLen;
1048
1049        return;
1050}
1051
1052/*
1053        ==========================================================================
1054        Description:
1055                Insert Measure Report IE into frame.
1056
1057        Parametrs:
1058                1. frame buffer pointer.
1059                2. frame length.
1060                3. Measure Token.
1061                4. Measure Request Mode.
1062                5. Measure Request Type.
1063                6. Length of Report Infomation
1064                7. Pointer of Report Infomation Buffer.
1065
1066        Return  : None.
1067        ==========================================================================
1068 */
1069static void InsertMeasureReportIE(struct rt_rtmp_adapter *pAd,
1070                                  u8 *pFrameBuf,
1071                                  unsigned long *pFrameLen,
1072                                  struct rt_measure_report_info * pMeasureReportIE,
1073                                  u8 ReportLnfoLen, u8 *pReportInfo)
1074{
1075        unsigned long TempLen;
1076        unsigned long Len;
1077        u8 ElementID = IE_MEASUREMENT_REPORT;
1078
1079        Len = sizeof(struct rt_measure_report_info) + ReportLnfoLen;
1080
1081        MakeOutgoingFrame(pFrameBuf, &TempLen,
1082                          1, &ElementID,
1083                          1, &Len, Len, pMeasureReportIE, END_OF_ARGS);
1084
1085        *pFrameLen = *pFrameLen + TempLen;
1086
1087        if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) {
1088                MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1089                                  ReportLnfoLen, pReportInfo, END_OF_ARGS);
1090
1091                *pFrameLen = *pFrameLen + TempLen;
1092        }
1093        return;
1094}
1095
1096/*
1097        ==========================================================================
1098        Description:
1099                Prepare Measurement request action frame and enqueue it into
1100                management queue waiting for transmition.
1101
1102        Parametrs:
1103                1. the destination mac address of the frame.
1104
1105        Return  : None.
1106        ==========================================================================
1107 */
1108void MakeMeasurementReqFrame(struct rt_rtmp_adapter *pAd,
1109                             u8 *pOutBuffer,
1110                             unsigned long *pFrameLen,
1111                             u8 TotalLen,
1112                             u8 Category,
1113                             u8 Action,
1114                             u8 MeasureToken,
1115                             u8 MeasureReqMode,
1116                             u8 MeasureReqType, u8 NumOfRepetitions)
1117{
1118        unsigned long TempLen;
1119        struct rt_measure_req_info MeasureReqIE;
1120
1121        InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category,
1122                       Action);
1123
1124        /* fill Dialog Token */
1125        InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1126                          MeasureToken);
1127
1128        /* fill Number of repetitions. */
1129        if (Category == CATEGORY_RM) {
1130                MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen,
1131                                  2, &NumOfRepetitions, END_OF_ARGS);
1132
1133                *pFrameLen += TempLen;
1134        }
1135        /* prepare Measurement IE. */
1136        NdisZeroMemory(&MeasureReqIE, sizeof(struct rt_measure_req_info));
1137        MeasureReqIE.Token = MeasureToken;
1138        MeasureReqIE.ReqMode.word = MeasureReqMode;
1139        MeasureReqIE.ReqType = MeasureReqType;
1140        InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1141                           TotalLen, &MeasureReqIE);
1142
1143        return;
1144}
1145
1146/*
1147        ==========================================================================
1148        Description:
1149                Prepare Measurement report action frame and enqueue it into
1150                management queue waiting for transmition.
1151
1152        Parametrs:
1153                1. the destination mac address of the frame.
1154
1155        Return  : None.
1156        ==========================================================================
1157 */
1158void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd,
1159                           u8 *pDA,
1160                           u8 DialogToken,
1161                           u8 MeasureToken,
1162                           u8 MeasureReqMode,
1163                           u8 MeasureReqType,
1164                           u8 ReportInfoLen, u8 *pReportInfo)
1165{
1166        u8 *pOutBuffer = NULL;
1167        int NStatus;
1168        unsigned long FrameLen;
1169        struct rt_header_802_11 ActHdr;
1170        struct rt_measure_report_info MeasureRepIE;
1171
1172        /* build action frame header. */
1173        MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1174                         pAd->CurrentAddress);
1175
1176        NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1177        if (NStatus != NDIS_STATUS_SUCCESS) {
1178                DBGPRINT(RT_DEBUG_TRACE,
1179                         ("%s() allocate memory failed \n", __func__));
1180                return;
1181        }
1182        NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1183        FrameLen = sizeof(struct rt_header_802_11);
1184
1185        InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1186                       CATEGORY_SPECTRUM, SPEC_MRP);
1187
1188        /* fill Dialog Token */
1189        InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1190
1191        /* prepare Measurement IE. */
1192        NdisZeroMemory(&MeasureRepIE, sizeof(struct rt_measure_report_info));
1193        MeasureRepIE.Token = MeasureToken;
1194        MeasureRepIE.ReportMode = MeasureReqMode;
1195        MeasureRepIE.ReportType = MeasureReqType;
1196        InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
1197                              &MeasureRepIE, ReportInfoLen, pReportInfo);
1198
1199        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1200        MlmeFreeMemory(pAd, pOutBuffer);
1201
1202        return;
1203}
1204
1205/*
1206        ==========================================================================
1207        Description:
1208                Prepare TPC Request action frame and enqueue it into
1209                management queue waiting for transmition.
1210
1211        Parametrs:
1212                1. the destination mac address of the frame.
1213
1214        Return  : None.
1215        ==========================================================================
1216 */
1217void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken)
1218{
1219        u8 *pOutBuffer = NULL;
1220        int NStatus;
1221        unsigned long FrameLen;
1222
1223        struct rt_header_802_11 ActHdr;
1224
1225        /* build action frame header. */
1226        MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1227                         pAd->CurrentAddress);
1228
1229        NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1230        if (NStatus != NDIS_STATUS_SUCCESS) {
1231                DBGPRINT(RT_DEBUG_TRACE,
1232                         ("%s() allocate memory failed \n", __func__));
1233                return;
1234        }
1235        NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1236        FrameLen = sizeof(struct rt_header_802_11);
1237
1238        InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1239                       CATEGORY_SPECTRUM, SPEC_TPCRQ);
1240
1241        /* fill Dialog Token */
1242        InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1243
1244        /* Insert TPC Request IE. */
1245        InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1246
1247        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1248        MlmeFreeMemory(pAd, pOutBuffer);
1249
1250        return;
1251}
1252
1253/*
1254        ==========================================================================
1255        Description:
1256                Prepare TPC Report action frame and enqueue it into
1257                management queue waiting for transmition.
1258
1259        Parametrs:
1260                1. the destination mac address of the frame.
1261
1262        Return  : None.
1263        ==========================================================================
1264 */
1265void EnqueueTPCRep(struct rt_rtmp_adapter *pAd,
1266                   u8 *pDA,
1267                   u8 DialogToken, u8 TxPwr, u8 LinkMargin)
1268{
1269        u8 *pOutBuffer = NULL;
1270        int NStatus;
1271        unsigned long FrameLen;
1272
1273        struct rt_header_802_11 ActHdr;
1274
1275        /* build action frame header. */
1276        MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1277                         pAd->CurrentAddress);
1278
1279        NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1280        if (NStatus != NDIS_STATUS_SUCCESS) {
1281                DBGPRINT(RT_DEBUG_TRACE,
1282                         ("%s() allocate memory failed \n", __func__));
1283                return;
1284        }
1285        NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1286        FrameLen = sizeof(struct rt_header_802_11);
1287
1288        InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1289                       CATEGORY_SPECTRUM, SPEC_TPCRP);
1290
1291        /* fill Dialog Token */
1292        InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1293
1294        /* Insert TPC Request IE. */
1295        InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr,
1296                          LinkMargin);
1297
1298        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1299        MlmeFreeMemory(pAd, pOutBuffer);
1300
1301        return;
1302}
1303
1304/*
1305        ==========================================================================
1306        Description:
1307                Prepare Channel Switch Announcement action frame and enqueue it into
1308                management queue waiting for transmition.
1309
1310        Parametrs:
1311                1. the destination mac address of the frame.
1312                2. Channel switch announcement mode.
1313                2. a New selected channel.
1314
1315        Return  : None.
1316        ==========================================================================
1317 */
1318void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd,
1319                    u8 *pDA, u8 ChSwMode, u8 NewCh)
1320{
1321        u8 *pOutBuffer = NULL;
1322        int NStatus;
1323        unsigned long FrameLen;
1324
1325        struct rt_header_802_11 ActHdr;
1326
1327        /* build action frame header. */
1328        MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1329                         pAd->CurrentAddress);
1330
1331        NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1332        if (NStatus != NDIS_STATUS_SUCCESS) {
1333                DBGPRINT(RT_DEBUG_TRACE,
1334                         ("%s() allocate memory failed \n", __func__));
1335                return;
1336        }
1337        NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1338        FrameLen = sizeof(struct rt_header_802_11);
1339
1340        InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1341                       CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1342
1343        InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode,
1344                        NewCh, 0);
1345
1346        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1347        MlmeFreeMemory(pAd, pOutBuffer);
1348
1349        return;
1350}
1351
1352static BOOLEAN DfsRequirementCheck(struct rt_rtmp_adapter *pAd, u8 Channel)
1353{
1354        BOOLEAN Result = FALSE;
1355        int i;
1356
1357        do {
1358                /* check DFS procedure is running. */
1359                /* make sure DFS procedure won't start twice. */
1360                if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) {
1361                        Result = FALSE;
1362                        break;
1363                }
1364                /* check the new channel carried from Channel Switch Announcemnet is valid. */
1365                for (i = 0; i < pAd->ChannelListNum; i++) {
1366                        if ((Channel == pAd->ChannelList[i].Channel)
1367                            && (pAd->ChannelList[i].RemainingTimeForUse == 0)) {
1368                                /* found radar signal in the channel. the channel can't use at least for 30 minutes. */
1369                                pAd->ChannelList[i].RemainingTimeForUse = 1800; /*30 min = 1800 sec */
1370                                Result = TRUE;
1371                                break;
1372                        }
1373                }
1374        } while (FALSE);
1375
1376        return Result;
1377}
1378
1379void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd,
1380                            u8 *pRA,
1381                            u8 *pTA, u8 ChSwMode, u8 Channel)
1382{
1383}
1384
1385static void StartDFSProcedure(struct rt_rtmp_adapter *pAd,
1386                              u8 Channel, u8 ChSwMode)
1387{
1388        /* start DFS procedure */
1389        pAd->CommonCfg.Channel = Channel;
1390
1391        N_ChannelCheck(pAd);
1392
1393        pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1394        pAd->CommonCfg.RadarDetect.CSCount = 0;
1395}
1396
1397/*
1398        ==========================================================================
1399        Description:
1400                Channel Switch Announcement action frame sanity check.
1401
1402        Parametrs:
1403                1. MLME message containing the received frame
1404                2. message length.
1405                3. Channel switch announcement infomation buffer.
1406
1407        Return  : None.
1408        ==========================================================================
1409 */
1410
1411/*
1412  Channel Switch Announcement IE.
1413  +----+-----+-----------+------------+-----------+
1414  | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1415  +----+-----+-----------+------------+-----------+
1416    1    1        1           1            1
1417*/
1418static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd,
1419                                 void * pMsg,
1420                                 unsigned long MsgLen,
1421                                 struct rt_ch_sw_ann_info * pChSwAnnInfo)
1422{
1423        struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1424        u8 *pFramePtr = Fr->Octet;
1425        BOOLEAN result = FALSE;
1426        struct rt_eid * eid_ptr;
1427
1428        /* skip 802.11 header. */
1429        MsgLen -= sizeof(struct rt_header_802_11);
1430
1431        /* skip category and action code. */
1432        pFramePtr += 2;
1433        MsgLen -= 2;
1434
1435        if (pChSwAnnInfo == NULL)
1436                return result;
1437
1438        eid_ptr = (struct rt_eid *) pFramePtr;
1439        while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1440               ((u8 *)pFramePtr + MsgLen)) {
1441                switch (eid_ptr->Eid) {
1442                case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1443                        NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet,
1444                                       1);
1445                        NdisMoveMemory(&pChSwAnnInfo->Channel,
1446                                       eid_ptr->Octet + 1, 1);
1447                        NdisMoveMemory(&pChSwAnnInfo->ChSwCnt,
1448                                       eid_ptr->Octet + 2, 1);
1449
1450                        result = TRUE;
1451                        break;
1452
1453                default:
1454                        break;
1455                }
1456                eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1457        }
1458
1459        return result;
1460}
1461
1462/*
1463        ==========================================================================
1464        Description:
1465                Measurement request action frame sanity check.
1466
1467        Parametrs:
1468                1. MLME message containing the received frame
1469                2. message length.
1470                3. Measurement request infomation buffer.
1471
1472        Return  : None.
1473        ==========================================================================
1474 */
1475static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd,
1476                                    void * pMsg,
1477                                    unsigned long MsgLen,
1478                                    u8 *pDialogToken,
1479                                    struct rt_measure_req_info * pMeasureReqInfo,
1480                                    struct rt_measure_req * pMeasureReq)
1481{
1482        struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1483        u8 *pFramePtr = Fr->Octet;
1484        BOOLEAN result = FALSE;
1485        struct rt_eid * eid_ptr;
1486        u8 *ptr;
1487        u64 MeasureStartTime;
1488        u16 MeasureDuration;
1489
1490        /* skip 802.11 header. */
1491        MsgLen -= sizeof(struct rt_header_802_11);
1492
1493        /* skip category and action code. */
1494        pFramePtr += 2;
1495        MsgLen -= 2;
1496
1497        if (pMeasureReqInfo == NULL)
1498                return result;
1499
1500        NdisMoveMemory(pDialogToken, pFramePtr, 1);
1501        pFramePtr += 1;
1502        MsgLen -= 1;
1503
1504        eid_ptr = (struct rt_eid *) pFramePtr;
1505        while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1506               ((u8 *)pFramePtr + MsgLen)) {
1507                switch (eid_ptr->Eid) {
1508                case IE_MEASUREMENT_REQUEST:
1509                        NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet,
1510                                       1);
1511                        NdisMoveMemory(&pMeasureReqInfo->ReqMode.word,
1512                                       eid_ptr->Octet + 1, 1);
1513                        NdisMoveMemory(&pMeasureReqInfo->ReqType,
1514                                       eid_ptr->Octet + 2, 1);
1515                        ptr = (u8 *)(eid_ptr->Octet + 3);
1516                        NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1517                        NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1518                        pMeasureReq->MeasureStartTime =
1519                            SWAP64(MeasureStartTime);
1520                        NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1521                        pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
1522
1523                        result = TRUE;
1524                        break;
1525
1526                default:
1527                        break;
1528                }
1529                eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1530        }
1531
1532        return result;
1533}
1534
1535/*
1536        ==========================================================================
1537        Description:
1538                Measurement report action frame sanity check.
1539
1540        Parametrs:
1541                1. MLME message containing the received frame
1542                2. message length.
1543                3. Measurement report infomation buffer.
1544                4. basic report infomation buffer.
1545
1546        Return  : None.
1547        ==========================================================================
1548 */
1549
1550/*
1551  Measurement Report IE.
1552  +----+-----+-------+-------------+--------------+----------------+
1553  | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1554  +----+-----+-------+-------------+--------------+----------------+
1555    1     1      1          1             1            variable
1556
1557  Basic Report.
1558  +--------+------------+----------+-----+
1559  | Ch Num | Start Time | Duration | Map |
1560  +--------+------------+----------+-----+
1561      1          8           2        1
1562
1563  Map Field Bit Format.
1564  +-----+---------------+---------------------+-------+------------+----------+
1565  | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1566  +-----+---------------+---------------------+-------+------------+----------+
1567     0          1                  2              3         4          5-7
1568*/
1569static BOOLEAN PeerMeasureReportSanity(struct rt_rtmp_adapter *pAd,
1570                                       void * pMsg,
1571                                       unsigned long MsgLen,
1572                                       u8 *pDialogToken,
1573                                       struct rt_measure_report_info *
1574                                       pMeasureReportInfo,
1575                                       u8 *pReportBuf)
1576{
1577        struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1578        u8 *pFramePtr = Fr->Octet;
1579        BOOLEAN result = FALSE;
1580        struct rt_eid * eid_ptr;
1581        u8 *ptr;
1582
1583        /* skip 802.11 header. */
1584        MsgLen -= sizeof(struct rt_header_802_11);
1585
1586        /* skip category and action code. */
1587        pFramePtr += 2;
1588        MsgLen -= 2;
1589
1590        if (pMeasureReportInfo == NULL)
1591                return result;
1592
1593        NdisMoveMemory(pDialogToken, pFramePtr, 1);
1594        pFramePtr += 1;
1595        MsgLen -= 1;
1596
1597        eid_ptr = (struct rt_eid *) pFramePtr;
1598        while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1599               ((u8 *)pFramePtr + MsgLen)) {
1600                switch (eid_ptr->Eid) {
1601                case IE_MEASUREMENT_REPORT:
1602                        NdisMoveMemory(&pMeasureReportInfo->Token,
1603                                       eid_ptr->Octet, 1);
1604                        NdisMoveMemory(&pMeasureReportInfo->ReportMode,
1605                                       eid_ptr->Octet + 1, 1);
1606                        NdisMoveMemory(&pMeasureReportInfo->ReportType,
1607                                       eid_ptr->Octet + 2, 1);
1608                        if (pMeasureReportInfo->ReportType == RM_BASIC) {
1609                                struct rt_measure_basic_report * pReport =
1610                                    (struct rt_measure_basic_report *) pReportBuf;
1611                                ptr = (u8 *)(eid_ptr->Octet + 3);
1612                                NdisMoveMemory(&pReport->ChNum, ptr, 1);
1613                                NdisMoveMemory(&pReport->MeasureStartTime,
1614                                               ptr + 1, 8);
1615                                NdisMoveMemory(&pReport->MeasureDuration,
1616                                               ptr + 9, 2);
1617                                NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1618
1619                        } else if (pMeasureReportInfo->ReportType == RM_CCA) {
1620                                struct rt_measure_cca_report * pReport =
1621                                    (struct rt_measure_cca_report *) pReportBuf;
1622                                ptr = (u8 *)(eid_ptr->Octet + 3);
1623                                NdisMoveMemory(&pReport->ChNum, ptr, 1);
1624                                NdisMoveMemory(&pReport->MeasureStartTime,
1625                                               ptr + 1, 8);
1626                                NdisMoveMemory(&pReport->MeasureDuration,
1627                                               ptr + 9, 2);
1628                                NdisMoveMemory(&pReport->CCA_Busy_Fraction,
1629                                               ptr + 11, 1);
1630
1631                        } else if (pMeasureReportInfo->ReportType ==
1632                                   RM_RPI_HISTOGRAM) {
1633                                struct rt_measure_rpi_report * pReport =
1634                                    (struct rt_measure_rpi_report *) pReportBuf;
1635                                ptr = (u8 *)(eid_ptr->Octet + 3);
1636                                NdisMoveMemory(&pReport->ChNum, ptr, 1);
1637                                NdisMoveMemory(&pReport->MeasureStartTime,
1638                                               ptr + 1, 8);
1639                                NdisMoveMemory(&pReport->MeasureDuration,
1640                                               ptr + 9, 2);
1641                                NdisMoveMemory(&pReport->RPI_Density, ptr + 11,
1642                                               8);
1643                        }
1644                        result = TRUE;
1645                        break;
1646
1647                default:
1648                        break;
1649                }
1650                eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1651        }
1652
1653        return result;
1654}
1655
1656/*
1657        ==========================================================================
1658        Description:
1659                TPC Request action frame sanity check.
1660
1661        Parametrs:
1662                1. MLME message containing the received frame
1663                2. message length.
1664                3. Dialog Token.
1665
1666        Return  : None.
1667        ==========================================================================
1668 */
1669static BOOLEAN PeerTpcReqSanity(struct rt_rtmp_adapter *pAd,
1670                                void * pMsg,
1671                                unsigned long MsgLen, u8 *pDialogToken)
1672{
1673        struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1674        u8 *pFramePtr = Fr->Octet;
1675        BOOLEAN result = FALSE;
1676        struct rt_eid * eid_ptr;
1677
1678        MsgLen -= sizeof(struct rt_header_802_11);
1679
1680        /* skip category and action code. */
1681        pFramePtr += 2;
1682        MsgLen -= 2;
1683
1684        if (pDialogToken == NULL)
1685                return result;
1686
1687        NdisMoveMemory(pDialogToken, pFramePtr, 1);
1688        pFramePtr += 1;
1689        MsgLen -= 1;
1690
1691        eid_ptr = (struct rt_eid *) pFramePtr;
1692        while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1693               ((u8 *)pFramePtr + MsgLen)) {
1694                switch (eid_ptr->Eid) {
1695                case IE_TPC_REQUEST:
1696                        result = TRUE;
1697                        break;
1698
1699                default:
1700                        break;
1701                }
1702                eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1703        }
1704
1705        return result;
1706}
1707
1708/*
1709        ==========================================================================
1710        Description:
1711                TPC Report action frame sanity check.
1712
1713        Parametrs:
1714                1. MLME message containing the received frame
1715                2. message length.
1716                3. Dialog Token.
1717                4. TPC Report IE.
1718
1719        Return  : None.
1720        ==========================================================================
1721 */
1722static BOOLEAN PeerTpcRepSanity(struct rt_rtmp_adapter *pAd,
1723                                void * pMsg,
1724                                unsigned long MsgLen,
1725                                u8 *pDialogToken,
1726                                struct rt_tpc_report_info * pTpcRepInfo)
1727{
1728        struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1729        u8 *pFramePtr = Fr->Octet;
1730        BOOLEAN result = FALSE;
1731        struct rt_eid * eid_ptr;
1732
1733        MsgLen -= sizeof(struct rt_header_802_11);
1734
1735        /* skip category and action code. */
1736        pFramePtr += 2;
1737        MsgLen -= 2;
1738
1739        if (pDialogToken == NULL)
1740                return result;
1741
1742        NdisMoveMemory(pDialogToken, pFramePtr, 1);
1743        pFramePtr += 1;
1744        MsgLen -= 1;
1745
1746        eid_ptr = (struct rt_eid *) pFramePtr;
1747        while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1748               ((u8 *)pFramePtr + MsgLen)) {
1749                switch (eid_ptr->Eid) {
1750                case IE_TPC_REPORT:
1751                        NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1752                        NdisMoveMemory(&pTpcRepInfo->LinkMargin,
1753                                       eid_ptr->Octet + 1, 1);
1754                        result = TRUE;
1755                        break;
1756
1757                default:
1758                        break;
1759                }
1760                eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1761        }
1762
1763        return result;
1764}
1765
1766/*
1767        ==========================================================================
1768        Description:
1769                Channel Switch Announcement action frame handler.
1770
1771        Parametrs:
1772                Elme - MLME message containing the received frame
1773
1774        Return  : None.
1775        ==========================================================================
1776 */
1777static void PeerChSwAnnAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1778{
1779        struct rt_ch_sw_ann_info ChSwAnnInfo;
1780        struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1781        u8 index = 0, Channel = 0, NewChannel = 0;
1782        unsigned long Bssidx = 0;
1783
1784        NdisZeroMemory(&ChSwAnnInfo, sizeof(struct rt_ch_sw_ann_info));
1785        if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) {
1786                DBGPRINT(RT_DEBUG_TRACE,
1787                         ("Invalid Channel Switch Action Frame.\n"));
1788                return;
1789        }
1790
1791        if (pAd->OpMode == OPMODE_STA) {
1792                Bssidx =
1793                    BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3,
1794                                   pAd->CommonCfg.Channel);
1795                if (Bssidx == BSS_NOT_FOUND) {
1796                        DBGPRINT(RT_DEBUG_TRACE,
1797                                 ("PeerChSwAnnAction - Bssidx is not found\n"));
1798                        return;
1799                }
1800
1801                DBGPRINT(RT_DEBUG_TRACE,
1802                         ("\n****Bssidx is %d, Channel = %d\n", index,
1803                          pAd->ScanTab.BssEntry[Bssidx].Channel));
1804                hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6);
1805
1806                Channel = pAd->CommonCfg.Channel;
1807                NewChannel = ChSwAnnInfo.Channel;
1808
1809                if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0)
1810                    && (Channel != NewChannel)) {
1811                        /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */
1812                        /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */
1813                        AsicSwitchChannel(pAd, 1, FALSE);
1814                        AsicLockChannel(pAd, 1);
1815                        LinkDown(pAd, FALSE);
1816                        MlmeQueueInit(&pAd->Mlme.Queue);
1817                        BssTableInit(&pAd->ScanTab);
1818                        RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */
1819
1820                        /* channel sanity check */
1821                        for (index = 0; index < pAd->ChannelListNum; index++) {
1822                                if (pAd->ChannelList[index].Channel ==
1823                                    NewChannel) {
1824                                        pAd->ScanTab.BssEntry[Bssidx].Channel =
1825                                            NewChannel;
1826                                        pAd->CommonCfg.Channel = NewChannel;
1827                                        AsicSwitchChannel(pAd,
1828                                                          pAd->CommonCfg.
1829                                                          Channel, FALSE);
1830                                        AsicLockChannel(pAd,
1831                                                        pAd->CommonCfg.Channel);
1832                                        DBGPRINT(RT_DEBUG_TRACE,
1833                                                 ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n",
1834                                                  NewChannel));
1835                                        break;
1836                                }
1837                        }
1838
1839                        if (index >= pAd->ChannelListNum) {
1840                                DBGPRINT_ERR("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum);
1841                        }
1842                }
1843        }
1844
1845        return;
1846}
1847
1848/*
1849        ==========================================================================
1850        Description:
1851                Measurement Request action frame handler.
1852
1853        Parametrs:
1854                Elme - MLME message containing the received frame
1855
1856        Return  : None.
1857        ==========================================================================
1858 */
1859static void PeerMeasureReqAction(struct rt_rtmp_adapter *pAd,
1860                                 struct rt_mlme_queue_elem *Elem)
1861{
1862        struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1863        u8 DialogToken;
1864        struct rt_measure_req_info MeasureReqInfo;
1865        struct rt_measure_req MeasureReq;
1866        MEASURE_REPORT_MODE ReportMode;
1867
1868        if (PeerMeasureReqSanity
1869            (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo,
1870             &MeasureReq)) {
1871                ReportMode.word = 0;
1872                ReportMode.field.Incapable = 1;
1873                EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken,
1874                                      MeasureReqInfo.Token, ReportMode.word,
1875                                      MeasureReqInfo.ReqType, 0, NULL);
1876        }
1877
1878        return;
1879}
1880
1881/*
1882        ==========================================================================
1883        Description:
1884                Measurement Report action frame handler.
1885
1886        Parametrs:
1887                Elme - MLME message containing the received frame
1888
1889        Return  : None.
1890        ==========================================================================
1891 */
1892static void PeerMeasureReportAction(struct rt_rtmp_adapter *pAd,
1893                                    struct rt_mlme_queue_elem *Elem)
1894{
1895        struct rt_measure_report_info MeasureReportInfo;
1896        struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1897        u8 DialogToken;
1898        u8 *pMeasureReportInfo;
1899
1900/*      if (pAd->CommonCfg.bIEEE80211H != TRUE) */
1901/*              return; */
1902
1903        pMeasureReportInfo = kmalloc(sizeof(struct rt_measure_rpi_report), GFP_ATOMIC);
1904        if (pMeasureReportInfo == NULL) {
1905                DBGPRINT(RT_DEBUG_ERROR,
1906                         ("%s unable to alloc memory for measure report buffer (size=%zu).\n",
1907                          __func__, sizeof(struct rt_measure_rpi_report)));
1908                return;
1909        }
1910
1911        NdisZeroMemory(&MeasureReportInfo, sizeof(struct rt_measure_report_info));
1912        NdisZeroMemory(pMeasureReportInfo, sizeof(struct rt_measure_rpi_report));
1913        if (PeerMeasureReportSanity
1914            (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo,
1915             pMeasureReportInfo)) {
1916                do {
1917                        struct rt_measure_req_entry *pEntry = NULL;
1918
1919                        /* Not a autonomous measure report. */
1920                        /* check the dialog token field. drop it if the dialog token doesn't match. */
1921                        if ((DialogToken != 0)
1922                            && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) ==
1923                                NULL))
1924                                break;
1925
1926                        if (pEntry != NULL)
1927                                MeasureReqDelete(pAd, pEntry->DialogToken);
1928
1929                        if (MeasureReportInfo.ReportType == RM_BASIC) {
1930                                struct rt_measure_basic_report * pBasicReport =
1931                                    (struct rt_measure_basic_report *) pMeasureReportInfo;
1932                                if ((pBasicReport->Map.field.Radar)
1933                                    &&
1934                                    (DfsRequirementCheck
1935                                     (pAd, pBasicReport->ChNum) == TRUE)) {
1936                                        NotifyChSwAnnToPeerAPs(pAd,
1937                                                               pFr->Hdr.Addr1,
1938                                                               pFr->Hdr.Addr2,
1939                                                               1,
1940                                                               pBasicReport->
1941                                                               ChNum);
1942                                        StartDFSProcedure(pAd,
1943                                                          pBasicReport->ChNum,
1944                                                          1);
1945                                }
1946                        }
1947                } while (FALSE);
1948        } else
1949                DBGPRINT(RT_DEBUG_TRACE,
1950                         ("Invalid Measurement Report Frame.\n"));
1951
1952        kfree(pMeasureReportInfo);
1953
1954        return;
1955}
1956
1957/*
1958        ==========================================================================
1959        Description:
1960                TPC Request action frame handler.
1961
1962        Parametrs:
1963                Elme - MLME message containing the received frame
1964
1965        Return  : None.
1966        ==========================================================================
1967 */
1968static void PeerTpcReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1969{
1970        struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1971        u8 *pFramePtr = pFr->Octet;
1972        u8 DialogToken;
1973        u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1974        u8 LinkMargin = 0;
1975        char RealRssi;
1976
1977        /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */
1978        /*                              STA may incorporate rate information and channel conditions, including interference, into its computation */
1979        /*                              of link margin. */
1980
1981        RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1982                               ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1983                               ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1984
1985        /* skip Category and action code. */
1986        pFramePtr += 2;
1987
1988        /* Dialog token. */
1989        NdisMoveMemory(&DialogToken, pFramePtr, 1);
1990
1991        LinkMargin = (RealRssi / MIN_RCV_PWR);
1992        if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1993                EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr,
1994                              LinkMargin);
1995
1996        return;
1997}
1998
1999/*
2000        ==========================================================================
2001        Description:
2002                TPC Report action frame handler.
2003
2004        Parametrs:
2005                Elme - MLME message containing the received frame
2006
2007        Return  : None.
2008        ==========================================================================
2009 */
2010static void PeerTpcRepAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2011{
2012        u8 DialogToken;
2013        struct rt_tpc_report_info TpcRepInfo;
2014        struct rt_tpc_req_entry *pEntry = NULL;
2015
2016        NdisZeroMemory(&TpcRepInfo, sizeof(struct rt_tpc_report_info));
2017        if (PeerTpcRepSanity
2018            (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) {
2019                pEntry = TpcReqLookUp(pAd, DialogToken);
2020                if (pEntry != NULL) {
2021                        TpcReqDelete(pAd, pEntry->DialogToken);
2022                        DBGPRINT(RT_DEBUG_TRACE,
2023                                 ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
2024                                  __func__, DialogToken, TpcRepInfo.TxPwr,
2025                                  TpcRepInfo.LinkMargin));
2026                }
2027        }
2028
2029        return;
2030}
2031
2032/*
2033        ==========================================================================
2034        Description:
2035                Spectrun action frames Handler such as channel switch annoucement,
2036                measurement report, measurement request actions frames.
2037
2038        Parametrs:
2039                Elme - MLME message containing the received frame
2040
2041        Return  : None.
2042        ==========================================================================
2043 */
2044void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2045{
2046
2047        u8 Action = Elem->Msg[LENGTH_802_11 + 1];
2048
2049        if (pAd->CommonCfg.bIEEE80211H != TRUE)
2050                return;
2051
2052        switch (Action) {
2053        case SPEC_MRQ:
2054                /* current rt2860 unable do such measure specified in Measurement Request. */
2055                /* reject all measurement request. */
2056                PeerMeasureReqAction(pAd, Elem);
2057                break;
2058
2059        case SPEC_MRP:
2060                PeerMeasureReportAction(pAd, Elem);
2061                break;
2062
2063        case SPEC_TPCRQ:
2064                PeerTpcReqAction(pAd, Elem);
2065                break;
2066
2067        case SPEC_TPCRP:
2068                PeerTpcRepAction(pAd, Elem);
2069                break;
2070
2071        case SPEC_CHANNEL_SWITCH:
2072
2073                PeerChSwAnnAction(pAd, Elem);
2074                break;
2075        }
2076
2077        return;
2078}
2079
2080/*
2081        ==========================================================================
2082        Description:
2083
2084        Parametrs:
2085
2086        Return  : None.
2087        ==========================================================================
2088 */
2089int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2090{
2091        u32 Aid = 1;
2092        u32 ArgIdx;
2093        char *thisChar;
2094
2095        MEASURE_REQ_MODE MeasureReqMode;
2096        u8 MeasureReqToken = RandomByte(pAd);
2097        u8 MeasureReqType = RM_BASIC;
2098        u8 MeasureCh = 1;
2099        u64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2100        struct rt_measure_req MeasureReq;
2101        u8 TotalLen;
2102
2103        struct rt_header_802_11 ActHdr;
2104        u8 *pOutBuffer = NULL;
2105        int NStatus;
2106        unsigned long FrameLen;
2107
2108        NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
2109        if (NStatus != NDIS_STATUS_SUCCESS) {
2110                DBGPRINT(RT_DEBUG_TRACE,
2111                         ("%s() allocate memory failed \n", __func__));
2112                goto END_OF_MEASURE_REQ;
2113        }
2114
2115        ArgIdx = 1;
2116        while ((thisChar = strsep((char **)&arg, "-")) != NULL) {
2117                switch (ArgIdx) {
2118                case 1: /* Aid. */
2119                        Aid = (u8)simple_strtol(thisChar, 0, 16);
2120                        break;
2121
2122                case 2: /* Measurement Request Type. */
2123                        MeasureReqType = simple_strtol(thisChar, 0, 16);
2124                        if (MeasureReqType > 3) {
2125                                DBGPRINT(RT_DEBUG_ERROR,
2126                                         ("%s: unknow MeasureReqType(%d)\n",
2127                                          __func__, MeasureReqType));
2128                                goto END_OF_MEASURE_REQ;
2129                        }
2130                        break;
2131
2132                case 3: /* Measurement channel. */
2133                        MeasureCh = (u8)simple_strtol(thisChar, 0, 16);
2134                        break;
2135                }
2136                ArgIdx++;
2137        }
2138
2139        DBGPRINT(RT_DEBUG_TRACE,
2140                 ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__,
2141                  Aid, MeasureReqType, MeasureCh));
2142        if (!VALID_WCID(Aid)) {
2143                DBGPRINT(RT_DEBUG_ERROR,
2144                         ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2145                goto END_OF_MEASURE_REQ;
2146        }
2147
2148        MeasureReqMode.word = 0;
2149        MeasureReqMode.field.Enable = 1;
2150
2151        MeasureReqInsert(pAd, MeasureReqToken);
2152
2153        /* build action frame header. */
2154        MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0,
2155                         pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress);
2156
2157        NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
2158        FrameLen = sizeof(struct rt_header_802_11);
2159
2160        TotalLen = sizeof(struct rt_measure_req_info) + sizeof(struct rt_measure_req);
2161
2162        MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2163                                sizeof(struct rt_measure_req_info), CATEGORY_RM, RM_BASIC,
2164                                MeasureReqToken, MeasureReqMode.word,
2165                                MeasureReqType, 0);
2166
2167        MeasureReq.ChNum = MeasureCh;
2168        MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2169        MeasureReq.MeasureDuration = cpu2le16(2000);
2170
2171        {
2172                unsigned long TempLen;
2173                MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
2174                                  sizeof(struct rt_measure_req), &MeasureReq,
2175                                  END_OF_ARGS);
2176                FrameLen += TempLen;
2177        }
2178
2179        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen);
2180
2181END_OF_MEASURE_REQ:
2182        MlmeFreeMemory(pAd, pOutBuffer);
2183
2184        return TRUE;
2185}
2186
2187int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2188{
2189        u32 Aid;
2190
2191        u8 TpcReqToken = RandomByte(pAd);
2192
2193        Aid = (u32)simple_strtol(arg, 0, 16);
2194
2195        DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
2196        if (!VALID_WCID(Aid)) {
2197                DBGPRINT(RT_DEBUG_ERROR,
2198                         ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2199                return TRUE;
2200        }
2201
2202        TpcReqInsert(pAd, TpcReqToken);
2203
2204        EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
2205
2206        return TRUE;
2207}
2208