linux/drivers/staging/rt2860/common/mlme.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        mlme.c
  29
  30        Abstract:
  31
  32        Revision History:
  33        Who                     When                    What
  34        --------        ----------              ----------------------------------------------
  35        John Chang      2004-08-25              Modify from RT2500 code base
  36        John Chang      2004-09-06              modified for RT2600
  37*/
  38
  39#include "../rt_config.h"
  40#include <stdarg.h>
  41#include <linux/kernel.h>
  42
  43u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 };
  44
  45u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
  46u8 RSN_OUI[] = { 0x00, 0x0f, 0xac };
  47u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
  48u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
  49u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 };
  50u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 };
  51u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c };
  52u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
  53u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c };
  54
  55u8 RateSwitchTable[] = {
  56/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
  57        0x11, 0x00, 0, 0, 0,    /* Initial used item after association */
  58        0x00, 0x00, 0, 40, 101,
  59        0x01, 0x00, 1, 40, 50,
  60        0x02, 0x00, 2, 35, 45,
  61        0x03, 0x00, 3, 20, 45,
  62        0x04, 0x21, 0, 30, 50,
  63        0x05, 0x21, 1, 20, 50,
  64        0x06, 0x21, 2, 20, 50,
  65        0x07, 0x21, 3, 15, 50,
  66        0x08, 0x21, 4, 15, 30,
  67        0x09, 0x21, 5, 10, 25,
  68        0x0a, 0x21, 6, 8, 25,
  69        0x0b, 0x21, 7, 8, 25,
  70        0x0c, 0x20, 12, 15, 30,
  71        0x0d, 0x20, 13, 8, 20,
  72        0x0e, 0x20, 14, 8, 20,
  73        0x0f, 0x20, 15, 8, 25,
  74        0x10, 0x22, 15, 8, 25,
  75        0x11, 0x00, 0, 0, 0,
  76        0x12, 0x00, 0, 0, 0,
  77        0x13, 0x00, 0, 0, 0,
  78        0x14, 0x00, 0, 0, 0,
  79        0x15, 0x00, 0, 0, 0,
  80        0x16, 0x00, 0, 0, 0,
  81        0x17, 0x00, 0, 0, 0,
  82        0x18, 0x00, 0, 0, 0,
  83        0x19, 0x00, 0, 0, 0,
  84        0x1a, 0x00, 0, 0, 0,
  85        0x1b, 0x00, 0, 0, 0,
  86        0x1c, 0x00, 0, 0, 0,
  87        0x1d, 0x00, 0, 0, 0,
  88        0x1e, 0x00, 0, 0, 0,
  89        0x1f, 0x00, 0, 0, 0,
  90};
  91
  92u8 RateSwitchTable11B[] = {
  93/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
  94        0x04, 0x03, 0, 0, 0,    /* Initial used item after association */
  95        0x00, 0x00, 0, 40, 101,
  96        0x01, 0x00, 1, 40, 50,
  97        0x02, 0x00, 2, 35, 45,
  98        0x03, 0x00, 3, 20, 45,
  99};
 100
 101u8 RateSwitchTable11BG[] = {
 102/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 103        0x0a, 0x00, 0, 0, 0,    /* Initial used item after association */
 104        0x00, 0x00, 0, 40, 101,
 105        0x01, 0x00, 1, 40, 50,
 106        0x02, 0x00, 2, 35, 45,
 107        0x03, 0x00, 3, 20, 45,
 108        0x04, 0x10, 2, 20, 35,
 109        0x05, 0x10, 3, 16, 35,
 110        0x06, 0x10, 4, 10, 25,
 111        0x07, 0x10, 5, 16, 25,
 112        0x08, 0x10, 6, 10, 25,
 113        0x09, 0x10, 7, 10, 13,
 114};
 115
 116u8 RateSwitchTable11G[] = {
 117/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 118        0x08, 0x00, 0, 0, 0,    /* Initial used item after association */
 119        0x00, 0x10, 0, 20, 101,
 120        0x01, 0x10, 1, 20, 35,
 121        0x02, 0x10, 2, 20, 35,
 122        0x03, 0x10, 3, 16, 35,
 123        0x04, 0x10, 4, 10, 25,
 124        0x05, 0x10, 5, 16, 25,
 125        0x06, 0x10, 6, 10, 25,
 126        0x07, 0x10, 7, 10, 13,
 127};
 128
 129u8 RateSwitchTable11N1S[] = {
 130/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 131        0x0c, 0x0a, 0, 0, 0,    /* Initial used item after association */
 132        0x00, 0x00, 0, 40, 101,
 133        0x01, 0x00, 1, 40, 50,
 134        0x02, 0x00, 2, 25, 45,
 135        0x03, 0x21, 0, 20, 35,
 136        0x04, 0x21, 1, 20, 35,
 137        0x05, 0x21, 2, 20, 35,
 138        0x06, 0x21, 3, 15, 35,
 139        0x07, 0x21, 4, 15, 30,
 140        0x08, 0x21, 5, 10, 25,
 141        0x09, 0x21, 6, 8, 14,
 142        0x0a, 0x21, 7, 8, 14,
 143        0x0b, 0x23, 7, 8, 14,
 144};
 145
 146u8 RateSwitchTable11N2S[] = {
 147/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 148        0x0e, 0x0c, 0, 0, 0,    /* Initial used item after association */
 149        0x00, 0x00, 0, 40, 101,
 150        0x01, 0x00, 1, 40, 50,
 151        0x02, 0x00, 2, 25, 45,
 152        0x03, 0x21, 0, 20, 35,
 153        0x04, 0x21, 1, 20, 35,
 154        0x05, 0x21, 2, 20, 35,
 155        0x06, 0x21, 3, 15, 35,
 156        0x07, 0x21, 4, 15, 30,
 157        0x08, 0x20, 11, 15, 30,
 158        0x09, 0x20, 12, 15, 30,
 159        0x0a, 0x20, 13, 8, 20,
 160        0x0b, 0x20, 14, 8, 20,
 161        0x0c, 0x20, 15, 8, 25,
 162        0x0d, 0x22, 15, 8, 15,
 163};
 164
 165u8 RateSwitchTable11N3S[] = {
 166/* Item No.     Mode    Curr-MCS        TrainUp TrainDown       // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 167        0x0b, 0x00, 0, 0, 0,    /* 0x0a, 0x00,  0,  0,  0,      // Initial used item after association */
 168        0x00, 0x21, 0, 30, 101,
 169        0x01, 0x21, 1, 20, 50,
 170        0x02, 0x21, 2, 20, 50,
 171        0x03, 0x21, 3, 15, 50,
 172        0x04, 0x21, 4, 15, 30,
 173        0x05, 0x20, 11, 15, 30, /* Required by System-Alan @ 20080812 */
 174        0x06, 0x20, 12, 15, 30, /* 0x05, 0x20, 12, 15, 30, */
 175        0x07, 0x20, 13, 8, 20,  /* 0x06, 0x20, 13,  8, 20, */
 176        0x08, 0x20, 14, 8, 20,  /* 0x07, 0x20, 14,  8, 20, */
 177        0x09, 0x20, 15, 8, 25,  /* 0x08, 0x20, 15,  8, 25, */
 178        0x0a, 0x22, 15, 8, 25,  /* 0x09, 0x22, 15,  8, 25, */
 179};
 180
 181u8 RateSwitchTable11N2SForABand[] = {
 182/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 183        0x0b, 0x09, 0, 0, 0,    /* Initial used item after association */
 184        0x00, 0x21, 0, 30, 101,
 185        0x01, 0x21, 1, 20, 50,
 186        0x02, 0x21, 2, 20, 50,
 187        0x03, 0x21, 3, 15, 50,
 188        0x04, 0x21, 4, 15, 30,
 189        0x05, 0x21, 5, 15, 30,
 190        0x06, 0x20, 12, 15, 30,
 191        0x07, 0x20, 13, 8, 20,
 192        0x08, 0x20, 14, 8, 20,
 193        0x09, 0x20, 15, 8, 25,
 194        0x0a, 0x22, 15, 8, 25,
 195};
 196
 197u8 RateSwitchTable11N3SForABand[] = {   /* 3*3 */
 198/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 199        0x0b, 0x09, 0, 0, 0,    /* Initial used item after association */
 200        0x00, 0x21, 0, 30, 101,
 201        0x01, 0x21, 1, 20, 50,
 202        0x02, 0x21, 2, 20, 50,
 203        0x03, 0x21, 3, 15, 50,
 204        0x04, 0x21, 4, 15, 30,
 205        0x05, 0x21, 5, 15, 30,
 206        0x06, 0x20, 12, 15, 30,
 207        0x07, 0x20, 13, 8, 20,
 208        0x08, 0x20, 14, 8, 20,
 209        0x09, 0x20, 15, 8, 25,
 210        0x0a, 0x22, 15, 8, 25,
 211};
 212
 213u8 RateSwitchTable11BGN1S[] = {
 214/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 215        0x0c, 0x0a, 0, 0, 0,    /* Initial used item after association */
 216        0x00, 0x00, 0, 40, 101,
 217        0x01, 0x00, 1, 40, 50,
 218        0x02, 0x00, 2, 25, 45,
 219        0x03, 0x21, 0, 20, 35,
 220        0x04, 0x21, 1, 20, 35,
 221        0x05, 0x21, 2, 20, 35,
 222        0x06, 0x21, 3, 15, 35,
 223        0x07, 0x21, 4, 15, 30,
 224        0x08, 0x21, 5, 10, 25,
 225        0x09, 0x21, 6, 8, 14,
 226        0x0a, 0x21, 7, 8, 14,
 227        0x0b, 0x23, 7, 8, 14,
 228};
 229
 230u8 RateSwitchTable11BGN2S[] = {
 231/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 232        0x0e, 0x0c, 0, 0, 0,    /* Initial used item after association */
 233        0x00, 0x00, 0, 40, 101,
 234        0x01, 0x00, 1, 40, 50,
 235        0x02, 0x00, 2, 25, 45,
 236        0x03, 0x21, 0, 20, 35,
 237        0x04, 0x21, 1, 20, 35,
 238        0x05, 0x21, 2, 20, 35,
 239        0x06, 0x21, 3, 15, 35,
 240        0x07, 0x21, 4, 15, 30,
 241        0x08, 0x20, 11, 15, 30,
 242        0x09, 0x20, 12, 15, 30,
 243        0x0a, 0x20, 13, 8, 20,
 244        0x0b, 0x20, 14, 8, 20,
 245        0x0c, 0x20, 15, 8, 25,
 246        0x0d, 0x22, 15, 8, 15,
 247};
 248
 249u8 RateSwitchTable11BGN3S[] = { /* 3*3 */
 250/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 251        0x0a, 0x00, 0, 0, 0,    /* Initial used item after association */
 252        0x00, 0x21, 0, 30, 101, /*50 */
 253        0x01, 0x21, 1, 20, 50,
 254        0x02, 0x21, 2, 20, 50,
 255        0x03, 0x21, 3, 20, 50,
 256        0x04, 0x21, 4, 15, 50,
 257        0x05, 0x20, 20, 15, 30,
 258        0x06, 0x20, 21, 8, 20,
 259        0x07, 0x20, 22, 8, 20,
 260        0x08, 0x20, 23, 8, 25,
 261        0x09, 0x22, 23, 8, 25,
 262};
 263
 264u8 RateSwitchTable11BGN2SForABand[] = {
 265/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 266        0x0b, 0x09, 0, 0, 0,    /* Initial used item after association */
 267        0x00, 0x21, 0, 30, 101, /*50 */
 268        0x01, 0x21, 1, 20, 50,
 269        0x02, 0x21, 2, 20, 50,
 270        0x03, 0x21, 3, 15, 50,
 271        0x04, 0x21, 4, 15, 30,
 272        0x05, 0x21, 5, 15, 30,
 273        0x06, 0x20, 12, 15, 30,
 274        0x07, 0x20, 13, 8, 20,
 275        0x08, 0x20, 14, 8, 20,
 276        0x09, 0x20, 15, 8, 25,
 277        0x0a, 0x22, 15, 8, 25,
 278};
 279
 280u8 RateSwitchTable11BGN3SForABand[] = { /* 3*3 */
 281/* Item No.   Mode   Curr-MCS   TrainUp   TrainDown             // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
 282        0x0c, 0x09, 0, 0, 0,    /* Initial used item after association */
 283        0x00, 0x21, 0, 30, 101, /*50 */
 284        0x01, 0x21, 1, 20, 50,
 285        0x02, 0x21, 2, 20, 50,
 286        0x03, 0x21, 3, 15, 50,
 287        0x04, 0x21, 4, 15, 30,
 288        0x05, 0x21, 5, 15, 30,
 289        0x06, 0x21, 12, 15, 30,
 290        0x07, 0x20, 20, 15, 30,
 291        0x08, 0x20, 21, 8, 20,
 292        0x09, 0x20, 22, 8, 20,
 293        0x0a, 0x20, 23, 8, 25,
 294        0x0b, 0x22, 23, 8, 25,
 295};
 296
 297extern u8 OfdmRateToRxwiMCS[];
 298/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */
 299/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */
 300unsigned long BasicRateMask[12] =
 301    { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ ,
 3020xfffff00f /* 11 */ ,
 303        0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ ,
 304            0xfffff0ff /* 18 */ ,
 305        0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ ,
 306            0xffffffff /* 54 */
 307};
 308
 309u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 310u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 311
 312/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */
 313/*              this value, then it's quaranteed capable of operating in 36 mbps TX rate in */
 314/*              clean environment. */
 315/*                                                                TxRate: 1   2   5.5   11       6        9    12       18       24   36   48   54       72  100 */
 316char RssiSafeLevelForTxRate[] =
 317    { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
 318
 319u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
 320u16 RateIdTo500Kbps[] =
 321    { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
 322
 323u8 SsidIe = IE_SSID;
 324u8 SupRateIe = IE_SUPP_RATES;
 325u8 ExtRateIe = IE_EXT_SUPP_RATES;
 326u8 HtCapIe = IE_HT_CAP;
 327u8 AddHtInfoIe = IE_ADD_HT;
 328u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET;
 329u8 ErpIe = IE_ERP;
 330u8 DsIe = IE_DS_PARM;
 331u8 TimIe = IE_TIM;
 332u8 WpaIe = IE_WPA;
 333u8 Wpa2Ie = IE_WPA2;
 334u8 IbssIe = IE_IBSS_PARM;
 335
 336extern u8 WPA_OUI[];
 337
 338u8 SES_OUI[] = { 0x00, 0x90, 0x4c };
 339
 340u8 ZeroSsid[32] =
 341    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 3420x00, 0x00, 0x00, 0x00,
 343        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 344            0x00, 0x00, 0x00, 0x00
 345};
 346
 347/*
 348        ==========================================================================
 349        Description:
 350                initialize the MLME task and its data structure (queue, spinlock,
 351                timer, state machines).
 352
 353        IRQL = PASSIVE_LEVEL
 354
 355        Return:
 356                always return NDIS_STATUS_SUCCESS
 357
 358        ==========================================================================
 359*/
 360int MlmeInit(struct rt_rtmp_adapter *pAd)
 361{
 362        int Status = NDIS_STATUS_SUCCESS;
 363
 364        DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
 365
 366        do {
 367                Status = MlmeQueueInit(&pAd->Mlme.Queue);
 368                if (Status != NDIS_STATUS_SUCCESS)
 369                        break;
 370
 371                pAd->Mlme.bRunning = FALSE;
 372                NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
 373
 374                {
 375                        BssTableInit(&pAd->ScanTab);
 376
 377                        /* init STA state machines */
 378                        AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine,
 379                                              pAd->Mlme.AssocFunc);
 380                        AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine,
 381                                             pAd->Mlme.AuthFunc);
 382                        AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine,
 383                                                pAd->Mlme.AuthRspFunc);
 384                        SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine,
 385                                             pAd->Mlme.SyncFunc);
 386
 387                        /* Since we are using switch/case to implement it, the init is different from the above */
 388                        /* state machine init */
 389                        MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
 390                }
 391
 392                WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine,
 393                                    pAd->Mlme.WpaFunc);
 394
 395                ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine,
 396                                       pAd->Mlme.ActFunc);
 397
 398                /* Init mlme periodic timer */
 399                RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer,
 400                              GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
 401
 402                /* Set mlme periodic timer */
 403                RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
 404
 405                /* software-based RX Antenna diversity */
 406                RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer,
 407                              GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd,
 408                              FALSE);
 409
 410                {
 411#ifdef RTMP_PCI_SUPPORT
 412                        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
 413                                /* only PCIe cards need these two timers */
 414                                RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer,
 415                                              GET_TIMER_FUNCTION
 416                                              (PsPollWakeExec), pAd, FALSE);
 417                                RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer,
 418                                              GET_TIMER_FUNCTION(RadioOnExec),
 419                                              pAd, FALSE);
 420                        }
 421#endif /* RTMP_PCI_SUPPORT // */
 422
 423                        RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer,
 424                                      GET_TIMER_FUNCTION(LinkDownExec), pAd,
 425                                      FALSE);
 426
 427#ifdef RTMP_MAC_USB
 428                        RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer,
 429                                      GET_TIMER_FUNCTION
 430                                      (RtmpUsbStaAsicForceWakeupTimeout), pAd,
 431                                      FALSE);
 432                        pAd->Mlme.AutoWakeupTimerRunning = FALSE;
 433#endif /* RTMP_MAC_USB // */
 434                }
 435
 436        } while (FALSE);
 437
 438        DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
 439
 440        return Status;
 441}
 442
 443/*
 444        ==========================================================================
 445        Description:
 446                main loop of the MLME
 447        Pre:
 448                Mlme has to be initialized, and there are something inside the queue
 449        Note:
 450                This function is invoked from MPSetInformation and MPReceive;
 451                This task guarantee only one MlmeHandler will run.
 452
 453        IRQL = DISPATCH_LEVEL
 454
 455        ==========================================================================
 456 */
 457void MlmeHandler(struct rt_rtmp_adapter *pAd)
 458{
 459        struct rt_mlme_queue_elem *Elem = NULL;
 460
 461        /* Only accept MLME and Frame from peer side, no other (control/data) frame should */
 462        /* get into this state machine */
 463
 464        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
 465        if (pAd->Mlme.bRunning) {
 466                NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
 467                return;
 468        } else {
 469                pAd->Mlme.bRunning = TRUE;
 470        }
 471        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
 472
 473        while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
 474                if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
 475                    RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
 476                    RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
 477                        DBGPRINT(RT_DEBUG_TRACE,
 478                                 ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n",
 479                                  pAd->Mlme.Queue.Num));
 480                        break;
 481                }
 482                /*From message type, determine which state machine I should drive */
 483                if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
 484#ifdef RTMP_MAC_USB
 485                        if (Elem->MsgType == MT2_RESET_CONF) {
 486                                DBGPRINT_RAW(RT_DEBUG_TRACE,
 487                                             ("reset MLME state machine!\n"));
 488                                MlmeRestartStateMachine(pAd);
 489                                Elem->Occupied = FALSE;
 490                                Elem->MsgLen = 0;
 491                                continue;
 492                        }
 493#endif /* RTMP_MAC_USB // */
 494
 495                        /* if dequeue success */
 496                        switch (Elem->Machine) {
 497                                /* STA state machines */
 498                        case ASSOC_STATE_MACHINE:
 499                                StateMachinePerformAction(pAd,
 500                                                          &pAd->Mlme.
 501                                                          AssocMachine, Elem);
 502                                break;
 503                        case AUTH_STATE_MACHINE:
 504                                StateMachinePerformAction(pAd,
 505                                                          &pAd->Mlme.
 506                                                          AuthMachine, Elem);
 507                                break;
 508                        case AUTH_RSP_STATE_MACHINE:
 509                                StateMachinePerformAction(pAd,
 510                                                          &pAd->Mlme.
 511                                                          AuthRspMachine, Elem);
 512                                break;
 513                        case SYNC_STATE_MACHINE:
 514                                StateMachinePerformAction(pAd,
 515                                                          &pAd->Mlme.
 516                                                          SyncMachine, Elem);
 517                                break;
 518                        case MLME_CNTL_STATE_MACHINE:
 519                                MlmeCntlMachinePerformAction(pAd,
 520                                                             &pAd->Mlme.
 521                                                             CntlMachine, Elem);
 522                                break;
 523                        case WPA_PSK_STATE_MACHINE:
 524                                StateMachinePerformAction(pAd,
 525                                                          &pAd->Mlme.
 526                                                          WpaPskMachine, Elem);
 527                                break;
 528
 529                        case ACTION_STATE_MACHINE:
 530                                StateMachinePerformAction(pAd,
 531                                                          &pAd->Mlme.ActMachine,
 532                                                          Elem);
 533                                break;
 534
 535                        case WPA_STATE_MACHINE:
 536                                StateMachinePerformAction(pAd,
 537                                                          &pAd->Mlme.WpaMachine,
 538                                                          Elem);
 539                                break;
 540
 541                        default:
 542                                DBGPRINT(RT_DEBUG_TRACE,
 543                                         ("ERROR: Illegal machine %ld in MlmeHandler()\n",
 544                                          Elem->Machine));
 545                                break;
 546                        }       /* end of switch */
 547
 548                        /* free MLME element */
 549                        Elem->Occupied = FALSE;
 550                        Elem->MsgLen = 0;
 551
 552                } else {
 553                        DBGPRINT_ERR("MlmeHandler: MlmeQueue empty\n");
 554                }
 555        }
 556
 557        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
 558        pAd->Mlme.bRunning = FALSE;
 559        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
 560}
 561
 562/*
 563        ==========================================================================
 564        Description:
 565                Destructor of MLME (Destroy queue, state machine, spin lock and timer)
 566        Parameters:
 567                Adapter - NIC Adapter pointer
 568        Post:
 569                The MLME task will no longer work properly
 570
 571        IRQL = PASSIVE_LEVEL
 572
 573        ==========================================================================
 574 */
 575void MlmeHalt(struct rt_rtmp_adapter *pAd)
 576{
 577        BOOLEAN Cancelled;
 578
 579        DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
 580
 581        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
 582                /* disable BEACON generation and other BEACON related hardware timers */
 583                AsicDisableSync(pAd);
 584        }
 585
 586        {
 587                /* Cancel pending timers */
 588                RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
 589                RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
 590                RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
 591                RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
 592                RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
 593                RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
 594
 595#ifdef RTMP_MAC_PCI
 596                if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
 597                    && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) {
 598                        RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
 599                        RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
 600                }
 601#endif /* RTMP_MAC_PCI // */
 602
 603                RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
 604
 605#ifdef RTMP_MAC_USB
 606                RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
 607#endif /* RTMP_MAC_USB // */
 608        }
 609
 610        RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
 611        RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
 612
 613        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
 614                struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps;
 615
 616                /* Set LED */
 617                RTMPSetLED(pAd, LED_HALT);
 618                RTMPSetSignalLED(pAd, -100);    /* Force signal strength Led to be turned off, firmware is not done it. */
 619#ifdef RTMP_MAC_USB
 620                {
 621                        LED_CFG_STRUC LedCfg;
 622                        RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
 623                        LedCfg.field.LedPolar = 0;
 624                        LedCfg.field.RLedMode = 0;
 625                        LedCfg.field.GLedMode = 0;
 626                        LedCfg.field.YLedMode = 0;
 627                        RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
 628                }
 629#endif /* RTMP_MAC_USB // */
 630
 631                if (pChipOps->AsicHaltAction)
 632                        pChipOps->AsicHaltAction(pAd);
 633        }
 634
 635        RTMPusecDelay(5000);    /*  5 msec to guarantee Ant Diversity timer canceled */
 636
 637        MlmeQueueDestroy(&pAd->Mlme.Queue);
 638        NdisFreeSpinLock(&pAd->Mlme.TaskLock);
 639
 640        DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
 641}
 642
 643void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd)
 644{
 645        pAd->RalinkCounters.LastOneSecRxOkDataCnt =
 646            pAd->RalinkCounters.OneSecRxOkDataCnt;
 647        /* clear all OneSecxxx counters. */
 648        pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
 649        pAd->RalinkCounters.OneSecFalseCCACnt = 0;
 650        pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
 651        pAd->RalinkCounters.OneSecRxOkCnt = 0;
 652        pAd->RalinkCounters.OneSecTxFailCount = 0;
 653        pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
 654        pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
 655        pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
 656        pAd->RalinkCounters.OneSecReceivedByteCount = 0;
 657        pAd->RalinkCounters.OneSecTransmittedByteCount = 0;
 658
 659        /* TODO: for debug only. to be removed */
 660        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
 661        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
 662        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
 663        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
 664        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
 665        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
 666        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
 667        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
 668        pAd->RalinkCounters.OneSecTxDoneCount = 0;
 669        pAd->RalinkCounters.OneSecRxCount = 0;
 670        pAd->RalinkCounters.OneSecTxAggregationCount = 0;
 671        pAd->RalinkCounters.OneSecRxAggregationCount = 0;
 672
 673        return;
 674}
 675
 676/*
 677        ==========================================================================
 678        Description:
 679                This routine is executed periodically to -
 680                1. Decide if it's a right time to turn on PwrMgmt bit of all
 681                   outgoiing frames
 682                2. Calculate ChannelQuality based on statistics of the last
 683                   period, so that TX rate won't toggling very frequently between a
 684                   successful TX and a failed TX.
 685                3. If the calculated ChannelQuality indicated current connection not
 686                   healthy, then a ROAMing attempt is tried here.
 687
 688        IRQL = DISPATCH_LEVEL
 689
 690        ==========================================================================
 691 */
 692#define ADHOC_BEACON_LOST_TIME          (8*OS_HZ)       /* 8 sec */
 693void MlmePeriodicExec(void *SystemSpecific1,
 694                      void *FunctionContext,
 695                      void *SystemSpecific2, void *SystemSpecific3)
 696{
 697        unsigned long TxTotalCnt;
 698        struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
 699
 700#ifdef RTMP_MAC_PCI
 701        {
 702                /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */
 703                /* Move code to here, because following code will return when radio is off */
 704                if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) ==
 705                     0) && (pAd->StaCfg.bHardwareRadio == TRUE)
 706                    && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
 707                    && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
 708                    /*&&(pAd->bPCIclkOff == FALSE) */
 709                    ) {
 710                        u32 data = 0;
 711
 712                        /* Read GPIO pin2 as Hardware controlled radio state */
 713#ifndef RT3090
 714                        RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
 715#endif /* RT3090 // */
 716/*KH(PCIE PS):Added based on Jane<-- */
 717#ifdef RT3090
 718/* Read GPIO pin2 as Hardware controlled radio state */
 719/* We need to Read GPIO if HW said so no mater what advance power saving */
 720                        if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
 721                            &&
 722                            (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
 723                            && (pAd->StaCfg.PSControl.field.EnablePSinIdle ==
 724                                TRUE)) {
 725                                /* Want to make sure device goes to L0 state before reading register. */
 726                                RTMPPCIeLinkCtrlValueRestore(pAd, 0);
 727                                RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
 728                                RTMPPCIeLinkCtrlSetting(pAd, 3);
 729                        } else
 730                                RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
 731#endif /* RT3090 // */
 732/*KH(PCIE PS):Added based on Jane--> */
 733
 734                        if (data & 0x04) {
 735                                pAd->StaCfg.bHwRadio = TRUE;
 736                        } else {
 737                                pAd->StaCfg.bHwRadio = FALSE;
 738                        }
 739                        if (pAd->StaCfg.bRadio !=
 740                            (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) {
 741                                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio
 742                                                      && pAd->StaCfg.bSwRadio);
 743                                if (pAd->StaCfg.bRadio == TRUE) {
 744                                        MlmeRadioOn(pAd);
 745                                        /* Update extra information */
 746                                        pAd->ExtraInfo = EXTRA_INFO_CLEAR;
 747                                } else {
 748                                        MlmeRadioOff(pAd);
 749                                        /* Update extra information */
 750                                        pAd->ExtraInfo = HW_RADIO_OFF;
 751                                }
 752                        }
 753                }
 754        }
 755#endif /* RTMP_MAC_PCI // */
 756
 757        /* Do nothing if the driver is starting halt state. */
 758        /* This might happen when timer already been fired before cancel timer with mlmehalt */
 759        if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
 760                                  fRTMP_ADAPTER_RADIO_OFF |
 761                                  fRTMP_ADAPTER_RADIO_MEASUREMENT |
 762                                  fRTMP_ADAPTER_RESET_IN_PROGRESS))))
 763                return;
 764
 765        RTMP_MLME_PRE_SANITY_CHECK(pAd);
 766
 767        {
 768                /* Do nothing if monitor mode is on */
 769                if (MONITOR_ON(pAd))
 770                        return;
 771
 772                if (pAd->Mlme.PeriodicRound & 0x1) {
 773                        /* This is the fix for wifi 11n extension channel overlapping test case.  for 2860D */
 774                        if (((pAd->MACVersion & 0xffff) == 0x0101) &&
 775                            (STA_TGN_WIFI_ON(pAd)) &&
 776                            (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
 777                        {
 778                                RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
 779                                pAd->CommonCfg.IOTestParm.bToggle = TRUE;
 780                        } else if ((STA_TGN_WIFI_ON(pAd)) &&
 781                                   ((pAd->MACVersion & 0xffff) == 0x0101)) {
 782                                RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
 783                                pAd->CommonCfg.IOTestParm.bToggle = FALSE;
 784                        }
 785                }
 786        }
 787
 788        pAd->bUpdateBcnCntDone = FALSE;
 789
 790/*      RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */
 791        pAd->Mlme.PeriodicRound++;
 792
 793#ifdef RTMP_MAC_USB
 794        /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */
 795        NICUpdateFifoStaCounters(pAd);
 796#endif /* RTMP_MAC_USB // */
 797
 798        /* execute every 500ms */
 799        if ((pAd->Mlme.PeriodicRound % 5 == 0)
 800            && RTMPAutoRateSwitchCheck(pAd)
 801            /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ )
 802        {
 803                /* perform dynamic tx rate switching based on past TX history */
 804                {
 805                        if ((OPSTATUS_TEST_FLAG
 806                             (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
 807                            )
 808                            && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
 809                                MlmeDynamicTxRateSwitching(pAd);
 810                }
 811        }
 812        /* Normal 1 second Mlme PeriodicExec. */
 813        if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) {
 814                pAd->Mlme.OneSecPeriodicRound++;
 815
 816                /*ORIBATimerTimeout(pAd); */
 817
 818                /* Media status changed, report to NDIS */
 819                if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) {
 820                        RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
 821                        if (OPSTATUS_TEST_FLAG
 822                            (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
 823                                pAd->IndicateMediaState =
 824                                    NdisMediaStateConnected;
 825                                RTMP_IndicateMediaState(pAd);
 826
 827                        } else {
 828                                pAd->IndicateMediaState =
 829                                    NdisMediaStateDisconnected;
 830                                RTMP_IndicateMediaState(pAd);
 831                        }
 832                }
 833
 834                NdisGetSystemUpTime(&pAd->Mlme.Now32);
 835
 836                /* add the most up-to-date h/w raw counters into software variable, so that */
 837                /* the dynamic tuning mechanism below are based on most up-to-date information */
 838                NICUpdateRawCounters(pAd);
 839
 840#ifdef RTMP_MAC_USB
 841                RTUSBWatchDog(pAd);
 842#endif /* RTMP_MAC_USB // */
 843
 844                /* Need statistics after read counter. So put after NICUpdateRawCounters */
 845                ORIBATimerTimeout(pAd);
 846
 847                /* if MGMT RING is full more than twice within 1 second, we consider there's */
 848                /* a hardware problem stucking the TX path. In this case, try a hardware reset */
 849                /* to recover the system */
 850                /*      if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */
 851                /*              RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */
 852                /*      else */
 853                /*              pAd->RalinkCounters.MgmtRingFullCount = 0; */
 854
 855                /* The time period for checking antenna is according to traffic */
 856                {
 857                        if (pAd->Mlme.bEnableAutoAntennaCheck) {
 858                                TxTotalCnt =
 859                                    pAd->RalinkCounters.OneSecTxNoRetryOkCount +
 860                                    pAd->RalinkCounters.OneSecTxRetryOkCount +
 861                                    pAd->RalinkCounters.OneSecTxFailCount;
 862
 863                                /* dynamic adjust antenna evaluation period according to the traffic */
 864                                if (TxTotalCnt > 50) {
 865                                        if (pAd->Mlme.OneSecPeriodicRound %
 866                                            10 == 0) {
 867                                                AsicEvaluateRxAnt(pAd);
 868                                        }
 869                                } else {
 870                                        if (pAd->Mlme.OneSecPeriodicRound % 3 ==
 871                                            0) {
 872                                                AsicEvaluateRxAnt(pAd);
 873                                        }
 874                                }
 875                        }
 876                }
 877
 878                STAMlmePeriodicExec(pAd);
 879
 880                MlmeResetRalinkCounters(pAd);
 881
 882                {
 883#ifdef RTMP_MAC_PCI
 884                        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
 885                            && (pAd->bPCIclkOff == FALSE))
 886#endif /* RTMP_MAC_PCI // */
 887                        {
 888                                /* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */
 889                                /* and sending CTS-to-self over and over. */
 890                                /* Software Patch Solution: */
 891                                /* 1. Polling debug state register 0x10F4 every one second. */
 892                                /* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */
 893                                /* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */
 894
 895                                u32 MacReg = 0;
 896
 897                                RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
 898                                if (((MacReg & 0x20000000) && (MacReg & 0x80))
 899                                    || ((MacReg & 0x20000000)
 900                                        && (MacReg & 0x20))) {
 901                                        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
 902                                        RTMPusecDelay(1);
 903                                        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
 904
 905                                        DBGPRINT(RT_DEBUG_WARN,
 906                                                 ("Warning, MAC specific condition occurs \n"));
 907                                }
 908                        }
 909                }
 910
 911                RTMP_MLME_HANDLER(pAd);
 912        }
 913
 914        pAd->bUpdateBcnCntDone = FALSE;
 915}
 916
 917/*
 918        ==========================================================================
 919        Validate SSID for connection try and rescan purpose
 920        Valid SSID will have visible chars only.
 921        The valid length is from 0 to 32.
 922        IRQL = DISPATCH_LEVEL
 923        ==========================================================================
 924 */
 925BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen)
 926{
 927        int index;
 928
 929        if (SsidLen > MAX_LEN_OF_SSID)
 930                return (FALSE);
 931
 932        /* Check each character value */
 933        for (index = 0; index < SsidLen; index++) {
 934                if (pSsid[index] < 0x20)
 935                        return (FALSE);
 936        }
 937
 938        /* All checked */
 939        return (TRUE);
 940}
 941
 942void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd,
 943                           struct rt_mac_table_entry *pEntry,
 944                           u8 ** ppTable,
 945                           u8 *pTableSize, u8 *pInitTxRateIdx)
 946{
 947        do {
 948                /* decide the rate table for tuning */
 949                if (pAd->CommonCfg.TxRateTableSize > 0) {
 950                        *ppTable = RateSwitchTable;
 951                        *pTableSize = RateSwitchTable[0];
 952                        *pInitTxRateIdx = RateSwitchTable[1];
 953
 954                        break;
 955                }
 956
 957                if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) {
 958                        if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) {       /* 11N 1S Adhoc */
 959                                *ppTable = RateSwitchTable11N1S;
 960                                *pTableSize = RateSwitchTable11N1S[0];
 961                                *pInitTxRateIdx = RateSwitchTable11N1S[1];
 962
 963                        } else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) {  /* 11N 2S Adhoc */
 964                                if (pAd->LatchRfRegs.Channel <= 14) {
 965                                        *ppTable = RateSwitchTable11N2S;
 966                                        *pTableSize = RateSwitchTable11N2S[0];
 967                                        *pInitTxRateIdx =
 968                                            RateSwitchTable11N2S[1];
 969                                } else {
 970                                        *ppTable = RateSwitchTable11N2SForABand;
 971                                        *pTableSize =
 972                                            RateSwitchTable11N2SForABand[0];
 973                                        *pInitTxRateIdx =
 974                                            RateSwitchTable11N2SForABand[1];
 975                                }
 976
 977                        } else if ((pEntry->RateLen == 4)
 978                                   && (pEntry->HTCapability.MCSSet[0] == 0)
 979                                   && (pEntry->HTCapability.MCSSet[1] == 0)
 980                            ) {
 981                                *ppTable = RateSwitchTable11B;
 982                                *pTableSize = RateSwitchTable11B[0];
 983                                *pInitTxRateIdx = RateSwitchTable11B[1];
 984
 985                        } else if (pAd->LatchRfRegs.Channel <= 14) {
 986                                *ppTable = RateSwitchTable11BG;
 987                                *pTableSize = RateSwitchTable11BG[0];
 988                                *pInitTxRateIdx = RateSwitchTable11BG[1];
 989
 990                        } else {
 991                                *ppTable = RateSwitchTable11G;
 992                                *pTableSize = RateSwitchTable11G[0];
 993                                *pInitTxRateIdx = RateSwitchTable11G[1];
 994
 995                        }
 996                        break;
 997                }
 998                /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
 999                /*      ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1000                if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) {     /* 11BGN 1S AP */
1001                        *ppTable = RateSwitchTable11BGN1S;
1002                        *pTableSize = RateSwitchTable11BGN1S[0];
1003                        *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1004
1005                        break;
1006                }
1007                /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
1008                /*      (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1009                if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) {       /* 11BGN 2S AP */
1010                        if (pAd->LatchRfRegs.Channel <= 14) {
1011                                *ppTable = RateSwitchTable11BGN2S;
1012                                *pTableSize = RateSwitchTable11BGN2S[0];
1013                                *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1014
1015                        } else {
1016                                *ppTable = RateSwitchTable11BGN2SForABand;
1017                                *pTableSize = RateSwitchTable11BGN2SForABand[0];
1018                                *pInitTxRateIdx =
1019                                    RateSwitchTable11BGN2SForABand[1];
1020
1021                        }
1022                        break;
1023                }
1024                /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1025                if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11N 1S AP */
1026                        *ppTable = RateSwitchTable11N1S;
1027                        *pTableSize = RateSwitchTable11N1S[0];
1028                        *pInitTxRateIdx = RateSwitchTable11N1S[1];
1029
1030                        break;
1031                }
1032                /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1033                if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) {   /* 11N 2S AP */
1034                        if (pAd->LatchRfRegs.Channel <= 14) {
1035                                *ppTable = RateSwitchTable11N2S;
1036                                *pTableSize = RateSwitchTable11N2S[0];
1037                                *pInitTxRateIdx = RateSwitchTable11N2S[1];
1038                        } else {
1039                                *ppTable = RateSwitchTable11N2SForABand;
1040                                *pTableSize = RateSwitchTable11N2SForABand[0];
1041                                *pInitTxRateIdx =
1042                                    RateSwitchTable11N2SForABand[1];
1043                        }
1044
1045                        break;
1046                }
1047                /*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1048                if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode == PHY_11B)
1049                    /*Iverson mark for Adhoc b mode,sta will use rate 54  Mbps when connect with sta b/g/n mode */
1050                    /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */
1051                    ) {         /* B only AP */
1052                        *ppTable = RateSwitchTable11B;
1053                        *pTableSize = RateSwitchTable11B[0];
1054                        *pInitTxRateIdx = RateSwitchTable11B[1];
1055
1056                        break;
1057                }
1058                /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1059                if ((pEntry->RateLen > 8)
1060                    && (pEntry->HTCapability.MCSSet[0] == 0)
1061                    && (pEntry->HTCapability.MCSSet[1] == 0)
1062                    ) {         /* B/G  mixed AP */
1063                        *ppTable = RateSwitchTable11BG;
1064                        *pTableSize = RateSwitchTable11BG[0];
1065                        *pInitTxRateIdx = RateSwitchTable11BG[1];
1066
1067                        break;
1068                }
1069                /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1070                if ((pEntry->RateLen == 8)
1071                    && (pEntry->HTCapability.MCSSet[0] == 0)
1072                    && (pEntry->HTCapability.MCSSet[1] == 0)
1073                    ) {         /* G only AP */
1074                        *ppTable = RateSwitchTable11G;
1075                        *pTableSize = RateSwitchTable11G[0];
1076                        *pInitTxRateIdx = RateSwitchTable11G[1];
1077
1078                        break;
1079                }
1080
1081                {
1082                        /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1083                        if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) {   /* Legacy mode */
1084                                if (pAd->CommonCfg.MaxTxRate <= RATE_11) {
1085                                        *ppTable = RateSwitchTable11B;
1086                                        *pTableSize = RateSwitchTable11B[0];
1087                                        *pInitTxRateIdx = RateSwitchTable11B[1];
1088                                } else if ((pAd->CommonCfg.MaxTxRate > RATE_11)
1089                                           && (pAd->CommonCfg.MinTxRate >
1090                                               RATE_11)) {
1091                                        *ppTable = RateSwitchTable11G;
1092                                        *pTableSize = RateSwitchTable11G[0];
1093                                        *pInitTxRateIdx = RateSwitchTable11G[1];
1094
1095                                } else {
1096                                        *ppTable = RateSwitchTable11BG;
1097                                        *pTableSize = RateSwitchTable11BG[0];
1098                                        *pInitTxRateIdx =
1099                                            RateSwitchTable11BG[1];
1100                                }
1101                                break;
1102                        }
1103                        if (pAd->LatchRfRegs.Channel <= 14) {
1104                                if (pAd->CommonCfg.TxStream == 1) {
1105                                        *ppTable = RateSwitchTable11N1S;
1106                                        *pTableSize = RateSwitchTable11N1S[0];
1107                                        *pInitTxRateIdx =
1108                                            RateSwitchTable11N1S[1];
1109                                        DBGPRINT_RAW(RT_DEBUG_ERROR,
1110                                                     ("DRS: unknown mode,default use 11N 1S AP \n"));
1111                                } else {
1112                                        *ppTable = RateSwitchTable11N2S;
1113                                        *pTableSize = RateSwitchTable11N2S[0];
1114                                        *pInitTxRateIdx =
1115                                            RateSwitchTable11N2S[1];
1116                                        DBGPRINT_RAW(RT_DEBUG_ERROR,
1117                                                     ("DRS: unknown mode,default use 11N 2S AP \n"));
1118                                }
1119                        } else {
1120                                if (pAd->CommonCfg.TxStream == 1) {
1121                                        *ppTable = RateSwitchTable11N1S;
1122                                        *pTableSize = RateSwitchTable11N1S[0];
1123                                        *pInitTxRateIdx =
1124                                            RateSwitchTable11N1S[1];
1125                                        DBGPRINT_RAW(RT_DEBUG_ERROR,
1126                                                     ("DRS: unknown mode,default use 11N 1S AP \n"));
1127                                } else {
1128                                        *ppTable = RateSwitchTable11N2SForABand;
1129                                        *pTableSize =
1130                                            RateSwitchTable11N2SForABand[0];
1131                                        *pInitTxRateIdx =
1132                                            RateSwitchTable11N2SForABand[1];
1133                                        DBGPRINT_RAW(RT_DEBUG_ERROR,
1134                                                     ("DRS: unknown mode,default use 11N 2S AP \n"));
1135                                }
1136                        }
1137                        DBGPRINT_RAW(RT_DEBUG_ERROR,
1138                                     ("DRS: unknown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1139                                      pAd->StaActive.SupRateLen,
1140                                      pAd->StaActive.ExtRateLen,
1141                                      pAd->StaActive.SupportedPhyInfo.MCSSet[0],
1142                                      pAd->StaActive.SupportedPhyInfo.
1143                                      MCSSet[1]));
1144                }
1145        } while (FALSE);
1146}
1147
1148void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd)
1149{
1150        unsigned long TxTotalCnt;
1151        int i;
1152
1153        /*
1154           We return here in ATE mode, because the statistics
1155           that ATE need are not collected via this routine.
1156         */
1157#if defined(RT305x)||defined(RT3070)
1158        /* request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18 */
1159        if (!pAd->CommonCfg.HighPowerPatchDisabled) {
1160#ifdef RT3070
1161                if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201)))
1162#endif /* RT3070 // */
1163                {
1164                        if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0)
1165                            && (pAd->StaCfg.RssiSample.AvgRssi0 >
1166                                (pAd->BbpRssiToDbmDelta - 35))) {
1167                                RT30xxWriteRFRegister(pAd, RF_R27, 0x20);
1168                        } else {
1169                                RT30xxWriteRFRegister(pAd, RF_R27, 0x23);
1170                        }
1171                }
1172        }
1173#endif
1174#ifdef PCIE_PS_SUPPORT
1175/* don't perform idle-power-save mechanism within 3 min after driver initialization. */
1176/* This can make rebooter test more robust */
1177        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
1178                if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
1179                    && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1180                    && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1181                    && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) {
1182                        if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) {
1183                                if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1184                                    TRUE) {
1185                                        DBGPRINT(RT_DEBUG_TRACE,
1186                                                 ("%s\n", __func__));
1187                                        RT28xxPciAsicRadioOff(pAd,
1188                                                              GUI_IDLE_POWER_SAVE,
1189                                                              0);
1190                                } else {
1191                                        AsicSendCommandToMcu(pAd, 0x30,
1192                                                             PowerSafeCID, 0xff,
1193                                                             0x2);
1194                                        /* Wait command success */
1195                                        AsicCheckCommanOk(pAd, PowerSafeCID);
1196                                        RTMP_SET_FLAG(pAd,
1197                                                      fRTMP_ADAPTER_IDLE_RADIO_OFF);
1198                                        DBGPRINT(RT_DEBUG_TRACE,
1199                                                 ("PSM - rt30xx Issue Sleep command)\n"));
1200                                }
1201                        } else if (pAd->Mlme.OneSecPeriodicRound > 180) {
1202                                if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1203                                    TRUE) {
1204                                        DBGPRINT(RT_DEBUG_TRACE,
1205                                                 ("%s\n", __func__));
1206                                        RT28xxPciAsicRadioOff(pAd,
1207                                                              GUI_IDLE_POWER_SAVE,
1208                                                              0);
1209                                } else {
1210                                        AsicSendCommandToMcu(pAd, 0x30,
1211                                                             PowerSafeCID, 0xff,
1212                                                             0x02);
1213                                        /* Wait command success */
1214                                        AsicCheckCommanOk(pAd, PowerSafeCID);
1215                                        RTMP_SET_FLAG(pAd,
1216                                                      fRTMP_ADAPTER_IDLE_RADIO_OFF);
1217                                        DBGPRINT(RT_DEBUG_TRACE,
1218                                                 ("PSM -  rt28xx Issue Sleep command)\n"));
1219                                }
1220                        }
1221                } else {
1222                        DBGPRINT(RT_DEBUG_TRACE,
1223                                 ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1224                                  pAd->CommonCfg.SsidLen,
1225                                  pAd->CommonCfg.Ssid[0],
1226                                  pAd->CommonCfg.Ssid[1],
1227                                  pAd->CommonCfg.Ssid[2],
1228                                  pAd->CommonCfg.Ssid[3], pAd->MlmeAux.SsidLen,
1229                                  pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1],
1230                                  pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
1231                }
1232        }
1233#endif /* PCIE_PS_SUPPORT // */
1234
1235        if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) {
1236                /* WPA MIC error should block association attempt for 60 seconds */
1237                if (pAd->StaCfg.bBlockAssoc &&
1238                    RTMP_TIME_AFTER(pAd->Mlme.Now32,
1239                                    pAd->StaCfg.LastMicErrorTime +
1240                                    (60 * OS_HZ)))
1241                        pAd->StaCfg.bBlockAssoc = FALSE;
1242        }
1243
1244        if ((pAd->PreMediaState != pAd->IndicateMediaState)
1245            && (pAd->CommonCfg.bWirelessEvent)) {
1246                if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1247                        RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1248                                              pAd->MacTab.Content[BSSID_WCID].
1249                                              Addr, BSS0, 0);
1250                }
1251                pAd->PreMediaState = pAd->IndicateMediaState;
1252        }
1253
1254        if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) {
1255        } else {
1256                AsicStaBbpTuning(pAd);
1257        }
1258
1259        TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1260            pAd->RalinkCounters.OneSecTxRetryOkCount +
1261            pAd->RalinkCounters.OneSecTxFailCount;
1262
1263        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
1264                /* update channel quality for Roaming and UI LinkQuality display */
1265                MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32);
1266        }
1267        /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */
1268        /* Radio is currently in noisy environment */
1269        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1270                AsicAdjustTxPower(pAd);
1271
1272        if (INFRA_ON(pAd)) {
1273
1274                /* Is PSM bit consistent with user power management policy? */
1275                /* This is the only place that will set PSM bit ON. */
1276                if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1277                        MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1278
1279                pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1280
1281                if ((RTMP_TIME_AFTER
1282                     (pAd->Mlme.Now32,
1283                      pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ)))
1284                    &&
1285                    (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1286                    &&
1287                    (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) <
1288                      600))) {
1289                        RTMPSetAGCInitValue(pAd, BW_20);
1290                        DBGPRINT(RT_DEBUG_TRACE,
1291                                 ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n",
1292                                  (0x2E + GET_LNA_GAIN(pAd))));
1293                }
1294                /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */
1295                /*    (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */
1296                {
1297                        if (pAd->CommonCfg.bAPSDCapable
1298                            && pAd->CommonCfg.APEdcaParm.bAPSDCapable) {
1299                                /* When APSD is enabled, the period changes as 20 sec */
1300                                if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1301                                        RTMPSendNullFrame(pAd,
1302                                                          pAd->CommonCfg.TxRate,
1303                                                          TRUE);
1304                        } else {
1305                                /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */
1306                                if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) {
1307                                        if (pAd->CommonCfg.bWmmCapable)
1308                                                RTMPSendNullFrame(pAd,
1309                                                                  pAd->
1310                                                                  CommonCfg.
1311                                                                  TxRate, TRUE);
1312                                        else
1313                                                RTMPSendNullFrame(pAd,
1314                                                                  pAd->
1315                                                                  CommonCfg.
1316                                                                  TxRate,
1317                                                                  FALSE);
1318                                }
1319                        }
1320                }
1321
1322                if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) {
1323                        DBGPRINT(RT_DEBUG_TRACE,
1324                                 ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n",
1325                                  pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1326
1327                        /* Lost AP, send disconnect & link down event */
1328                        LinkDown(pAd, FALSE);
1329
1330                        RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL,
1331                                                0);
1332
1333                        /* RTMPPatchMacBbpBug(pAd); */
1334                        MlmeAutoReconnectLastSSID(pAd);
1335                } else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) {
1336                        pAd->RalinkCounters.BadCQIAutoRecoveryCount++;
1337                        DBGPRINT(RT_DEBUG_TRACE,
1338                                 ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n",
1339                                  pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1340                        MlmeAutoReconnectLastSSID(pAd);
1341                }
1342
1343                if (pAd->StaCfg.bAutoRoaming) {
1344                        BOOLEAN rv = FALSE;
1345                        char dBmToRoam = pAd->StaCfg.dBmToRoam;
1346                        char MaxRssi = RTMPMaxRssi(pAd,
1347                                                   pAd->StaCfg.RssiSample.
1348                                                   LastRssi0,
1349                                                   pAd->StaCfg.RssiSample.
1350                                                   LastRssi1,
1351                                                   pAd->StaCfg.RssiSample.
1352                                                   LastRssi2);
1353
1354                        /* Scanning, ignore Roaming */
1355                        if (!RTMP_TEST_FLAG
1356                            (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
1357                            && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1358                            && (MaxRssi <= dBmToRoam)) {
1359                                DBGPRINT(RT_DEBUG_TRACE,
1360                                         ("Rssi=%d, dBmToRoam=%d\n", MaxRssi,
1361                                          (char)dBmToRoam));
1362
1363                                /* Add auto seamless roaming */
1364                                if (rv == FALSE)
1365                                        rv = MlmeCheckForFastRoaming(pAd);
1366
1367                                if (rv == FALSE) {
1368                                        if ((pAd->StaCfg.LastScanTime +
1369                                             10 * OS_HZ) < pAd->Mlme.Now32) {
1370                                                DBGPRINT(RT_DEBUG_TRACE,
1371                                                         ("MMCHK - Roaming, No eligible entry, try new scan!\n"));
1372                                                pAd->StaCfg.ScanCnt = 2;
1373                                                pAd->StaCfg.LastScanTime =
1374                                                    pAd->Mlme.Now32;
1375                                                MlmeAutoScan(pAd);
1376                                        }
1377                                }
1378                        }
1379                }
1380        } else if (ADHOC_ON(pAd)) {
1381                /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */
1382                /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */
1383                /* join later. */
1384                if (RTMP_TIME_AFTER
1385                    (pAd->Mlme.Now32,
1386                     pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)
1387                    && OPSTATUS_TEST_FLAG(pAd,
1388                                          fOP_STATUS_MEDIA_STATE_CONNECTED)) {
1389                        struct rt_mlme_start_req StartReq;
1390
1391                        DBGPRINT(RT_DEBUG_TRACE,
1392                                 ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1393                        LinkDown(pAd, FALSE);
1394
1395                        StartParmFill(pAd, &StartReq,
1396                                      (char *) pAd->MlmeAux.Ssid,
1397                                      pAd->MlmeAux.SsidLen);
1398                        MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ,
1399                                    sizeof(struct rt_mlme_start_req), &StartReq);
1400                        pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1401                }
1402
1403                for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1404                        struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i];
1405
1406                        if (pEntry->ValidAsCLI == FALSE)
1407                                continue;
1408
1409                        if (RTMP_TIME_AFTER
1410                            (pAd->Mlme.Now32,
1411                             pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1412                                MacTableDeleteEntry(pAd, pEntry->Aid,
1413                                                    pEntry->Addr);
1414                }
1415        } else                  /* no INFRA nor ADHOC connection */
1416        {
1417
1418                if (pAd->StaCfg.bScanReqIsFromWebUI &&
1419                    RTMP_TIME_BEFORE(pAd->Mlme.Now32,
1420                                     pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
1421                        goto SKIP_AUTO_SCAN_CONN;
1422                else
1423                        pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1424
1425                if ((pAd->StaCfg.bAutoReconnect == TRUE)
1426                    && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1427                    &&
1428                    (MlmeValidateSSID
1429                     (pAd->MlmeAux.AutoReconnectSsid,
1430                      pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1431                        if ((pAd->ScanTab.BssNr == 0)
1432                            && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) {
1433                                struct rt_mlme_scan_req ScanReq;
1434
1435                                if (RTMP_TIME_AFTER
1436                                    (pAd->Mlme.Now32,
1437                                     pAd->StaCfg.LastScanTime + (10 * OS_HZ))) {
1438                                        DBGPRINT(RT_DEBUG_TRACE,
1439                                                 ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n",
1440                                                  pAd->MlmeAux.
1441                                                  AutoReconnectSsid));
1442                                        ScanParmFill(pAd, &ScanReq,
1443                                                     (char *)pAd->MlmeAux.
1444                                                     AutoReconnectSsid,
1445                                                     pAd->MlmeAux.
1446                                                     AutoReconnectSsidLen,
1447                                                     BSS_ANY, SCAN_ACTIVE);
1448                                        MlmeEnqueue(pAd, SYNC_STATE_MACHINE,
1449                                                    MT2_MLME_SCAN_REQ,
1450                                                    sizeof
1451                                                    (struct rt_mlme_scan_req),
1452                                                    &ScanReq);
1453                                        pAd->Mlme.CntlMachine.CurrState =
1454                                            CNTL_WAIT_OID_LIST_SCAN;
1455                                        /* Reset Missed scan number */
1456                                        pAd->StaCfg.LastScanTime =
1457                                            pAd->Mlme.Now32;
1458                                } else if (pAd->StaCfg.BssType == BSS_ADHOC)    /* Quit the forever scan when in a very clean room */
1459                                        MlmeAutoReconnectLastSSID(pAd);
1460                        } else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1461                                if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) {
1462                                        MlmeAutoScan(pAd);
1463                                        pAd->StaCfg.LastScanTime =
1464                                            pAd->Mlme.Now32;
1465                                } else {
1466                                        MlmeAutoReconnectLastSSID(pAd);
1467                                }
1468                        }
1469                }
1470        }
1471
1472SKIP_AUTO_SCAN_CONN:
1473
1474        if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap != 0)
1475            && (pAd->MacTab.fAnyBASession == FALSE)) {
1476                pAd->MacTab.fAnyBASession = TRUE;
1477                AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE,
1478                                  FALSE);
1479        } else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap == 0)
1480                   && (pAd->MacTab.fAnyBASession == TRUE)) {
1481                pAd->MacTab.fAnyBASession = FALSE;
1482                AsicUpdateProtect(pAd,
1483                                  pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1484                                  OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1485        }
1486
1487        return;
1488}
1489
1490/* Link down report */
1491void LinkDownExec(void *SystemSpecific1,
1492                  void *FunctionContext,
1493                  void *SystemSpecific2, void *SystemSpecific3)
1494{
1495        struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
1496
1497        if (pAd != NULL) {
1498                struct rt_mlme_disassoc_req DisassocReq;
1499
1500                if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
1501                    (INFRA_ON(pAd))) {
1502                        DBGPRINT(RT_DEBUG_TRACE,
1503                                 ("LinkDownExec(): disassociate with current AP...\n"));
1504                        DisassocParmFill(pAd, &DisassocReq,
1505                                         pAd->CommonCfg.Bssid,
1506                                         REASON_DISASSOC_STA_LEAVING);
1507                        MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
1508                                    MT2_MLME_DISASSOC_REQ,
1509                                    sizeof(struct rt_mlme_disassoc_req),
1510                                    &DisassocReq);
1511                        pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1512
1513                        pAd->IndicateMediaState = NdisMediaStateDisconnected;
1514                        RTMP_IndicateMediaState(pAd);
1515                        pAd->ExtraInfo = GENERAL_LINK_DOWN;
1516                }
1517        }
1518}
1519
1520/* IRQL = DISPATCH_LEVEL */
1521void MlmeAutoScan(struct rt_rtmp_adapter *pAd)
1522{
1523        /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1524        if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1525                DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1526                MlmeEnqueue(pAd,
1527                            MLME_CNTL_STATE_MACHINE,
1528                            OID_802_11_BSSID_LIST_SCAN,
1529                            pAd->MlmeAux.AutoReconnectSsidLen,
1530                            pAd->MlmeAux.AutoReconnectSsid);
1531                RTMP_MLME_HANDLER(pAd);
1532        }
1533}
1534
1535/* IRQL = DISPATCH_LEVEL */
1536void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd)
1537{
1538        if (pAd->StaCfg.bAutoConnectByBssid) {
1539                DBGPRINT(RT_DEBUG_TRACE,
1540                        ("Driver auto reconnect to last OID_802_11_BSSID "
1541                                "setting - %pM\n", pAd->MlmeAux.Bssid));
1542
1543                pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1544                MlmeEnqueue(pAd,
1545                            MLME_CNTL_STATE_MACHINE,
1546                            OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid);
1547
1548                pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1549
1550                RTMP_MLME_HANDLER(pAd);
1551        }
1552        /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1553        else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1554                 (MlmeValidateSSID
1555                  (pAd->MlmeAux.AutoReconnectSsid,
1556                   pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1557                struct rt_ndis_802_11_ssid OidSsid;
1558                OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1559                NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid,
1560                               pAd->MlmeAux.AutoReconnectSsidLen);
1561
1562                DBGPRINT(RT_DEBUG_TRACE,
1563                         ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
1564                          pAd->MlmeAux.AutoReconnectSsid,
1565                          pAd->MlmeAux.AutoReconnectSsidLen));
1566                MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID,
1567                            sizeof(struct rt_ndis_802_11_ssid), &OidSsid);
1568                RTMP_MLME_HANDLER(pAd);
1569        }
1570}
1571
1572/*
1573        ==========================================================================
1574        Description:
1575                This routine checks if there're other APs out there capable for
1576                roaming. Caller should call this routine only when Link up in INFRA mode
1577                and channel quality is below CQI_GOOD_THRESHOLD.
1578
1579        IRQL = DISPATCH_LEVEL
1580
1581        Output:
1582        ==========================================================================
1583 */
1584void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32)
1585{
1586        u16 i;
1587        struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1588        struct rt_bss_entry *pBss;
1589
1590        DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1591        /* put all roaming candidates into RoamTab, and sort in RSSI order */
1592        BssTableInit(pRoamTab);
1593        for (i = 0; i < pAd->ScanTab.BssNr; i++) {
1594                pBss = &pAd->ScanTab.BssEntry[i];
1595
1596                if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) <
1597                    Now32)
1598                        continue;       /* AP disappear */
1599                if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1600                        continue;       /* RSSI too weak. forget it. */
1601                if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1602                        continue;       /* skip current AP */
1603                if (pBss->Rssi <
1604                    (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1605                        continue;       /* only AP with stronger RSSI is eligible for roaming */
1606
1607                /* AP passing all above rules is put into roaming candidate table */
1608                NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
1609                               sizeof(struct rt_bss_entry));
1610                pRoamTab->BssNr += 1;
1611        }
1612
1613        if (pRoamTab->BssNr > 0) {
1614                /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1615                if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1616                        pAd->RalinkCounters.PoorCQIRoamingCount++;
1617                        DBGPRINT(RT_DEBUG_TRACE,
1618                                 ("MMCHK - Roaming attempt #%ld\n",
1619                                  pAd->RalinkCounters.PoorCQIRoamingCount));
1620                        MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1621                                    MT2_MLME_ROAMING_REQ, 0, NULL);
1622                        RTMP_MLME_HANDLER(pAd);
1623                }
1624        }
1625        DBGPRINT(RT_DEBUG_TRACE,
1626                 ("<== MlmeCheckForRoaming(# of candidate= %d)\n",
1627                  pRoamTab->BssNr));
1628}
1629
1630/*
1631        ==========================================================================
1632        Description:
1633                This routine checks if there're other APs out there capable for
1634                roaming. Caller should call this routine only when link up in INFRA mode
1635                and channel quality is below CQI_GOOD_THRESHOLD.
1636
1637        IRQL = DISPATCH_LEVEL
1638
1639        Output:
1640        ==========================================================================
1641 */
1642BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd)
1643{
1644        u16 i;
1645        struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1646        struct rt_bss_entry *pBss;
1647
1648        DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1649        /* put all roaming candidates into RoamTab, and sort in RSSI order */
1650        BssTableInit(pRoamTab);
1651        for (i = 0; i < pAd->ScanTab.BssNr; i++) {
1652                pBss = &pAd->ScanTab.BssEntry[i];
1653
1654                if ((pBss->Rssi <= -50)
1655                    && (pBss->Channel == pAd->CommonCfg.Channel))
1656                        continue;       /* RSSI too weak. forget it. */
1657                if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1658                        continue;       /* skip current AP */
1659                if (!SSID_EQUAL
1660                    (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid,
1661                     pAd->CommonCfg.SsidLen))
1662                        continue;       /* skip different SSID */
1663                if (pBss->Rssi <
1664                    (RTMPMaxRssi
1665                     (pAd, pAd->StaCfg.RssiSample.LastRssi0,
1666                      pAd->StaCfg.RssiSample.LastRssi1,
1667                      pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1668                        continue;       /* skip AP without better RSSI */
1669
1670                DBGPRINT(RT_DEBUG_TRACE,
1671                         ("LastRssi0 = %d, pBss->Rssi = %d\n",
1672                          RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0,
1673                                      pAd->StaCfg.RssiSample.LastRssi1,
1674                                      pAd->StaCfg.RssiSample.LastRssi2),
1675                          pBss->Rssi));
1676                /* AP passing all above rules is put into roaming candidate table */
1677                NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
1678                               sizeof(struct rt_bss_entry));
1679                pRoamTab->BssNr += 1;
1680        }
1681
1682        DBGPRINT(RT_DEBUG_TRACE,
1683                 ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1684        if (pRoamTab->BssNr > 0) {
1685                /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
1686                if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1687                        pAd->RalinkCounters.PoorCQIRoamingCount++;
1688                        DBGPRINT(RT_DEBUG_TRACE,
1689                                 ("MMCHK - Roaming attempt #%ld\n",
1690                                  pAd->RalinkCounters.PoorCQIRoamingCount));
1691                        MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1692                                    MT2_MLME_ROAMING_REQ, 0, NULL);
1693                        RTMP_MLME_HANDLER(pAd);
1694                        return TRUE;
1695                }
1696        }
1697
1698        return FALSE;
1699}
1700
1701void MlmeSetTxRate(struct rt_rtmp_adapter *pAd,
1702                   struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate)
1703{
1704        u8 MaxMode = MODE_OFDM;
1705
1706        MaxMode = MODE_HTGREENFIELD;
1707
1708        if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC)
1709            && (pAd->Antenna.field.TxPath == 2))
1710                pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1711        else
1712                pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1713
1714        if (pTxRate->CurrMCS < MCS_AUTO)
1715                pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1716
1717        if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1718                pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1719
1720        if (ADHOC_ON(pAd)) {
1721                /* If peer adhoc is b-only mode, we can't send 11g rate. */
1722                pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1723                pEntry->HTPhyMode.field.STBC = STBC_NONE;
1724
1725                /* */
1726                /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */
1727                /* */
1728                pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1729                pEntry->HTPhyMode.field.ShortGI =
1730                    pAd->StaCfg.HTPhyMode.field.ShortGI;
1731                pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1732
1733                /* Patch speed error in status page */
1734                pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1735        } else {
1736                if (pTxRate->Mode <= MaxMode)
1737                        pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1738
1739                if (pTxRate->ShortGI
1740                    && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1741                        pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1742                else
1743                        pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1744
1745                /* Reexam each bandwidth's SGI support. */
1746                if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) {
1747                        if ((pEntry->HTPhyMode.field.BW == BW_20)
1748                            &&
1749                            (!CLIENT_STATUS_TEST_FLAG
1750                             (pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1751                                pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1752                        if ((pEntry->HTPhyMode.field.BW == BW_40)
1753                            &&
1754                            (!CLIENT_STATUS_TEST_FLAG
1755                             (pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1756                                pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1757                }
1758                /* Turn RTS/CTS rate to 6Mbps. */
1759                if ((pEntry->HTPhyMode.field.MCS == 0)
1760                    && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) {
1761                        pEntry->HTPhyMode.field.MCS =
1762                            pAd->StaCfg.HTPhyMode.field.MCS;
1763                        if (pAd->MacTab.fAnyBASession) {
1764                                AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1765                                                  ALLN_SETPROTECT, TRUE,
1766                                                  (BOOLEAN) pAd->MlmeAux.
1767                                                  AddHtInfo.AddHtInfo2.
1768                                                  NonGfPresent);
1769                        } else {
1770                                AsicUpdateProtect(pAd,
1771                                                  pAd->MlmeAux.AddHtInfo.
1772                                                  AddHtInfo2.OperaionMode,
1773                                                  ALLN_SETPROTECT, TRUE,
1774                                                  (BOOLEAN) pAd->MlmeAux.
1775                                                  AddHtInfo.AddHtInfo2.
1776                                                  NonGfPresent);
1777                        }
1778                } else if ((pEntry->HTPhyMode.field.MCS == 8)
1779                           && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) {
1780                        pEntry->HTPhyMode.field.MCS =
1781                            pAd->StaCfg.HTPhyMode.field.MCS;
1782                        if (pAd->MacTab.fAnyBASession) {
1783                                AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1784                                                  ALLN_SETPROTECT, TRUE,
1785                                                  (BOOLEAN) pAd->MlmeAux.
1786                                                  AddHtInfo.AddHtInfo2.
1787                                                  NonGfPresent);
1788                        } else {
1789                                AsicUpdateProtect(pAd,
1790                                                  pAd->MlmeAux.AddHtInfo.
1791                                                  AddHtInfo2.OperaionMode,
1792                                                  ALLN_SETPROTECT, TRUE,
1793                                                  (BOOLEAN) pAd->MlmeAux.
1794                                                  AddHtInfo.AddHtInfo2.
1795                                                  NonGfPresent);
1796                        }
1797                } else if ((pEntry->HTPhyMode.field.MCS != 0)
1798                           && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) {
1799                        AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1800                                          TRUE,
1801                                          (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1802                                          AddHtInfo2.NonGfPresent);
1803
1804                } else if ((pEntry->HTPhyMode.field.MCS != 8)
1805                           && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) {
1806                        AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1807                                          TRUE,
1808                                          (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1809                                          AddHtInfo2.NonGfPresent);
1810                }
1811
1812                pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1813                pEntry->HTPhyMode.field.ShortGI =
1814                    pAd->StaCfg.HTPhyMode.field.ShortGI;
1815                pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1816                pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1817                if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD)
1818                    && pAd->WIFItestbed.bGreenField)
1819                        pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1820        }
1821
1822        pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word);
1823}
1824
1825/*
1826        ==========================================================================
1827        Description:
1828                This routine calculates the acumulated TxPER of eaxh TxRate. And
1829                according to the calculation result, change CommonCfg.TxRate which
1830                is the stable TX Rate we expect the Radio situation could sustained.
1831
1832                CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1833        Output:
1834                CommonCfg.TxRate -
1835
1836        IRQL = DISPATCH_LEVEL
1837
1838        NOTE:
1839                call this routine every second
1840        ==========================================================================
1841 */
1842void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd)
1843{
1844        u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1845        unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt;
1846        unsigned long TxErrorRatio = 0;
1847        BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
1848        struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
1849        u8 *pTable;
1850        u8 TableSize = 0;
1851        u8 InitTxRateIdx = 0, TrainUp, TrainDown;
1852        char Rssi, RssiOffset = 0;
1853        TX_STA_CNT1_STRUC StaTx1;
1854        TX_STA_CNT0_STRUC TxStaCnt0;
1855        unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1856        struct rt_mac_table_entry *pEntry;
1857        struct rt_rssi_sample *pRssi = &pAd->StaCfg.RssiSample;
1858
1859        /* */
1860        /* walk through MAC table, see if need to change AP's TX rate toward each entry */
1861        /* */
1862        for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1863                pEntry = &pAd->MacTab.Content[i];
1864
1865                /* check if this entry need to switch rate automatically */
1866                if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1867                        continue;
1868
1869                if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) {
1870                        Rssi = RTMPMaxRssi(pAd,
1871                                           pRssi->AvgRssi0,
1872                                           pRssi->AvgRssi1, pRssi->AvgRssi2);
1873
1874                        /* Update statistic counter */
1875                        RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1876                        RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1877                        pAd->bUpdateBcnCntDone = TRUE;
1878                        TxRetransmit = StaTx1.field.TxRetransmit;
1879                        TxSuccess = StaTx1.field.TxSuccess;
1880                        TxFailCount = TxStaCnt0.field.TxFailCount;
1881                        TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1882
1883                        pAd->RalinkCounters.OneSecTxRetryOkCount +=
1884                            StaTx1.field.TxRetransmit;
1885                        pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
1886                            StaTx1.field.TxSuccess;
1887                        pAd->RalinkCounters.OneSecTxFailCount +=
1888                            TxStaCnt0.field.TxFailCount;
1889                        pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
1890                            StaTx1.field.TxSuccess;
1891                        pAd->WlanCounters.RetryCount.u.LowPart +=
1892                            StaTx1.field.TxRetransmit;
1893                        pAd->WlanCounters.FailedCount.u.LowPart +=
1894                            TxStaCnt0.field.TxFailCount;
1895
1896                        /* if no traffic in the past 1-sec period, don't change TX rate, */
1897                        /* but clear all bad history. because the bad history may affect the next */
1898                        /* Chariot throughput test */
1899                        AccuTxTotalCnt =
1900                            pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1901                            pAd->RalinkCounters.OneSecTxRetryOkCount +
1902                            pAd->RalinkCounters.OneSecTxFailCount;
1903
1904                        if (TxTotalCnt)
1905                                TxErrorRatio =
1906                                    ((TxRetransmit +
1907                                      TxFailCount) * 100) / TxTotalCnt;
1908                } else {
1909                        if (INFRA_ON(pAd) && (i == 1))
1910                                Rssi = RTMPMaxRssi(pAd,
1911                                                   pRssi->AvgRssi0,
1912                                                   pRssi->AvgRssi1,
1913                                                   pRssi->AvgRssi2);
1914                        else
1915                                Rssi = RTMPMaxRssi(pAd,
1916                                                   pEntry->RssiSample.AvgRssi0,
1917                                                   pEntry->RssiSample.AvgRssi1,
1918                                                   pEntry->RssiSample.AvgRssi2);
1919
1920                        TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1921                            pEntry->OneSecTxRetryOkCount +
1922                            pEntry->OneSecTxFailCount;
1923
1924                        if (TxTotalCnt)
1925                                TxErrorRatio =
1926                                    ((pEntry->OneSecTxRetryOkCount +
1927                                      pEntry->OneSecTxFailCount) * 100) /
1928                                    TxTotalCnt;
1929                }
1930
1931                if (TxTotalCnt) {
1932                        /*
1933                           Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1934                           We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1935                         */
1936                        if (TxErrorRatio == 100) {
1937                                TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp;
1938                                unsigned long Index;
1939                                unsigned long MACValue;
1940
1941                                RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1942                                TxRtyCfgtmp.word = TxRtyCfg.word;
1943                                TxRtyCfg.field.LongRtyLimit = 0x0;
1944                                TxRtyCfg.field.ShortRtyLimit = 0x0;
1945                                RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1946
1947                                RTMPusecDelay(1);
1948
1949                                Index = 0;
1950                                MACValue = 0;
1951                                do {
1952                                        RTMP_IO_READ32(pAd, TXRXQ_PCNT,
1953                                                       &MACValue);
1954                                        if ((MACValue & 0xffffff) == 0)
1955                                                break;
1956                                        Index++;
1957                                        RTMPusecDelay(1000);
1958                                } while ((Index < 330)
1959                                         &&
1960                                         (!RTMP_TEST_FLAG
1961                                          (pAd,
1962                                           fRTMP_ADAPTER_HALT_IN_PROGRESS)));
1963
1964                                RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1965                                TxRtyCfg.field.LongRtyLimit =
1966                                    TxRtyCfgtmp.field.LongRtyLimit;
1967                                TxRtyCfg.field.ShortRtyLimit =
1968                                    TxRtyCfgtmp.field.ShortRtyLimit;
1969                                RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1970                        }
1971                }
1972
1973                CurrRateIdx = pEntry->CurrTxRateIndex;
1974
1975                MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
1976                                      &InitTxRateIdx);
1977
1978                if (CurrRateIdx >= TableSize) {
1979                        CurrRateIdx = TableSize - 1;
1980                }
1981                /* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */
1982                /* So need to sync here. */
1983                pCurrTxRate =
1984                    (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
1985                if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1986                    /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */
1987                    ) {
1988
1989                        /* Need to sync Real Tx rate and our record. */
1990                        /* Then return for next DRS. */
1991                        pCurrTxRate =
1992                            (struct rt_rtmp_tx_rate_switch *) & pTable[(InitTxRateIdx + 1)
1993                                                            * 5];
1994                        pEntry->CurrTxRateIndex = InitTxRateIdx;
1995                        MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1996
1997                        /* reset all OneSecTx counters */
1998                        RESET_ONE_SEC_TX_CNT(pEntry);
1999                        continue;
2000                }
2001                /* decide the next upgrade rate and downgrade rate, if any */
2002                if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
2003                        UpRateIdx = CurrRateIdx + 1;
2004                        DownRateIdx = CurrRateIdx - 1;
2005                } else if (CurrRateIdx == 0) {
2006                        UpRateIdx = CurrRateIdx + 1;
2007                        DownRateIdx = CurrRateIdx;
2008                } else if (CurrRateIdx == (TableSize - 1)) {
2009                        UpRateIdx = CurrRateIdx;
2010                        DownRateIdx = CurrRateIdx - 1;
2011                }
2012
2013                pCurrTxRate =
2014                    (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
2015
2016                if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2017                        TrainUp =
2018                            (pCurrTxRate->TrainUp +
2019                             (pCurrTxRate->TrainUp >> 1));
2020                        TrainDown =
2021                            (pCurrTxRate->TrainDown +
2022                             (pCurrTxRate->TrainDown >> 1));
2023                } else {
2024                        TrainUp = pCurrTxRate->TrainUp;
2025                        TrainDown = pCurrTxRate->TrainDown;
2026                }
2027
2028                /*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */
2029
2030                /* */
2031                /* Keep the last time TxRateChangeAction status. */
2032                /* */
2033                pEntry->LastTimeTxRateChangeAction =
2034                    pEntry->LastSecTxRateChangeAction;
2035
2036                /* */
2037                /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2038                /*         (criteria copied from RT2500 for Netopia case) */
2039                /* */
2040                if (TxTotalCnt <= 15) {
2041                        char idx = 0;
2042                        u8 TxRateIdx;
2043                        u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 =
2044                            0, MCS5 = 0, MCS6 = 0, MCS7 = 0;
2045                        u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2046                        u8 MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0;  /* 3*3 */
2047
2048                        /* check the existence and index of each needed MCS */
2049                        while (idx < pTable[0]) {
2050                                pCurrTxRate =
2051                                    (struct rt_rtmp_tx_rate_switch *) & pTable[(idx + 1) *
2052                                                                    5];
2053
2054                                if (pCurrTxRate->CurrMCS == MCS_0) {
2055                                        MCS0 = idx;
2056                                } else if (pCurrTxRate->CurrMCS == MCS_1) {
2057                                        MCS1 = idx;
2058                                } else if (pCurrTxRate->CurrMCS == MCS_2) {
2059                                        MCS2 = idx;
2060                                } else if (pCurrTxRate->CurrMCS == MCS_3) {
2061                                        MCS3 = idx;
2062                                } else if (pCurrTxRate->CurrMCS == MCS_4) {
2063                                        MCS4 = idx;
2064                                } else if (pCurrTxRate->CurrMCS == MCS_5) {
2065                                        MCS5 = idx;
2066                                } else if (pCurrTxRate->CurrMCS == MCS_6) {
2067                                        MCS6 = idx;
2068                                }
2069                                /*else if (pCurrTxRate->CurrMCS == MCS_7) */
2070                                else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800))   /* prevent the highest MCS using short GI when 1T and low throughput */
2071                                {
2072                                        MCS7 = idx;
2073                                } else if (pCurrTxRate->CurrMCS == MCS_12) {
2074                                        MCS12 = idx;
2075                                } else if (pCurrTxRate->CurrMCS == MCS_13) {
2076                                        MCS13 = idx;
2077                                } else if (pCurrTxRate->CurrMCS == MCS_14) {
2078                                        MCS14 = idx;
2079                                }
2080                                else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800))  /*we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI */
2081                                {
2082                                        MCS15 = idx;
2083                                } else if (pCurrTxRate->CurrMCS == MCS_20)      /* 3*3 */
2084                                {
2085                                        MCS20 = idx;
2086                                } else if (pCurrTxRate->CurrMCS == MCS_21) {
2087                                        MCS21 = idx;
2088                                } else if (pCurrTxRate->CurrMCS == MCS_22) {
2089                                        MCS22 = idx;
2090                                } else if (pCurrTxRate->CurrMCS == MCS_23) {
2091                                        MCS23 = idx;
2092                                }
2093                                idx++;
2094                        }
2095
2096                        if (pAd->LatchRfRegs.Channel <= 14) {
2097                                if (pAd->NicConfig2.field.ExternalLNAForG) {
2098                                        RssiOffset = 2;
2099                                } else {
2100                                        RssiOffset = 5;
2101                                }
2102                        } else {
2103                                if (pAd->NicConfig2.field.ExternalLNAForA) {
2104                                        RssiOffset = 5;
2105                                } else {
2106                                        RssiOffset = 8;
2107                                }
2108                        }
2109
2110                        /*if (MCS15) */
2111                        if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) {    /* N mode with 3 stream // 3*3 */
2112                                if (MCS23 && (Rssi >= -70))
2113                                        TxRateIdx = MCS23;
2114                                else if (MCS22 && (Rssi >= -72))
2115                                        TxRateIdx = MCS22;
2116                                else if (MCS21 && (Rssi >= -76))
2117                                        TxRateIdx = MCS21;
2118                                else if (MCS20 && (Rssi >= -78))
2119                                        TxRateIdx = MCS20;
2120                                else if (MCS4 && (Rssi >= -82))
2121                                        TxRateIdx = MCS4;
2122                                else if (MCS3 && (Rssi >= -84))
2123                                        TxRateIdx = MCS3;
2124                                else if (MCS2 && (Rssi >= -86))
2125                                        TxRateIdx = MCS2;
2126                                else if (MCS1 && (Rssi >= -88))
2127                                        TxRateIdx = MCS1;
2128                                else
2129                                        TxRateIdx = MCS0;
2130                        }
2131/*              else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */
2132                        else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand))      /* 3*3 */
2133                        {       /* N mode with 2 stream */
2134                                if (MCS15 && (Rssi >= (-70 + RssiOffset)))
2135                                        TxRateIdx = MCS15;
2136                                else if (MCS14 && (Rssi >= (-72 + RssiOffset)))
2137                                        TxRateIdx = MCS14;
2138                                else if (MCS13 && (Rssi >= (-76 + RssiOffset)))
2139                                        TxRateIdx = MCS13;
2140                                else if (MCS12 && (Rssi >= (-78 + RssiOffset)))
2141                                        TxRateIdx = MCS12;
2142                                else if (MCS4 && (Rssi >= (-82 + RssiOffset)))
2143                                        TxRateIdx = MCS4;
2144                                else if (MCS3 && (Rssi >= (-84 + RssiOffset)))
2145                                        TxRateIdx = MCS3;
2146                                else if (MCS2 && (Rssi >= (-86 + RssiOffset)))
2147                                        TxRateIdx = MCS2;
2148                                else if (MCS1 && (Rssi >= (-88 + RssiOffset)))
2149                                        TxRateIdx = MCS1;
2150                                else
2151                                        TxRateIdx = MCS0;
2152                        } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) {    /* N mode with 1 stream */
2153                                if (MCS7 && (Rssi > (-72 + RssiOffset)))
2154                                        TxRateIdx = MCS7;
2155                                else if (MCS6 && (Rssi > (-74 + RssiOffset)))
2156                                        TxRateIdx = MCS6;
2157                                else if (MCS5 && (Rssi > (-77 + RssiOffset)))
2158                                        TxRateIdx = MCS5;
2159                                else if (MCS4 && (Rssi > (-79 + RssiOffset)))
2160                                        TxRateIdx = MCS4;
2161                                else if (MCS3 && (Rssi > (-81 + RssiOffset)))
2162                                        TxRateIdx = MCS3;
2163                                else if (MCS2 && (Rssi > (-83 + RssiOffset)))
2164                                        TxRateIdx = MCS2;
2165                                else if (MCS1 && (Rssi > (-86 + RssiOffset)))
2166                                        TxRateIdx = MCS1;
2167                                else
2168                                        TxRateIdx = MCS0;
2169                        } else {        /* Legacy mode */
2170                                if (MCS7 && (Rssi > -70))
2171                                        TxRateIdx = MCS7;
2172                                else if (MCS6 && (Rssi > -74))
2173                                        TxRateIdx = MCS6;
2174                                else if (MCS5 && (Rssi > -78))
2175                                        TxRateIdx = MCS5;
2176                                else if (MCS4 && (Rssi > -82))
2177                                        TxRateIdx = MCS4;
2178                                else if (MCS4 == 0)     /* for B-only mode */
2179                                        TxRateIdx = MCS3;
2180                                else if (MCS3 && (Rssi > -85))
2181                                        TxRateIdx = MCS3;
2182                                else if (MCS2 && (Rssi > -87))
2183                                        TxRateIdx = MCS2;
2184                                else if (MCS1 && (Rssi > -90))
2185                                        TxRateIdx = MCS1;
2186                                else
2187                                        TxRateIdx = MCS0;
2188                        }
2189
2190                        /*              if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */
2191                        {
2192                                pEntry->CurrTxRateIndex = TxRateIdx;
2193                                pNextTxRate =
2194                                    (struct rt_rtmp_tx_rate_switch *) &
2195                                    pTable[(pEntry->CurrTxRateIndex + 1) * 5];
2196                                MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2197                        }
2198
2199                        NdisZeroMemory(pEntry->TxQuality,
2200                                       sizeof(u16)*
2201                                       MAX_STEP_OF_TX_RATE_SWITCH);
2202                        NdisZeroMemory(pEntry->PER,
2203                                       sizeof(u8)*
2204                                       MAX_STEP_OF_TX_RATE_SWITCH);
2205                        pEntry->fLastSecAccordingRSSI = TRUE;
2206                        /* reset all OneSecTx counters */
2207                        RESET_ONE_SEC_TX_CNT(pEntry);
2208
2209                        continue;
2210                }
2211
2212                if (pEntry->fLastSecAccordingRSSI == TRUE) {
2213                        pEntry->fLastSecAccordingRSSI = FALSE;
2214                        pEntry->LastSecTxRateChangeAction = 0;
2215                        /* reset all OneSecTx counters */
2216                        RESET_ONE_SEC_TX_CNT(pEntry);
2217
2218                        continue;
2219                }
2220
2221                do {
2222                        BOOLEAN bTrainUpDown = FALSE;
2223
2224                        pEntry->CurrTxRateStableTime++;
2225
2226                        /* downgrade TX quality if PER >= Rate-Down threshold */
2227                        if (TxErrorRatio >= TrainDown) {
2228                                bTrainUpDown = TRUE;
2229                                pEntry->TxQuality[CurrRateIdx] =
2230                                    DRS_TX_QUALITY_WORST_BOUND;
2231                        }
2232                        /* upgrade TX quality if PER <= Rate-Up threshold */
2233                        else if (TxErrorRatio <= TrainUp) {
2234                                bTrainUpDown = TRUE;
2235                                bUpgradeQuality = TRUE;
2236                                if (pEntry->TxQuality[CurrRateIdx])
2237                                        pEntry->TxQuality[CurrRateIdx]--;       /* quality very good in CurrRate */
2238
2239                                if (pEntry->TxRateUpPenalty)
2240                                        pEntry->TxRateUpPenalty--;
2241                                else if (pEntry->TxQuality[UpRateIdx])
2242                                        pEntry->TxQuality[UpRateIdx]--; /* may improve next UP rate's quality */
2243                        }
2244
2245                        pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio;
2246
2247                        if (bTrainUpDown) {
2248                                /* perform DRS - consider TxRate Down first, then rate up. */
2249                                if ((CurrRateIdx != DownRateIdx)
2250                                    && (pEntry->TxQuality[CurrRateIdx] >=
2251                                        DRS_TX_QUALITY_WORST_BOUND)) {
2252                                        pEntry->CurrTxRateIndex = DownRateIdx;
2253                                } else if ((CurrRateIdx != UpRateIdx)
2254                                           && (pEntry->TxQuality[UpRateIdx] <=
2255                                               0)) {
2256                                        pEntry->CurrTxRateIndex = UpRateIdx;
2257                                }
2258                        }
2259                } while (FALSE);
2260
2261                /* if rate-up happen, clear all bad history of all TX rates */
2262                if (pEntry->CurrTxRateIndex > CurrRateIdx) {
2263                        pEntry->CurrTxRateStableTime = 0;
2264                        pEntry->TxRateUpPenalty = 0;
2265                        pEntry->LastSecTxRateChangeAction = 1;  /* rate UP */
2266                        NdisZeroMemory(pEntry->TxQuality,
2267                                       sizeof(u16)*
2268                                       MAX_STEP_OF_TX_RATE_SWITCH);
2269                        NdisZeroMemory(pEntry->PER,
2270                                       sizeof(u8)*
2271                                       MAX_STEP_OF_TX_RATE_SWITCH);
2272
2273                        /* */
2274                        /* For TxRate fast train up */
2275                        /* */
2276                        if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2277                                RTMPSetTimer(&pAd->StaCfg.
2278                                             StaQuickResponeForRateUpTimer,
2279                                             100);
2280
2281                                pAd->StaCfg.
2282                                    StaQuickResponeForRateUpTimerRunning = TRUE;
2283                        }
2284                        bTxRateChanged = TRUE;
2285                }
2286                /* if rate-down happen, only clear DownRate's bad history */
2287                else if (pEntry->CurrTxRateIndex < CurrRateIdx) {
2288                        pEntry->CurrTxRateStableTime = 0;
2289                        pEntry->TxRateUpPenalty = 0;    /* no penalty */
2290                        pEntry->LastSecTxRateChangeAction = 2;  /* rate DOWN */
2291                        pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2292                        pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2293
2294                        /* */
2295                        /* For TxRate fast train down */
2296                        /* */
2297                        if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2298                                RTMPSetTimer(&pAd->StaCfg.
2299                                             StaQuickResponeForRateUpTimer,
2300                                             100);
2301
2302                                pAd->StaCfg.
2303                                    StaQuickResponeForRateUpTimerRunning = TRUE;
2304                        }
2305                        bTxRateChanged = TRUE;
2306                } else {
2307                        pEntry->LastSecTxRateChangeAction = 0;  /* rate no change */
2308                        bTxRateChanged = FALSE;
2309                }
2310
2311                pEntry->LastTxOkCount = TxSuccess;
2312                {
2313                        u8 tmpTxRate;
2314
2315                        /* to fix tcp ack issue */
2316                        if (!bTxRateChanged
2317                            && (pAd->RalinkCounters.OneSecReceivedByteCount >
2318                                (pAd->RalinkCounters.
2319                                 OneSecTransmittedByteCount * 5))) {
2320                                tmpTxRate = DownRateIdx;
2321                                DBGPRINT_RAW(RT_DEBUG_TRACE,
2322                                             ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2323                                              pAd->RalinkCounters.
2324                                              OneSecReceivedByteCount,
2325                                              pAd->RalinkCounters.
2326                                              OneSecTransmittedByteCount,
2327                                              pEntry->CurrTxRateIndex,
2328                                              tmpTxRate));
2329                        } else {
2330                                tmpTxRate = pEntry->CurrTxRateIndex;
2331                        }
2332
2333                        pNextTxRate =
2334                            (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) *
2335                                                            5];
2336                }
2337                if (bTxRateChanged && pNextTxRate) {
2338                        MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2339                }
2340                /* reset all OneSecTx counters */
2341                RESET_ONE_SEC_TX_CNT(pEntry);
2342        }
2343}
2344
2345/*
2346        ========================================================================
2347        Routine Description:
2348                Station side, Auto TxRate faster train up timer call back function.
2349
2350        Arguments:
2351                SystemSpecific1                 - Not used.
2352                FunctionContext                 - Pointer to our Adapter context.
2353                SystemSpecific2                 - Not used.
2354                SystemSpecific3                 - Not used.
2355
2356        Return Value:
2357                None
2358
2359        ========================================================================
2360*/
2361void StaQuickResponeForRateUpExec(void *SystemSpecific1,
2362                                  void *FunctionContext,
2363                                  void *SystemSpecific2,
2364                                  void *SystemSpecific3)
2365{
2366        struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
2367        u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2368        unsigned long TxTotalCnt;
2369        unsigned long TxErrorRatio = 0;
2370        BOOLEAN bTxRateChanged; /*, bUpgradeQuality = FALSE; */
2371        struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
2372        u8 *pTable;
2373        u8 TableSize = 0;
2374        u8 InitTxRateIdx = 0, TrainUp, TrainDown;
2375        TX_STA_CNT1_STRUC StaTx1;
2376        TX_STA_CNT0_STRUC TxStaCnt0;
2377        char Rssi, ratio;
2378        unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2379        struct rt_mac_table_entry *pEntry;
2380        unsigned long i;
2381
2382        pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2383
2384        /* */
2385        /* walk through MAC table, see if need to change AP's TX rate toward each entry */
2386        /* */
2387        for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
2388                pEntry = &pAd->MacTab.Content[i];
2389
2390                /* check if this entry need to switch rate automatically */
2391                if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2392                        continue;
2393
2394                if (INFRA_ON(pAd) && (i == 1))
2395                        Rssi = RTMPMaxRssi(pAd,
2396                                           pAd->StaCfg.RssiSample.AvgRssi0,
2397                                           pAd->StaCfg.RssiSample.AvgRssi1,
2398                                           pAd->StaCfg.RssiSample.AvgRssi2);
2399                else
2400                        Rssi = RTMPMaxRssi(pAd,
2401                                           pEntry->RssiSample.AvgRssi0,
2402                                           pEntry->RssiSample.AvgRssi1,
2403                                           pEntry->RssiSample.AvgRssi2);
2404
2405                CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2406
2407                MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
2408                                      &InitTxRateIdx);
2409
2410                /* decide the next upgrade rate and downgrade rate, if any */
2411                if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
2412                        UpRateIdx = CurrRateIdx + 1;
2413                        DownRateIdx = CurrRateIdx - 1;
2414                } else if (CurrRateIdx == 0) {
2415                        UpRateIdx = CurrRateIdx + 1;
2416                        DownRateIdx = CurrRateIdx;
2417                } else if (CurrRateIdx == (TableSize - 1)) {
2418                        UpRateIdx = CurrRateIdx;
2419                        DownRateIdx = CurrRateIdx - 1;
2420                }
2421
2422                pCurrTxRate =
2423                    (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
2424
2425                if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2426                        TrainUp =
2427                            (pCurrTxRate->TrainUp +
2428                             (pCurrTxRate->TrainUp >> 1));
2429                        TrainDown =
2430                            (pCurrTxRate->TrainDown +
2431                             (pCurrTxRate->TrainDown >> 1));
2432                } else {
2433                        TrainUp = pCurrTxRate->TrainUp;
2434                        TrainDown = pCurrTxRate->TrainDown;
2435                }
2436
2437                if (pAd->MacTab.Size == 1) {
2438                        /* Update statistic counter */
2439                        RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2440                        RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2441
2442                        TxRetransmit = StaTx1.field.TxRetransmit;
2443                        TxSuccess = StaTx1.field.TxSuccess;
2444                        TxFailCount = TxStaCnt0.field.TxFailCount;
2445                        TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2446
2447                        pAd->RalinkCounters.OneSecTxRetryOkCount +=
2448                            StaTx1.field.TxRetransmit;
2449                        pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
2450                            StaTx1.field.TxSuccess;
2451                        pAd->RalinkCounters.OneSecTxFailCount +=
2452                            TxStaCnt0.field.TxFailCount;
2453                        pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
2454                            StaTx1.field.TxSuccess;
2455                        pAd->WlanCounters.RetryCount.u.LowPart +=
2456                            StaTx1.field.TxRetransmit;
2457                        pAd->WlanCounters.FailedCount.u.LowPart +=
2458                            TxStaCnt0.field.TxFailCount;
2459
2460                        if (TxTotalCnt)
2461                                TxErrorRatio =
2462                                    ((TxRetransmit +
2463                                      TxFailCount) * 100) / TxTotalCnt;
2464                } else {
2465                        TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2466                            pEntry->OneSecTxRetryOkCount +
2467                            pEntry->OneSecTxFailCount;
2468
2469                        if (TxTotalCnt)
2470                                TxErrorRatio =
2471                                    ((pEntry->OneSecTxRetryOkCount +
2472                                      pEntry->OneSecTxFailCount) * 100) /
2473                                    TxTotalCnt;
2474                }
2475
2476                /* */
2477                /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2478                /*         (criteria copied from RT2500 for Netopia case) */
2479                /* */
2480                if (TxTotalCnt <= 12) {
2481                        NdisZeroMemory(pAd->DrsCounters.TxQuality,
2482                                       sizeof(u16)*
2483                                       MAX_STEP_OF_TX_RATE_SWITCH);
2484                        NdisZeroMemory(pAd->DrsCounters.PER,
2485                                       sizeof(u8)*
2486                                       MAX_STEP_OF_TX_RATE_SWITCH);
2487
2488                        if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2489                            && (CurrRateIdx != DownRateIdx)) {
2490                                pAd->CommonCfg.TxRateIndex = DownRateIdx;
2491                                pAd->DrsCounters.TxQuality[CurrRateIdx] =
2492                                    DRS_TX_QUALITY_WORST_BOUND;
2493                        } else
2494                            if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2495                                 2) && (CurrRateIdx != UpRateIdx)) {
2496                                pAd->CommonCfg.TxRateIndex = UpRateIdx;
2497                        }
2498
2499                        DBGPRINT_RAW(RT_DEBUG_TRACE,
2500                                     ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2501                        return;
2502                }
2503
2504                do {
2505                        unsigned long OneSecTxNoRetryOKRationCount;
2506
2507                        if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2508                                ratio = 5;
2509                        else
2510                                ratio = 4;
2511
2512                        /* downgrade TX quality if PER >= Rate-Down threshold */
2513                        if (TxErrorRatio >= TrainDown) {
2514                                pAd->DrsCounters.TxQuality[CurrRateIdx] =
2515                                    DRS_TX_QUALITY_WORST_BOUND;
2516                        }
2517
2518                        pAd->DrsCounters.PER[CurrRateIdx] =
2519                            (u8)TxErrorRatio;
2520
2521                        OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2522
2523                        /* perform DRS - consider TxRate Down first, then rate up. */
2524                        if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2525                            && (CurrRateIdx != DownRateIdx)) {
2526                                if ((pAd->DrsCounters.LastTxOkCount + 2) >=
2527                                    OneSecTxNoRetryOKRationCount) {
2528                                        pAd->CommonCfg.TxRateIndex =
2529                                            DownRateIdx;
2530                                        pAd->DrsCounters.
2531                                            TxQuality[CurrRateIdx] =
2532                                            DRS_TX_QUALITY_WORST_BOUND;
2533
2534                                }
2535
2536                        } else
2537                            if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2538                                 2) && (CurrRateIdx != UpRateIdx)) {
2539                                if ((TxErrorRatio >= 50)
2540                                    || (TxErrorRatio >= TrainDown)) {
2541
2542                                } else if ((pAd->DrsCounters.LastTxOkCount + 2)
2543                                           >= OneSecTxNoRetryOKRationCount) {
2544                                        pAd->CommonCfg.TxRateIndex = UpRateIdx;
2545                                }
2546                        }
2547                } while (FALSE);
2548
2549                /* if rate-up happen, clear all bad history of all TX rates */
2550                if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) {
2551                        pAd->DrsCounters.TxRateUpPenalty = 0;
2552                        NdisZeroMemory(pAd->DrsCounters.TxQuality,
2553                                       sizeof(u16)*
2554                                       MAX_STEP_OF_TX_RATE_SWITCH);
2555                        NdisZeroMemory(pAd->DrsCounters.PER,
2556                                       sizeof(u8)*
2557                                       MAX_STEP_OF_TX_RATE_SWITCH);
2558                        bTxRateChanged = TRUE;
2559                }
2560                /* if rate-down happen, only clear DownRate's bad history */
2561                else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) {
2562                        DBGPRINT_RAW(RT_DEBUG_TRACE,
2563                                     ("QuickDRS: --TX rate from %d to %d \n",
2564                                      CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2565
2566                        pAd->DrsCounters.TxRateUpPenalty = 0;   /* no penalty */
2567                        pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] =
2568                            0;
2569                        pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2570                        bTxRateChanged = TRUE;
2571                } else {
2572                        bTxRateChanged = FALSE;
2573                }
2574
2575                pNextTxRate =
2576                    (struct rt_rtmp_tx_rate_switch *) &
2577                    pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5];
2578                if (bTxRateChanged && pNextTxRate) {
2579                        MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2580                }
2581        }
2582}
2583
2584/*
2585        ==========================================================================
2586        Description:
2587                This routine is executed periodically inside MlmePeriodicExec() after
2588                association with an AP.
2589                It checks if StaCfg.Psm is consistent with user policy (recorded in
2590                StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2591                there're some conditions to consider:
2592                1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2593                   the time when Mibss==TRUE
2594                2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2595                   if outgoing traffic available in TxRing or MgmtRing.
2596        Output:
2597                1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2598
2599        IRQL = DISPATCH_LEVEL
2600
2601        ==========================================================================
2602 */
2603void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32)
2604{
2605        unsigned long PowerMode;
2606
2607        /* condition - */
2608        /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */
2609        /* 2. user wants either MAX_PSP or FAST_PSP */
2610        /* 3. but current psm is not in PWR_SAVE */
2611        /* 4. CNTL state machine is not doing SCANning */
2612        /* 5. no TX SUCCESS event for the past 1-sec period */
2613        PowerMode = pAd->StaCfg.WindowsPowerMode;
2614
2615        if (INFRA_ON(pAd) &&
2616            (PowerMode != Ndis802_11PowerModeCAM) &&
2617            (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2618/*              (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */
2619            (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
2620            RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2621            /*&&
2622               (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2623               (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2624            ) {
2625                NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2626                pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2627                RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
2628                if (!
2629                    (pAd->CommonCfg.bAPSDCapable
2630                     && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
2631                        RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2632                } else {
2633                        RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2634                }
2635        }
2636}
2637
2638/* IRQL = PASSIVE_LEVEL */
2639/* IRQL = DISPATCH_LEVEL */
2640void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm)
2641{
2642        AUTO_RSP_CFG_STRUC csr4;
2643
2644        pAd->StaCfg.Psm = psm;
2645        RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2646        csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0;
2647        RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2648
2649        DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2650}
2651
2652/*
2653        ==========================================================================
2654        Description:
2655                This routine calculates TxPER, RxPER of the past N-sec period. And
2656                according to the calculation result, ChannelQuality is calculated here
2657                to decide if current AP is still doing the job.
2658
2659                If ChannelQuality is not good, a ROAMing attempt may be tried later.
2660        Output:
2661                StaCfg.ChannelQuality - 0..100
2662
2663        IRQL = DISPATCH_LEVEL
2664
2665        NOTE: This routine decide channle quality based on RX CRC error ratio.
2666                Caller should make sure a function call to NICUpdateRawCounters(pAd)
2667                is performed right before this routine, so that this routine can decide
2668                channel quality based on the most up-to-date information
2669        ==========================================================================
2670 */
2671void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd,
2672                                 struct rt_mac_table_entry *pMacEntry, unsigned long Now32)
2673{
2674        unsigned long TxOkCnt, TxCnt, TxPER, TxPRR;
2675        unsigned long RxCnt, RxPER;
2676        u8 NorRssi;
2677        char MaxRssi;
2678        struct rt_rssi_sample *pRssiSample = NULL;
2679        u32 OneSecTxNoRetryOkCount = 0;
2680        u32 OneSecTxRetryOkCount = 0;
2681        u32 OneSecTxFailCount = 0;
2682        u32 OneSecRxOkCnt = 0;
2683        u32 OneSecRxFcsErrCnt = 0;
2684        unsigned long ChannelQuality = 0;       /* 0..100, Channel Quality Indication for Roaming */
2685        unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime;
2686
2687        if (pAd->OpMode == OPMODE_STA) {
2688                pRssiSample = &pAd->StaCfg.RssiSample;
2689                OneSecTxNoRetryOkCount =
2690                    pAd->RalinkCounters.OneSecTxNoRetryOkCount;
2691                OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2692                OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2693                OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2694                OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
2695        }
2696
2697        MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
2698                              pRssiSample->LastRssi1, pRssiSample->LastRssi2);
2699
2700        /* */
2701        /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */
2702        /* */
2703        TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2704        TxCnt = TxOkCnt + OneSecTxFailCount;
2705        if (TxCnt < 5) {
2706                TxPER = 0;
2707                TxPRR = 0;
2708        } else {
2709                TxPER = (OneSecTxFailCount * 100) / TxCnt;
2710                TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2711        }
2712
2713        /* */
2714        /* calculate RX PER - don't take RxPER into consideration if too few sample */
2715        /* */
2716        RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2717        if (RxCnt < 5)
2718                RxPER = 0;
2719        else
2720                RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
2721
2722        /* */
2723        /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */
2724        /* */
2725        if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) &&     /* no heavy traffic */
2726            ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) {
2727                DBGPRINT(RT_DEBUG_TRACE,
2728                         ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2729                          BeaconLostTime, TxOkCnt));
2730                ChannelQuality = 0;
2731        } else {
2732                /* Normalize Rssi */
2733                if (MaxRssi > -40)
2734                        NorRssi = 100;
2735                else if (MaxRssi < -90)
2736                        NorRssi = 0;
2737                else
2738                        NorRssi = (MaxRssi + 90) * 2;
2739
2740                /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER        (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */
2741                ChannelQuality = (RSSI_WEIGHTING * NorRssi +
2742                                  TX_WEIGHTING * (100 - TxPRR) +
2743                                  RX_WEIGHTING * (100 - RxPER)) / 100;
2744        }
2745
2746        if (pAd->OpMode == OPMODE_STA)
2747                pAd->Mlme.ChannelQuality =
2748                    (ChannelQuality > 100) ? 100 : ChannelQuality;
2749
2750}
2751
2752/* IRQL = DISPATCH_LEVEL */
2753void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble)
2754{
2755        AUTO_RSP_CFG_STRUC csr4;
2756
2757        /* */
2758        /* Always use Long preamble before verifiation short preamble functionality works well. */
2759        /* Todo: remove the following line if short preamble functionality works */
2760        /* */
2761        /*TxPreamble = Rt802_11PreambleLong; */
2762
2763        RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2764        if (TxPreamble == Rt802_11PreambleLong) {
2765                DBGPRINT(RT_DEBUG_TRACE,
2766                         ("MlmeSetTxPreamble (= long PREAMBLE)\n"));
2767                OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2768                csr4.field.AutoResponderPreamble = 0;
2769        } else {
2770                /* NOTE: 1Mbps should always use long preamble */
2771                DBGPRINT(RT_DEBUG_TRACE,
2772                         ("MlmeSetTxPreamble (= short PREAMBLE)\n"));
2773                OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2774                csr4.field.AutoResponderPreamble = 1;
2775        }
2776
2777        RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2778}
2779
2780/*
2781    ==========================================================================
2782    Description:
2783        Update basic rate bitmap
2784    ==========================================================================
2785 */
2786
2787void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter)
2788{
2789        int i, j;
2790        /* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
2791        u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2792        u8 *sup_p = pAdapter->CommonCfg.SupRate;
2793        u8 *ext_p = pAdapter->CommonCfg.ExtRate;
2794        unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2795
2796        /* if A mode, always use fix BasicRateBitMap */
2797        /*if (pAdapter->CommonCfg.Channel == PHY_11A) */
2798        if (pAdapter->CommonCfg.Channel > 14)
2799                pAdapter->CommonCfg.BasicRateBitmap = 0x150;    /* 6, 12, 24M */
2800        /* End of if */
2801
2802        if (pAdapter->CommonCfg.BasicRateBitmap > 4095) {
2803                /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2804                return;
2805        }
2806        /* End of if */
2807        for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2808                sup_p[i] &= 0x7f;
2809                ext_p[i] &= 0x7f;
2810        }                       /* End of for */
2811
2812        for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2813                if (bitmap & (1 << i)) {
2814                        for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2815                                if (sup_p[j] == rate[i])
2816                                        sup_p[j] |= 0x80;
2817                                /* End of if */
2818                        }       /* End of for */
2819
2820                        for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2821                                if (ext_p[j] == rate[i])
2822                                        ext_p[j] |= 0x80;
2823                                /* End of if */
2824                        }       /* End of for */
2825                }               /* End of if */
2826        }                       /* End of for */
2827}                               /* End of UpdateBasicRateBitmap */
2828
2829/* IRQL = PASSIVE_LEVEL */
2830/* IRQL = DISPATCH_LEVEL */
2831/* bLinkUp is to identify the initial link speed. */
2832/* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */
2833void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx)
2834{
2835        int i, num;
2836        u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2837        u8 MinSupport = RATE_54;
2838        unsigned long BasicRateBitmap = 0;
2839        u8 CurrBasicRate = RATE_1;
2840        u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2841        PHTTRANSMIT_SETTING pHtPhy = NULL;
2842        PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2843        PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2844        BOOLEAN *auto_rate_cur_p;
2845        u8 HtMcs = MCS_AUTO;
2846
2847        /* find max desired rate */
2848        UpdateBasicRateBitmap(pAd);
2849
2850        num = 0;
2851        auto_rate_cur_p = NULL;
2852        for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2853                switch (pAd->CommonCfg.DesireRate[i] & 0x7f) {
2854                case 2:
2855                        Rate = RATE_1;
2856                        num++;
2857                        break;
2858                case 4:
2859                        Rate = RATE_2;
2860                        num++;
2861                        break;
2862                case 11:
2863                        Rate = RATE_5_5;
2864                        num++;
2865                        break;
2866                case 22:
2867                        Rate = RATE_11;
2868                        num++;
2869                        break;
2870                case 12:
2871                        Rate = RATE_6;
2872                        num++;
2873                        break;
2874                case 18:
2875                        Rate = RATE_9;
2876                        num++;
2877                        break;
2878                case 24:
2879                        Rate = RATE_12;
2880                        num++;
2881                        break;
2882                case 36:
2883                        Rate = RATE_18;
2884                        num++;
2885                        break;
2886                case 48:
2887                        Rate = RATE_24;
2888                        num++;
2889                        break;
2890                case 72:
2891                        Rate = RATE_36;
2892                        num++;
2893                        break;
2894                case 96:
2895                        Rate = RATE_48;
2896                        num++;
2897                        break;
2898                case 108:
2899                        Rate = RATE_54;
2900                        num++;
2901                        break;
2902                        /*default: Rate = RATE_1;   break; */
2903                }
2904                if (MaxDesire < Rate)
2905                        MaxDesire = Rate;
2906        }
2907
2908/*=========================================================================== */
2909/*=========================================================================== */
2910        {
2911                pHtPhy = &pAd->StaCfg.HTPhyMode;
2912                pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2913                pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2914
2915                auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2916                HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2917
2918                if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2919                    (pAd->CommonCfg.PhyMode == PHY_11B) &&
2920                    (MaxDesire > RATE_11)) {
2921                        MaxDesire = RATE_11;
2922                }
2923        }
2924
2925        pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2926        pMinHtPhy->word = 0;
2927        pMaxHtPhy->word = 0;
2928        pHtPhy->word = 0;
2929
2930        /* Auto rate switching is enabled only if more than one DESIRED RATES are */
2931        /* specified; otherwise disabled */
2932        if (num <= 1) {
2933                /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2934                /*pAd->CommonCfg.bAutoTxRateSwitch      = FALSE; */
2935                *auto_rate_cur_p = FALSE;
2936        } else {
2937                /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2938                /*pAd->CommonCfg.bAutoTxRateSwitch      = TRUE; */
2939                *auto_rate_cur_p = TRUE;
2940        }
2941
2942        if (HtMcs != MCS_AUTO) {
2943                /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2944                /*pAd->CommonCfg.bAutoTxRateSwitch      = FALSE; */
2945                *auto_rate_cur_p = FALSE;
2946        } else {
2947                /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2948                /*pAd->CommonCfg.bAutoTxRateSwitch      = TRUE; */
2949                *auto_rate_cur_p = TRUE;
2950        }
2951
2952        if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
2953                pSupRate = &pAd->StaActive.SupRate[0];
2954                pExtRate = &pAd->StaActive.ExtRate[0];
2955                SupRateLen = pAd->StaActive.SupRateLen;
2956                ExtRateLen = pAd->StaActive.ExtRateLen;
2957        } else {
2958                pSupRate = &pAd->CommonCfg.SupRate[0];
2959                pExtRate = &pAd->CommonCfg.ExtRate[0];
2960                SupRateLen = pAd->CommonCfg.SupRateLen;
2961                ExtRateLen = pAd->CommonCfg.ExtRateLen;
2962        }
2963
2964        /* find max supported rate */
2965        for (i = 0; i < SupRateLen; i++) {
2966                switch (pSupRate[i] & 0x7f) {
2967                case 2:
2968                        Rate = RATE_1;
2969                        if (pSupRate[i] & 0x80)
2970                                BasicRateBitmap |= 0x0001;
2971                        break;
2972                case 4:
2973                        Rate = RATE_2;
2974                        if (pSupRate[i] & 0x80)
2975                                BasicRateBitmap |= 0x0002;
2976                        break;
2977                case 11:
2978                        Rate = RATE_5_5;
2979                        if (pSupRate[i] & 0x80)
2980                                BasicRateBitmap |= 0x0004;
2981                        break;
2982                case 22:
2983                        Rate = RATE_11;
2984                        if (pSupRate[i] & 0x80)
2985                                BasicRateBitmap |= 0x0008;
2986                        break;
2987                case 12:
2988                        Rate = RATE_6;  /*if (pSupRate[i] & 0x80) */
2989                        BasicRateBitmap |= 0x0010;
2990                        break;
2991                case 18:
2992                        Rate = RATE_9;
2993                        if (pSupRate[i] & 0x80)
2994                                BasicRateBitmap |= 0x0020;
2995                        break;
2996                case 24:
2997                        Rate = RATE_12; /*if (pSupRate[i] & 0x80) */
2998                        BasicRateBitmap |= 0x0040;
2999                        break;
3000                case 36:
3001                        Rate = RATE_18;
3002                        if (pSupRate[i] & 0x80)
3003                                BasicRateBitmap |= 0x0080;
3004                        break;
3005                case 48:
3006                        Rate = RATE_24; /*if (pSupRate[i] & 0x80) */
3007                        BasicRateBitmap |= 0x0100;
3008                        break;
3009                case 72:
3010                        Rate = RATE_36;
3011                        if (pSupRate[i] & 0x80)
3012                                BasicRateBitmap |= 0x0200;
3013                        break;
3014                case 96:
3015                        Rate = RATE_48;
3016                        if (pSupRate[i] & 0x80)
3017                                BasicRateBitmap |= 0x0400;
3018                        break;
3019                case 108:
3020                        Rate = RATE_54;
3021                        if (pSupRate[i] & 0x80)
3022                                BasicRateBitmap |= 0x0800;
3023                        break;
3024                default:
3025                        Rate = RATE_1;
3026                        break;
3027                }
3028                if (MaxSupport < Rate)
3029                        MaxSupport = Rate;
3030
3031                if (MinSupport > Rate)
3032                        MinSupport = Rate;
3033        }
3034
3035        for (i = 0; i < ExtRateLen; i++) {
3036                switch (pExtRate[i] & 0x7f) {
3037                case 2:
3038                        Rate = RATE_1;
3039                        if (pExtRate[i] & 0x80)
3040                                BasicRateBitmap |= 0x0001;
3041                        break;
3042                case 4:
3043                        Rate = RATE_2;
3044                        if (pExtRate[i] & 0x80)
3045                                BasicRateBitmap |= 0x0002;
3046                        break;
3047                case 11:
3048                        Rate = RATE_5_5;
3049                        if (pExtRate[i] & 0x80)
3050                                BasicRateBitmap |= 0x0004;
3051                        break;
3052                case 22:
3053                        Rate = RATE_11;
3054                        if (pExtRate[i] & 0x80)
3055                                BasicRateBitmap |= 0x0008;
3056                        break;
3057                case 12:
3058                        Rate = RATE_6;  /*if (pExtRate[i] & 0x80) */
3059                        BasicRateBitmap |= 0x0010;
3060                        break;
3061                case 18:
3062                        Rate = RATE_9;
3063                        if (pExtRate[i] & 0x80)
3064                                BasicRateBitmap |= 0x0020;
3065                        break;
3066                case 24:
3067                        Rate = RATE_12; /*if (pExtRate[i] & 0x80) */
3068                        BasicRateBitmap |= 0x0040;
3069                        break;
3070                case 36:
3071                        Rate = RATE_18;
3072                        if (pExtRate[i] & 0x80)
3073                                BasicRateBitmap |= 0x0080;
3074                        break;
3075                case 48:
3076                        Rate = RATE_24; /*if (pExtRate[i] & 0x80) */
3077                        BasicRateBitmap |= 0x0100;
3078                        break;
3079                case 72:
3080                        Rate = RATE_36;
3081                        if (pExtRate[i] & 0x80)
3082                                BasicRateBitmap |= 0x0200;
3083                        break;
3084                case 96:
3085                        Rate = RATE_48;
3086                        if (pExtRate[i] & 0x80)
3087                                BasicRateBitmap |= 0x0400;
3088                        break;
3089                case 108:
3090                        Rate = RATE_54;
3091                        if (pExtRate[i] & 0x80)
3092                                BasicRateBitmap |= 0x0800;
3093                        break;
3094                default:
3095                        Rate = RATE_1;
3096                        break;
3097                }
3098                if (MaxSupport < Rate)
3099                        MaxSupport = Rate;
3100
3101                if (MinSupport > Rate)
3102                        MinSupport = Rate;
3103        }
3104
3105        RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3106
3107        /* bug fix */
3108        /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */
3109
3110        /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */
3111        /* the DURATION field of outgoing uniicast DATA/MGMT frame */
3112        for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
3113                if (BasicRateBitmap & (0x01 << i))
3114                        CurrBasicRate = (u8)i;
3115                pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3116        }
3117
3118        DBGPRINT(RT_DEBUG_TRACE,
3119                 ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3120                  RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3121        /* max tx rate = min {max desire rate, max supported rate} */
3122        if (MaxSupport < MaxDesire)
3123                pAd->CommonCfg.MaxTxRate = MaxSupport;
3124        else
3125                pAd->CommonCfg.MaxTxRate = MaxDesire;
3126
3127        pAd->CommonCfg.MinTxRate = MinSupport;
3128        /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */
3129        /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */
3130        /* on average RSSI */
3131        /*       1. RSSI >= -70db, start at 54 Mbps (short distance) */
3132        /*       2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */
3133        /*       3. -75 > RSSI, start at 11 Mbps (long distance) */
3134        if (*auto_rate_cur_p) {
3135                short dbm = 0;
3136
3137                dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3138
3139                if (bLinkUp == TRUE)
3140                        pAd->CommonCfg.TxRate = RATE_24;
3141                else
3142                        pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3143
3144                if (dbm < -75)
3145                        pAd->CommonCfg.TxRate = RATE_11;
3146                else if (dbm < -70)
3147                        pAd->CommonCfg.TxRate = RATE_24;
3148
3149                /* should never exceed MaxTxRate (consider 11B-only mode) */
3150                if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3151                        pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3152
3153                pAd->CommonCfg.TxRateIndex = 0;
3154        } else {
3155                pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3156                pHtPhy->field.MCS =
3157                    (pAd->CommonCfg.MaxTxRate >
3158                     3) ? (pAd->CommonCfg.MaxTxRate -
3159                           4) : pAd->CommonCfg.MaxTxRate;
3160                pHtPhy->field.MODE =
3161                    (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3162
3163                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC =
3164                    pHtPhy->field.STBC;
3165                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI =
3166                    pHtPhy->field.ShortGI;
3167                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS =
3168                    pHtPhy->field.MCS;
3169                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE =
3170                    pHtPhy->field.MODE;
3171        }
3172
3173        if (pAd->CommonCfg.TxRate <= RATE_11) {
3174                pMaxHtPhy->field.MODE = MODE_CCK;
3175                pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3176                pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3177        } else {
3178                pMaxHtPhy->field.MODE = MODE_OFDM;
3179                pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3180                if (pAd->CommonCfg.MinTxRate >= RATE_6
3181                    && (pAd->CommonCfg.MinTxRate <= RATE_54)) {
3182                        pMinHtPhy->field.MCS =
3183                            OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
3184                } else {
3185                        pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3186                }
3187        }
3188
3189        pHtPhy->word = (pMaxHtPhy->word);
3190        if (bLinkUp && (pAd->OpMode == OPMODE_STA)) {
3191                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3192                pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word =
3193                    pMaxHtPhy->word;
3194                pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word =
3195                    pMinHtPhy->word;
3196        } else {
3197                switch (pAd->CommonCfg.PhyMode) {
3198                case PHY_11BG_MIXED:
3199                case PHY_11B:
3200                case PHY_11BGN_MIXED:
3201                        pAd->CommonCfg.MlmeRate = RATE_1;
3202                        pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3203                        pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3204
3205/*#ifdef        WIFI_TEST */
3206                        pAd->CommonCfg.RtsRate = RATE_11;
3207/*#else */
3208/*                              pAd->CommonCfg.RtsRate = RATE_1; */
3209/*#endif */
3210                        break;
3211                case PHY_11G:
3212                case PHY_11A:
3213                case PHY_11AGN_MIXED:
3214                case PHY_11GN_MIXED:
3215                case PHY_11N_2_4G:
3216                case PHY_11AN_MIXED:
3217                case PHY_11N_5G:
3218                        pAd->CommonCfg.MlmeRate = RATE_6;
3219                        pAd->CommonCfg.RtsRate = RATE_6;
3220                        pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3221                        pAd->CommonCfg.MlmeTransmit.field.MCS =
3222                            OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3223                        break;
3224                case PHY_11ABG_MIXED:
3225                case PHY_11ABGN_MIXED:
3226                        if (pAd->CommonCfg.Channel <= 14) {
3227                                pAd->CommonCfg.MlmeRate = RATE_1;
3228                                pAd->CommonCfg.RtsRate = RATE_1;
3229                                pAd->CommonCfg.MlmeTransmit.field.MODE =
3230                                    MODE_CCK;
3231                                pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3232                        } else {
3233                                pAd->CommonCfg.MlmeRate = RATE_6;
3234                                pAd->CommonCfg.RtsRate = RATE_6;
3235                                pAd->CommonCfg.MlmeTransmit.field.MODE =
3236                                    MODE_OFDM;
3237                                pAd->CommonCfg.MlmeTransmit.field.MCS =
3238                                    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3239                        }
3240                        break;
3241                default:        /* error */
3242                        pAd->CommonCfg.MlmeRate = RATE_6;
3243                        pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3244                        pAd->CommonCfg.MlmeTransmit.field.MCS =
3245                            OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3246                        pAd->CommonCfg.RtsRate = RATE_1;
3247                        break;
3248                }
3249                /* */
3250                /* Keep Basic Mlme Rate. */
3251                /* */
3252                pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word =
3253                    pAd->CommonCfg.MlmeTransmit.word;
3254                if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3255                        pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3256                            OfdmRateToRxwiMCS[RATE_24];
3257                else
3258                        pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3259                            RATE_1;
3260                pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3261        }
3262
3263        DBGPRINT(RT_DEBUG_TRACE,
3264                 (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3265                  RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
3266                  RateIdToMbps[pAd->CommonCfg.MaxTxRate],
3267                  RateIdToMbps[pAd->CommonCfg.MinTxRate],
3268                  /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3269                  *auto_rate_cur_p));
3270        DBGPRINT(RT_DEBUG_TRACE,
3271                 (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3272                  RateIdToMbps[pAd->CommonCfg.TxRate],
3273                  RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3274        DBGPRINT(RT_DEBUG_TRACE,
3275                 ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3276                  pAd->CommonCfg.MlmeTransmit.word,
3277                  pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
3278                  pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
3279                  pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word));
3280}
3281
3282/*
3283        ==========================================================================
3284        Description:
3285                This function update HT Rate setting.
3286                Input Wcid value is valid for 2 case :
3287                1. it's used for Station in infra mode that copy AP rate to Mactable.
3288                2. OR Station   in adhoc mode to copy peer's HT rate to Mactable.
3289
3290 IRQL = DISPATCH_LEVEL
3291
3292        ==========================================================================
3293 */
3294void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx)
3295{
3296        u8 StbcMcs;             /*j, StbcMcs, bitmask; */
3297        char i;                 /* 3*3 */
3298        struct rt_ht_capability *pRtHtCap = NULL;
3299        struct rt_ht_phy_info *pActiveHtPhy = NULL;
3300        unsigned long BasicMCS;
3301        u8 j, bitmask;
3302        struct rt_ht_phy_info *pDesireHtPhy = NULL;
3303        PHTTRANSMIT_SETTING pHtPhy = NULL;
3304        PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3305        PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3306        BOOLEAN *auto_rate_cur_p;
3307
3308        DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n"));
3309
3310        auto_rate_cur_p = NULL;
3311
3312        {
3313                pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3314                pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3315                pHtPhy = &pAd->StaCfg.HTPhyMode;
3316                pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3317                pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3318
3319                auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3320        }
3321
3322        if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
3323                if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3324                        return;
3325
3326                pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3327                pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3328                StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3329                BasicMCS =
3330                    pAd->MlmeAux.AddHtInfo.MCSSet[0] +
3331                    (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3332                if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3333                    && (pAd->Antenna.field.TxPath == 2))
3334                        pMaxHtPhy->field.STBC = STBC_USE;
3335                else
3336                        pMaxHtPhy->field.STBC = STBC_NONE;
3337        } else {
3338                if (pDesireHtPhy->bHtEnable == FALSE)
3339                        return;
3340
3341                pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3342                StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3343                BasicMCS =
3344                    pAd->CommonCfg.AddHTInfo.MCSSet[0] +
3345                    (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3346                if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3347                    && (pAd->Antenna.field.TxPath == 2))
3348                        pMaxHtPhy->field.STBC = STBC_USE;
3349                else
3350                        pMaxHtPhy->field.STBC = STBC_NONE;
3351        }
3352
3353        /* Decide MAX ht rate. */
3354        if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3355                pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3356        else
3357                pMaxHtPhy->field.MODE = MODE_HTMIX;
3358
3359        if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth)
3360            && (pRtHtCap->ChannelWidth))
3361                pMaxHtPhy->field.BW = BW_40;
3362        else
3363                pMaxHtPhy->field.BW = BW_20;
3364
3365        if (pMaxHtPhy->field.BW == BW_20)
3366                pMaxHtPhy->field.ShortGI =
3367                    (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->
3368                     ShortGIfor20);
3369        else
3370                pMaxHtPhy->field.ShortGI =
3371                    (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->
3372                     ShortGIfor40);
3373
3374        if (pDesireHtPhy->MCSSet[4] != 0) {
3375                pMaxHtPhy->field.MCS = 32;
3376        }
3377
3378        for (i = 23; i >= 0; i--)       /* 3*3 */
3379        {
3380                j = i / 8;
3381                bitmask = (1 << (i - (j * 8)));
3382
3383                if ((pActiveHtPhy->MCSSet[j] & bitmask)
3384                    && (pDesireHtPhy->MCSSet[j] & bitmask)) {
3385                        pMaxHtPhy->field.MCS = i;
3386                        break;
3387                }
3388
3389                if (i == 0)
3390                        break;
3391        }
3392
3393        /* Copy MIN ht rate.  rt2860??? */
3394        pMinHtPhy->field.BW = BW_20;
3395        pMinHtPhy->field.MCS = 0;
3396        pMinHtPhy->field.STBC = 0;
3397        pMinHtPhy->field.ShortGI = 0;
3398        /*If STA assigns fixed rate. update to fixed here. */
3399        if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) {
3400                if (pDesireHtPhy->MCSSet[4] != 0) {
3401                        pMaxHtPhy->field.MCS = 32;
3402                        pMinHtPhy->field.MCS = 32;
3403                        DBGPRINT(RT_DEBUG_TRACE,
3404                                 ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3405                                  pMinHtPhy->field.MCS));
3406                }
3407
3408                for (i = 23; (char)i >= 0; i--) /* 3*3 */
3409                {
3410                        j = i / 8;
3411                        bitmask = (1 << (i - (j * 8)));
3412                        if ((pDesireHtPhy->MCSSet[j] & bitmask)
3413                            && (pActiveHtPhy->MCSSet[j] & bitmask)) {
3414                                pMaxHtPhy->field.MCS = i;
3415                                pMinHtPhy->field.MCS = i;
3416                                break;
3417                        }
3418                        if (i == 0)
3419                                break;
3420                }
3421        }
3422
3423        /* Decide ht rate */
3424        pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3425        pHtPhy->field.BW = pMaxHtPhy->field.BW;
3426        pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3427        pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3428        pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3429
3430        /* use default now. rt2860 */
3431        if (pDesireHtPhy->MCSSet[0] != 0xff)
3432                *auto_rate_cur_p = FALSE;
3433        else
3434                *auto_rate_cur_p = TRUE;
3435
3436        DBGPRINT(RT_DEBUG_TRACE,
3437                 (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n",
3438                  pAd->CommonCfg.DesiredHtPhy.AmsduSize));
3439        DBGPRINT(RT_DEBUG_TRACE,
3440                 ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n",
3441                  pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW,
3442                  pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3443        DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n"));
3444}
3445
3446void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab)
3447{
3448        int i;
3449
3450        Tab->numAsOriginator = 0;
3451        Tab->numAsRecipient = 0;
3452        Tab->numDoneOriginator = 0;
3453        NdisAllocateSpinLock(&pAd->BATabLock);
3454        for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
3455                Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3456                NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3457        }
3458        for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
3459                Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3460        }
3461}
3462
3463/* IRQL = DISPATCH_LEVEL */
3464void MlmeRadioOff(struct rt_rtmp_adapter *pAd)
3465{
3466        RTMP_MLME_RADIO_OFF(pAd);
3467}
3468
3469/* IRQL = DISPATCH_LEVEL */
3470void MlmeRadioOn(struct rt_rtmp_adapter *pAd)
3471{
3472        RTMP_MLME_RADIO_ON(pAd);
3473}
3474
3475/* =========================================================================================== */
3476/* bss_table.c */
3477/* =========================================================================================== */
3478
3479/*! \brief initialize BSS table
3480 *      \param p_tab pointer to the table
3481 *      \return none
3482 *      \pre
3483 *      \post
3484
3485 IRQL = PASSIVE_LEVEL
3486 IRQL = DISPATCH_LEVEL
3487
3488 */
3489void BssTableInit(struct rt_bss_table *Tab)
3490{
3491        int i;
3492
3493        Tab->BssNr = 0;
3494        Tab->BssOverlapNr = 0;
3495        for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) {
3496                NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry));
3497                Tab->BssEntry[i].Rssi = -127;   /* initial the rssi as a minimum value */
3498        }
3499}
3500
3501/*! \brief search the BSS table by SSID
3502 *      \param p_tab pointer to the bss table
3503 *      \param ssid SSID string
3504 *      \return index of the table, BSS_NOT_FOUND if not in the table
3505 *      \pre
3506 *      \post
3507 *      \note search by sequential search
3508
3509 IRQL = DISPATCH_LEVEL
3510
3511 */
3512unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel)
3513{
3514        u8 i;
3515
3516        for (i = 0; i < Tab->BssNr; i++) {
3517                /* */
3518                /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3519                /* We should distinguish this case. */
3520                /* */
3521                if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3522                     ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3523                    MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) {
3524                        return i;
3525                }
3526        }
3527        return (unsigned long)BSS_NOT_FOUND;
3528}
3529
3530unsigned long BssSsidTableSearch(struct rt_bss_table *Tab,
3531                         u8 *pBssid,
3532                         u8 *pSsid, u8 SsidLen, u8 Channel)
3533{
3534        u8 i;
3535
3536        for (i = 0; i < Tab->BssNr; i++) {
3537                /* */
3538                /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3539                /* We should distinguish this case. */
3540                /* */
3541                if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3542                     ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3543                    MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3544                    SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3545                               Tab->BssEntry[i].SsidLen)) {
3546                        return i;
3547                }
3548        }
3549        return (unsigned long)BSS_NOT_FOUND;
3550}
3551
3552unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab,
3553                             u8 *Bssid,
3554                             u8 *pSsid,
3555                             u8 SsidLen, u8 Channel)
3556{
3557        u8 i;
3558
3559        for (i = 0; i < Tab->BssNr; i++) {
3560                if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3561                     ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3562                    MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3563                    (SSID_EQUAL
3564                     (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3565                      Tab->BssEntry[i].SsidLen)
3566                     || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen))
3567                     ||
3568                     (NdisEqualMemory
3569                      (Tab->BssEntry[i].Ssid, ZeroSsid,
3570                       Tab->BssEntry[i].SsidLen)))) {
3571                        return i;
3572                }
3573        }
3574        return (unsigned long)BSS_NOT_FOUND;
3575}
3576
3577unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab,
3578                               u8 *pSsid, u8 SsidLen)
3579{
3580        u8 i;
3581
3582        for (i = 0; i < Tab->BssNr; i++) {
3583                if (SSID_EQUAL
3584                    (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3585                     Tab->BssEntry[i].SsidLen)) {
3586                        return i;
3587                }
3588        }
3589        return (unsigned long)BSS_NOT_FOUND;
3590}
3591
3592/* IRQL = DISPATCH_LEVEL */
3593void BssTableDeleteEntry(struct rt_bss_table *Tab,
3594                         u8 *pBssid, u8 Channel)
3595{
3596        u8 i, j;
3597
3598        for (i = 0; i < Tab->BssNr; i++) {
3599                if ((Tab->BssEntry[i].Channel == Channel) &&
3600                    (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) {
3601                        for (j = i; j < Tab->BssNr - 1; j++) {
3602                                NdisMoveMemory(&(Tab->BssEntry[j]),
3603                                               &(Tab->BssEntry[j + 1]),
3604                                               sizeof(struct rt_bss_entry));
3605                        }
3606                        NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]),
3607                                       sizeof(struct rt_bss_entry));
3608                        Tab->BssNr -= 1;
3609                        return;
3610                }
3611        }
3612}
3613
3614/*
3615        ========================================================================
3616        Routine Description:
3617                Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3618
3619        Arguments:
3620        // IRQL = DISPATCH_LEVEL
3621        ========================================================================
3622*/
3623void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd,
3624                           struct rt_ba_ori_entry *pBAORIEntry)
3625{
3626
3627        if (pBAORIEntry->ORI_BA_Status != Originator_NONE) {
3628                NdisAcquireSpinLock(&pAd->BATabLock);
3629                if (pBAORIEntry->ORI_BA_Status == Originator_Done) {
3630                        pAd->BATable.numAsOriginator -= 1;
3631                        DBGPRINT(RT_DEBUG_TRACE,
3632                                 ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3633                                  pAd->BATable.numAsRecipient));
3634                        /* Erase Bitmap flag. */
3635                }
3636                pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID)));      /* If STA mode,  erase flag here */
3637                pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;    /* If STA mode,  erase flag here */
3638                pBAORIEntry->ORI_BA_Status = Originator_NONE;
3639                pBAORIEntry->Token = 1;
3640                /* Not clear Sequence here. */
3641                NdisReleaseSpinLock(&pAd->BATabLock);
3642        }
3643}
3644
3645/*! \brief
3646 *      \param
3647 *      \return
3648 *      \pre
3649 *      \post
3650
3651 IRQL = DISPATCH_LEVEL
3652
3653 */
3654void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * pCfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo,  /* AP might use this additional ht info IE */
3655                 u8 HtCapabilityLen,
3656                 u8 AddHtInfoLen,
3657                 u8 NewExtChanOffset,
3658                 u8 Channel,
3659                 char Rssi,
3660                 IN LARGE_INTEGER TimeStamp,
3661                 u8 CkipFlag,
3662                 struct rt_edca_parm *pEdcaParm,
3663                 struct rt_qos_capability_parm *pQosCapability,
3664                 struct rt_qbss_load_parm *pQbssLoad,
3665                 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
3666{
3667        COPY_MAC_ADDR(pBss->Bssid, pBssid);
3668        /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */
3669        pBss->Hidden = 1;
3670        if (SsidLen > 0) {
3671                /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */
3672                /* Or send beacon /probe response with SSID len matching real SSID length, */
3673                /* but SSID is all zero. such as "00-00-00-00" with length 4. */
3674                /* We have to prevent this case overwrite correct table */
3675                if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) {
3676                        NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3677                        NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3678                        pBss->SsidLen = SsidLen;
3679                        pBss->Hidden = 0;
3680                }
3681        } else
3682                pBss->SsidLen = 0;
3683        pBss->BssType = BssType;
3684        pBss->BeaconPeriod = BeaconPeriod;
3685        if (BssType == BSS_INFRA) {
3686                if (pCfParm->bValid) {
3687                        pBss->CfpCount = pCfParm->CfpCount;
3688                        pBss->CfpPeriod = pCfParm->CfpPeriod;
3689                        pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3690                        pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3691                }
3692        } else {
3693                pBss->AtimWin = AtimWin;
3694        }
3695
3696        pBss->CapabilityInfo = CapabilityInfo;
3697        /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */
3698        /* Combine with AuthMode, they will decide the connection methods. */
3699        pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3700        ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3701        if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3702                NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3703        else
3704                NdisMoveMemory(pBss->SupRate, SupRate,
3705                               MAX_LEN_OF_SUPPORTED_RATES);
3706        pBss->SupRateLen = SupRateLen;
3707        ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3708        NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3709        pBss->NewExtChanOffset = NewExtChanOffset;
3710        pBss->ExtRateLen = ExtRateLen;
3711        pBss->Channel = Channel;
3712        pBss->CentralChannel = Channel;
3713        pBss->Rssi = Rssi;
3714        /* Update CkipFlag. if not exists, the value is 0x0 */
3715        pBss->CkipFlag = CkipFlag;
3716
3717        /* New for microsoft Fixed IEs */
3718        NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3719        pBss->FixIEs.BeaconInterval = BeaconPeriod;
3720        pBss->FixIEs.Capabilities = CapabilityInfo;
3721
3722        /* New for microsoft Variable IEs */
3723        if (LengthVIE != 0) {
3724                pBss->VarIELen = LengthVIE;
3725                NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3726        } else {
3727                pBss->VarIELen = 0;
3728        }
3729
3730        pBss->AddHtInfoLen = 0;
3731        pBss->HtCapabilityLen = 0;
3732        if (HtCapabilityLen > 0) {
3733                pBss->HtCapabilityLen = HtCapabilityLen;
3734                NdisMoveMemory(&pBss->HtCapability, pHtCapability,
3735                               HtCapabilityLen);
3736                if (AddHtInfoLen > 0) {
3737                        pBss->AddHtInfoLen = AddHtInfoLen;
3738                        NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo,
3739                                       AddHtInfoLen);
3740
3741                        if ((pAddHtInfo->ControlChan > 2)
3742                            && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
3743                                EXTCHA_BELOW)
3744                            && (pHtCapability->HtCapInfo.ChannelWidth ==
3745                                BW_40)) {
3746                                pBss->CentralChannel =
3747                                    pAddHtInfo->ControlChan - 2;
3748                        } else
3749                            if ((pAddHtInfo->AddHtInfo.ExtChanOffset ==
3750                                 EXTCHA_ABOVE)
3751                                && (pHtCapability->HtCapInfo.ChannelWidth ==
3752                                    BW_40)) {
3753                                pBss->CentralChannel =
3754                                    pAddHtInfo->ControlChan + 2;
3755                        }
3756                }
3757        }
3758
3759        BssCipherParse(pBss);
3760
3761        /* new for QOS */
3762        if (pEdcaParm)
3763                NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm));
3764        else
3765                pBss->EdcaParm.bValid = FALSE;
3766        if (pQosCapability)
3767                NdisMoveMemory(&pBss->QosCapability, pQosCapability,
3768                               sizeof(struct rt_qos_capability_parm));
3769        else
3770                pBss->QosCapability.bValid = FALSE;
3771        if (pQbssLoad)
3772                NdisMoveMemory(&pBss->QbssLoad, pQbssLoad,
3773                               sizeof(struct rt_qbss_load_parm));
3774        else
3775                pBss->QbssLoad.bValid = FALSE;
3776
3777        {
3778                struct rt_eid * pEid;
3779                u16 Length = 0;
3780
3781                NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3782                NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3783                pEid = (struct rt_eid *) pVIE;
3784                while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) {
3785                        switch (pEid->Eid) {
3786                        case IE_WPA:
3787                                if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) {
3788                                        if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3789                                                pBss->WpaIE.IELen = 0;
3790                                                break;
3791                                        }
3792                                        pBss->WpaIE.IELen = pEid->Len + 2;
3793                                        NdisMoveMemory(pBss->WpaIE.IE, pEid,
3794                                                       pBss->WpaIE.IELen);
3795                                }
3796                                break;
3797                        case IE_RSN:
3798                                if (NdisEqualMemory
3799                                    (pEid->Octet + 2, RSN_OUI, 3)) {
3800                                        if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3801                                                pBss->RsnIE.IELen = 0;
3802                                                break;
3803                                        }
3804                                        pBss->RsnIE.IELen = pEid->Len + 2;
3805                                        NdisMoveMemory(pBss->RsnIE.IE, pEid,
3806                                                       pBss->RsnIE.IELen);
3807                                }
3808                                break;
3809                        }
3810                        Length = Length + 2 + (u16)pEid->Len;   /* Eid[1] + Len[1]+ content[Len] */
3811                        pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len);
3812                }
3813        }
3814}
3815
3816/*!
3817 *      \brief insert an entry into the bss table
3818 *      \param p_tab The BSS table
3819 *      \param Bssid BSSID
3820 *      \param ssid SSID
3821 *      \param ssid_len Length of SSID
3822 *      \param bss_type
3823 *      \param beacon_period
3824 *      \param timestamp
3825 *      \param p_cf
3826 *      \param atim_win
3827 *      \param cap
3828 *      \param rates
3829 *      \param rates_len
3830 *      \param channel_idx
3831 *      \return none
3832 *      \pre
3833 *      \post
3834 *      \note If SSID is identical, the old entry will be replaced by the new one
3835
3836 IRQL = DISPATCH_LEVEL
3837
3838 */
3839unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *Tab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo,      /* AP might use this additional ht info IE */
3840                       u8 HtCapabilityLen,
3841                       u8 AddHtInfoLen,
3842                       u8 NewExtChanOffset,
3843                       u8 ChannelNo,
3844                       char Rssi,
3845                       IN LARGE_INTEGER TimeStamp,
3846                       u8 CkipFlag,
3847                       struct rt_edca_parm *pEdcaParm,
3848                       struct rt_qos_capability_parm *pQosCapability,
3849                       struct rt_qbss_load_parm *pQbssLoad,
3850                       u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
3851{
3852        unsigned long Idx;
3853
3854        Idx =
3855            BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen,
3856                                   ChannelNo);
3857        if (Idx == BSS_NOT_FOUND) {
3858                if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) {
3859                        /* */
3860                        /* It may happen when BSS Table was full. */
3861                        /* The desired AP will not be added into BSS Table */
3862                        /* In this case, if we found the desired AP then overwrite BSS Table. */
3863                        /* */
3864                        if (!OPSTATUS_TEST_FLAG
3865                            (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
3866                                if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid)
3867                                    || SSID_EQUAL(pAd->MlmeAux.Ssid,
3868                                                  pAd->MlmeAux.SsidLen, Ssid,
3869                                                  SsidLen)) {
3870                                        Idx = Tab->BssOverlapNr;
3871                                        BssEntrySet(pAd, &Tab->BssEntry[Idx],
3872                                                    pBssid, Ssid, SsidLen,
3873                                                    BssType, BeaconPeriod,
3874                                                    CfParm, AtimWin,
3875                                                    CapabilityInfo, SupRate,
3876                                                    SupRateLen, ExtRate,
3877                                                    ExtRateLen, pHtCapability,
3878                                                    pAddHtInfo, HtCapabilityLen,
3879                                                    AddHtInfoLen,
3880                                                    NewExtChanOffset, ChannelNo,
3881                                                    Rssi, TimeStamp, CkipFlag,
3882                                                    pEdcaParm, pQosCapability,
3883                                                    pQbssLoad, LengthVIE, pVIE);
3884                                        Tab->BssOverlapNr =
3885                                            (Tab->BssOverlapNr++) %
3886                                            MAX_LEN_OF_BSS_TABLE;
3887                                }
3888                                return Idx;
3889                        } else {
3890                                return BSS_NOT_FOUND;
3891                        }
3892                }
3893                Idx = Tab->BssNr;
3894                BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen,
3895                            BssType, BeaconPeriod, CfParm, AtimWin,
3896                            CapabilityInfo, SupRate, SupRateLen, ExtRate,
3897                            ExtRateLen, pHtCapability, pAddHtInfo,
3898                            HtCapabilityLen, AddHtInfoLen, NewExtChanOffset,
3899                            ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm,
3900                            pQosCapability, pQbssLoad, LengthVIE, pVIE);
3901                Tab->BssNr++;
3902        } else {
3903                /* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
3904                if ((SSID_EQUAL
3905                     (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid,
3906                      Tab->BssEntry[Idx].SsidLen))
3907                    ||
3908                    (NdisEqualMemory
3909                     (Tab->BssEntry[Idx].Ssid, ZeroSsid,
3910                      Tab->BssEntry[Idx].SsidLen))) {
3911                        BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid,
3912                                    SsidLen, BssType, BeaconPeriod, CfParm,
3913                                    AtimWin, CapabilityInfo, SupRate,
3914                                    SupRateLen, ExtRate, ExtRateLen,
3915                                    pHtCapability, pAddHtInfo, HtCapabilityLen,
3916                                    AddHtInfoLen, NewExtChanOffset, ChannelNo,
3917                                    Rssi, TimeStamp, CkipFlag, pEdcaParm,
3918                                    pQosCapability, pQbssLoad, LengthVIE, pVIE);
3919                }
3920        }
3921
3922        return Idx;
3923}
3924
3925/* IRQL = DISPATCH_LEVEL */
3926void BssTableSsidSort(struct rt_rtmp_adapter *pAd,
3927                      struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen)
3928{
3929        int i;
3930        BssTableInit(OutTab);
3931
3932        for (i = 0; i < pAd->ScanTab.BssNr; i++) {
3933                struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i];
3934                BOOLEAN bIsHiddenApIncluded = FALSE;
3935
3936                if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3937                     (pAd->MlmeAux.Channel > 14) &&
3938                     RadarChannelCheck(pAd, pInBss->Channel))
3939                    ) {
3940                        if (pInBss->Hidden)
3941                                bIsHiddenApIncluded = TRUE;
3942                }
3943
3944                if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3945                    (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen)
3946                     || bIsHiddenApIncluded)) {
3947                        struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3948
3949                        /* 2.4G/5G N only mode */
3950                        if ((pInBss->HtCapabilityLen == 0) &&
3951                            ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
3952                             || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
3953                                DBGPRINT(RT_DEBUG_TRACE,
3954                                         ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3955                                continue;
3956                        }
3957                        /* New for WPA2 */
3958                        /* Check the Authmode first */
3959                        if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
3960                                /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
3961                                if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
3962                                    && (pAd->StaCfg.AuthMode !=
3963                                        pInBss->AuthModeAux))
3964                                        /* None matched */
3965                                        continue;
3966
3967                                /* Check cipher suite, AP must have more secured cipher than station setting */
3968                                if ((pAd->StaCfg.AuthMode ==
3969                                     Ndis802_11AuthModeWPA)
3970                                    || (pAd->StaCfg.AuthMode ==
3971                                        Ndis802_11AuthModeWPAPSK)) {
3972                                        /* If it's not mixed mode, we should only let BSS pass with the same encryption */
3973                                        if (pInBss->WPA.bMixMode == FALSE)
3974                                                if (pAd->StaCfg.WepStatus !=
3975                                                    pInBss->WPA.GroupCipher)
3976                                                        continue;
3977
3978                                        /* check group cipher */
3979                                        if ((pAd->StaCfg.WepStatus <
3980                                             pInBss->WPA.GroupCipher)
3981                                            && (pInBss->WPA.GroupCipher !=
3982                                                Ndis802_11GroupWEP40Enabled)
3983                                            && (pInBss->WPA.GroupCipher !=
3984                                                Ndis802_11GroupWEP104Enabled))
3985                                                continue;
3986
3987                                        /* check pairwise cipher, skip if none matched */
3988                                        /* If profile set to AES, let it pass without question. */
3989                                        /* If profile set to TKIP, we must find one mateched */
3990                                        if ((pAd->StaCfg.WepStatus ==
3991                                             Ndis802_11Encryption2Enabled)
3992                                            && (pAd->StaCfg.WepStatus !=
3993                                                pInBss->WPA.PairCipher)
3994                                            && (pAd->StaCfg.WepStatus !=
3995                                                pInBss->WPA.PairCipherAux))
3996                                                continue;
3997                                } else
3998                                    if ((pAd->StaCfg.AuthMode ==
3999                                         Ndis802_11AuthModeWPA2)
4000                                        || (pAd->StaCfg.AuthMode ==
4001                                            Ndis802_11AuthModeWPA2PSK)) {
4002                                        /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4003                                        if (pInBss->WPA2.bMixMode == FALSE)
4004                                                if (pAd->StaCfg.WepStatus !=
4005                                                    pInBss->WPA2.GroupCipher)
4006                                                        continue;
4007
4008                                        /* check group cipher */
4009                                        if ((pAd->StaCfg.WepStatus <
4010                                             pInBss->WPA.GroupCipher)
4011                                            && (pInBss->WPA2.GroupCipher !=
4012                                                Ndis802_11GroupWEP40Enabled)
4013                                            && (pInBss->WPA2.GroupCipher !=
4014                                                Ndis802_11GroupWEP104Enabled))
4015                                                continue;
4016
4017                                        /* check pairwise cipher, skip if none matched */
4018                                        /* If profile set to AES, let it pass without question. */
4019                                        /* If profile set to TKIP, we must find one mateched */
4020                                        if ((pAd->StaCfg.WepStatus ==
4021                                             Ndis802_11Encryption2Enabled)
4022                                            && (pAd->StaCfg.WepStatus !=
4023                                                pInBss->WPA2.PairCipher)
4024                                            && (pAd->StaCfg.WepStatus !=
4025                                                pInBss->WPA2.PairCipherAux))
4026                                                continue;
4027                                }
4028                        }
4029                        /* Bss Type matched, SSID matched. */
4030                        /* We will check wepstatus for qualification Bss */
4031                        else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) {
4032                                DBGPRINT(RT_DEBUG_TRACE,
4033                                         ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4034                                          pAd->StaCfg.WepStatus,
4035                                          pInBss->WepStatus));
4036                                /* */
4037                                /* For the SESv2 case, we will not qualify WepStatus. */
4038                                /* */
4039                                if (!pInBss->bSES)
4040                                        continue;
4041                        }
4042                        /* Since the AP is using hidden SSID, and we are trying to connect to ANY */
4043                        /* It definitely will fail. So, skip it. */
4044                        /* CCX also require not even try to connect it! */
4045                        if (SsidLen == 0)
4046                                continue;
4047
4048                        /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4049                        /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4050                        if ((pInBss->CentralChannel != pInBss->Channel) &&
4051                            (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4052                             BW_40)) {
4053                                if (RTMPCheckChannel
4054                                    (pAd, pInBss->CentralChannel,
4055                                     pInBss->Channel) == FALSE) {
4056                                        pAd->CommonCfg.RegTransmitSetting.field.
4057                                            BW = BW_20;
4058                                        SetCommonHT(pAd);
4059                                        pAd->CommonCfg.RegTransmitSetting.field.
4060                                            BW = BW_40;
4061                                } else {
4062                                        if (pAd->CommonCfg.DesiredHtPhy.
4063                                            ChannelWidth == BAND_WIDTH_20) {
4064                                                SetCommonHT(pAd);
4065                                        }
4066                                }
4067                        }
4068                        /* copy matching BSS from InTab to OutTab */
4069                        NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
4070
4071                        OutTab->BssNr++;
4072                } else if ((pInBss->BssType == pAd->StaCfg.BssType)
4073                           && (SsidLen == 0)) {
4074                        struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4075
4076                        /* 2.4G/5G N only mode */
4077                        if ((pInBss->HtCapabilityLen == 0) &&
4078                            ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
4079                             || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
4080                                DBGPRINT(RT_DEBUG_TRACE,
4081                                         ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4082                                continue;
4083                        }
4084                        /* New for WPA2 */
4085                        /* Check the Authmode first */
4086                        if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
4087                                /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
4088                                if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
4089                                    && (pAd->StaCfg.AuthMode !=
4090                                        pInBss->AuthModeAux))
4091                                        /* None matched */
4092                                        continue;
4093
4094                                /* Check cipher suite, AP must have more secured cipher than station setting */
4095                                if ((pAd->StaCfg.AuthMode ==
4096                                     Ndis802_11AuthModeWPA)
4097                                    || (pAd->StaCfg.AuthMode ==
4098                                        Ndis802_11AuthModeWPAPSK)) {
4099                                        /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4100                                        if (pInBss->WPA.bMixMode == FALSE)
4101                                                if (pAd->StaCfg.WepStatus !=
4102                                                    pInBss->WPA.GroupCipher)
4103                                                        continue;
4104
4105                                        /* check group cipher */
4106                                        if (pAd->StaCfg.WepStatus <
4107                                            pInBss->WPA.GroupCipher)
4108                                                continue;
4109
4110                                        /* check pairwise cipher, skip if none matched */
4111                                        /* If profile set to AES, let it pass without question. */
4112                                        /* If profile set to TKIP, we must find one mateched */
4113                                        if ((pAd->StaCfg.WepStatus ==
4114                                             Ndis802_11Encryption2Enabled)
4115                                            && (pAd->StaCfg.WepStatus !=
4116                                                pInBss->WPA.PairCipher)
4117                                            && (pAd->StaCfg.WepStatus !=
4118                                                pInBss->WPA.PairCipherAux))
4119                                                continue;
4120                                } else
4121                                    if ((pAd->StaCfg.AuthMode ==
4122                                         Ndis802_11AuthModeWPA2)
4123                                        || (pAd->StaCfg.AuthMode ==
4124                                            Ndis802_11AuthModeWPA2PSK)) {
4125                                        /* If it's not mixed mode, we should only let BSS pass with the same encryption */
4126                                        if (pInBss->WPA2.bMixMode == FALSE)
4127                                                if (pAd->StaCfg.WepStatus !=
4128                                                    pInBss->WPA2.GroupCipher)
4129                                                        continue;
4130
4131                                        /* check group cipher */
4132                                        if (pAd->StaCfg.WepStatus <
4133                                            pInBss->WPA2.GroupCipher)
4134                                                continue;
4135
4136                                        /* check pairwise cipher, skip if none matched */
4137                                        /* If profile set to AES, let it pass without question. */
4138                                        /* If profile set to TKIP, we must find one mateched */
4139                                        if ((pAd->StaCfg.WepStatus ==
4140                                             Ndis802_11Encryption2Enabled)
4141                                            && (pAd->StaCfg.WepStatus !=
4142                                                pInBss->WPA2.PairCipher)
4143                                            && (pAd->StaCfg.WepStatus !=
4144                                                pInBss->WPA2.PairCipherAux))
4145                                                continue;
4146                                }
4147                        }
4148                        /* Bss Type matched, SSID matched. */
4149                        /* We will check wepstatus for qualification Bss */
4150                        else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4151                                continue;
4152
4153                        /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4154                        /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
4155                        if ((pInBss->CentralChannel != pInBss->Channel) &&
4156                            (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4157                             BW_40)) {
4158                                if (RTMPCheckChannel
4159                                    (pAd, pInBss->CentralChannel,
4160                                     pInBss->Channel) == FALSE) {
4161                                        pAd->CommonCfg.RegTransmitSetting.field.
4162                                            BW = BW_20;
4163                                        SetCommonHT(pAd);
4164                                        pAd->CommonCfg.RegTransmitSetting.field.
4165                                            BW = BW_40;
4166                                }
4167                        }
4168                        /* copy matching BSS from InTab to OutTab */
4169                        NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
4170
4171                        OutTab->BssNr++;
4172                }
4173
4174                if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4175                        break;
4176        }
4177
4178        BssTableSortByRssi(OutTab);
4179}
4180
4181/* IRQL = DISPATCH_LEVEL */
4182void BssTableSortByRssi(struct rt_bss_table *OutTab)
4183{
4184        int i, j;
4185        struct rt_bss_entry TmpBss;
4186
4187        for (i = 0; i < OutTab->BssNr - 1; i++) {
4188                for (j = i + 1; j < OutTab->BssNr; j++) {
4189                        if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) {
4190                                NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j],
4191                                               sizeof(struct rt_bss_entry));
4192                                NdisMoveMemory(&OutTab->BssEntry[j],
4193                                               &OutTab->BssEntry[i],
4194                                               sizeof(struct rt_bss_entry));
4195                                NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss,
4196                                               sizeof(struct rt_bss_entry));
4197                        }
4198                }
4199        }
4200}
4201
4202void BssCipherParse(struct rt_bss_entry *pBss)
4203{
4204        struct rt_eid * pEid;
4205        u8 *pTmp;
4206        struct rt_rsn_ie_header * pRsnHeader;
4207        struct rt_cipher_suite_struct * pCipher;
4208        struct rt_akm_suite * pAKM;
4209        u16 Count;
4210        int Length;
4211        NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4212
4213        /* */
4214        /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */
4215        /* */
4216        if (pBss->Privacy) {
4217                pBss->WepStatus = Ndis802_11WEPEnabled;
4218        } else {
4219                pBss->WepStatus = Ndis802_11WEPDisabled;
4220        }
4221        /* Set default to disable & open authentication before parsing variable IE */
4222        pBss->AuthMode = Ndis802_11AuthModeOpen;
4223        pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4224
4225        /* Init WPA setting */
4226        pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4227        pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4228        pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4229        pBss->WPA.RsnCapability = 0;
4230        pBss->WPA.bMixMode = FALSE;
4231
4232        /* Init WPA2 setting */
4233        pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4234        pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4235        pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4236        pBss->WPA2.RsnCapability = 0;
4237        pBss->WPA2.bMixMode = FALSE;
4238
4239        Length = (int)pBss->VarIELen;
4240
4241        while (Length > 0) {
4242                /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */
4243                pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length;
4244                pEid = (struct rt_eid *) pTmp;
4245                switch (pEid->Eid) {
4246                case IE_WPA:
4247                        if (NdisEqualMemory(pEid->Octet, SES_OUI, 3)
4248                            && (pEid->Len == 7)) {
4249                                pBss->bSES = TRUE;
4250                                break;
4251                        } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) !=
4252                                   1) {
4253                                /* if unsupported vendor specific IE */
4254                                break;
4255                        }
4256                        /* Skip OUI, version, and multicast suite */
4257                        /* This part should be improved in the future when AP supported multiple cipher suite. */
4258                        /* For now, it's OK since almost all APs have fixed cipher suite supported. */
4259                        /* pTmp = (u8 *)pEid->Octet; */
4260                        pTmp += 11;
4261
4262                        /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
4263                        /*      Value      Meaning */
4264                        /*      0                       None */
4265                        /*      1                       WEP-40 */
4266                        /*      2                       Tkip */
4267                        /*      3                       WRAP */
4268                        /*      4                       AES */
4269                        /*      5                       WEP-104 */
4270                        /* Parse group cipher */
4271                        switch (*pTmp) {
4272                        case 1:
4273                                pBss->WPA.GroupCipher =
4274                                    Ndis802_11GroupWEP40Enabled;
4275                                break;
4276                        case 5:
4277                                pBss->WPA.GroupCipher =
4278                                    Ndis802_11GroupWEP104Enabled;
4279                                break;
4280                        case 2:
4281                                pBss->WPA.GroupCipher =
4282                                    Ndis802_11Encryption2Enabled;
4283                                break;
4284                        case 4:
4285                                pBss->WPA.GroupCipher =
4286                                    Ndis802_11Encryption3Enabled;
4287                                break;
4288                        default:
4289                                break;
4290                        }
4291                        /* number of unicast suite */
4292                        pTmp += 1;
4293
4294                        /* skip all unicast cipher suites */
4295                        /*Count = *(u16 *)pTmp; */
4296                        Count = (pTmp[1] << 8) + pTmp[0];
4297                        pTmp += sizeof(u16);
4298
4299                        /* Parsing all unicast cipher suite */
4300                        while (Count > 0) {
4301                                /* Skip OUI */
4302                                pTmp += 3;
4303                                TmpCipher = Ndis802_11WEPDisabled;
4304                                switch (*pTmp) {
4305                                case 1:
4306                                case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4307                                        TmpCipher =
4308                                            Ndis802_11Encryption1Enabled;
4309                                        break;
4310                                case 2:
4311                                        TmpCipher =
4312                                            Ndis802_11Encryption2Enabled;
4313                                        break;
4314                                case 4:
4315                                        TmpCipher =
4316                                            Ndis802_11Encryption3Enabled;
4317                                        break;
4318                                default:
4319                                        break;
4320                                }
4321                                if (TmpCipher > pBss->WPA.PairCipher) {
4322                                        /* Move the lower cipher suite to PairCipherAux */
4323                                        pBss->WPA.PairCipherAux =
4324                                            pBss->WPA.PairCipher;
4325                                        pBss->WPA.PairCipher = TmpCipher;
4326                                } else {
4327                                        pBss->WPA.PairCipherAux = TmpCipher;
4328                                }
4329                                pTmp++;
4330                                Count--;
4331                        }
4332
4333                        /* 4. get AKM suite counts */
4334                        /*Count = *(u16 *)pTmp; */
4335                        Count = (pTmp[1] << 8) + pTmp[0];
4336                        pTmp += sizeof(u16);
4337                        pTmp += 3;
4338
4339                        switch (*pTmp) {
4340                        case 1:
4341                                /* Set AP support WPA-enterprise mode */
4342                                if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4343                                        pBss->AuthMode = Ndis802_11AuthModeWPA;
4344                                else
4345                                        pBss->AuthModeAux =
4346                                            Ndis802_11AuthModeWPA;
4347                                break;
4348                        case 2:
4349                                /* Set AP support WPA-PSK mode */
4350                                if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4351                                        pBss->AuthMode =
4352                                            Ndis802_11AuthModeWPAPSK;
4353                                else
4354                                        pBss->AuthModeAux =
4355                                            Ndis802_11AuthModeWPAPSK;
4356                                break;
4357                        default:
4358                                break;
4359                        }
4360                        pTmp += 1;
4361
4362                        /* Fixed for WPA-None */
4363                        if (pBss->BssType == BSS_ADHOC) {
4364                                pBss->AuthMode = Ndis802_11AuthModeWPANone;
4365                                pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4366                                pBss->WepStatus = pBss->WPA.GroupCipher;
4367                                /* Patched bugs for old driver */
4368                                if (pBss->WPA.PairCipherAux ==
4369                                    Ndis802_11WEPDisabled)
4370                                        pBss->WPA.PairCipherAux =
4371                                            pBss->WPA.GroupCipher;
4372                        } else
4373                                pBss->WepStatus = pBss->WPA.PairCipher;
4374
4375                        /* Check the Pair & Group, if different, turn on mixed mode flag */
4376                        if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4377                                pBss->WPA.bMixMode = TRUE;
4378
4379                        break;
4380
4381                case IE_RSN:
4382                        pRsnHeader = (struct rt_rsn_ie_header *) pTmp;
4383
4384                        /* 0. Version must be 1 */
4385                        if (le2cpu16(pRsnHeader->Version) != 1)
4386                                break;
4387                        pTmp += sizeof(struct rt_rsn_ie_header);
4388
4389                        /* 1. Check group cipher */
4390                        pCipher = (struct rt_cipher_suite_struct *) pTmp;
4391                        if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4392                                break;
4393
4394                        /* Parse group cipher */
4395                        switch (pCipher->Type) {
4396                        case 1:
4397                                pBss->WPA2.GroupCipher =
4398                                    Ndis802_11GroupWEP40Enabled;
4399                                break;
4400                        case 5:
4401                                pBss->WPA2.GroupCipher =
4402                                    Ndis802_11GroupWEP104Enabled;
4403                                break;
4404                        case 2:
4405                                pBss->WPA2.GroupCipher =
4406                                    Ndis802_11Encryption2Enabled;
4407                                break;
4408                        case 4:
4409                                pBss->WPA2.GroupCipher =
4410                                    Ndis802_11Encryption3Enabled;
4411                                break;
4412                        default:
4413                                break;
4414                        }
4415                        /* set to correct offset for next parsing */
4416                        pTmp += sizeof(struct rt_cipher_suite_struct);
4417
4418                        /* 2. Get pairwise cipher counts */
4419                        /*Count = *(u16 *)pTmp; */
4420                        Count = (pTmp[1] << 8) + pTmp[0];
4421                        pTmp += sizeof(u16);
4422
4423                        /* 3. Get pairwise cipher */
4424                        /* Parsing all unicast cipher suite */
4425                        while (Count > 0) {
4426                                /* Skip OUI */
4427                                pCipher = (struct rt_cipher_suite_struct *) pTmp;
4428                                TmpCipher = Ndis802_11WEPDisabled;
4429                                switch (pCipher->Type) {
4430                                case 1:
4431                                case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
4432                                        TmpCipher =
4433                                            Ndis802_11Encryption1Enabled;
4434                                        break;
4435                                case 2:
4436                                        TmpCipher =
4437                                            Ndis802_11Encryption2Enabled;
4438                                        break;
4439                                case 4:
4440                                        TmpCipher =
4441                                            Ndis802_11Encryption3Enabled;
4442                                        break;
4443                                default:
4444                                        break;
4445                                }
4446                                if (TmpCipher > pBss->WPA2.PairCipher) {
4447                                        /* Move the lower cipher suite to PairCipherAux */
4448                                        pBss->WPA2.PairCipherAux =
4449                                            pBss->WPA2.PairCipher;
4450                                        pBss->WPA2.PairCipher = TmpCipher;
4451                                } else {
4452                                        pBss->WPA2.PairCipherAux = TmpCipher;
4453                                }
4454                                pTmp += sizeof(struct rt_cipher_suite_struct);
4455                                Count--;
4456                        }
4457
4458                        /* 4. get AKM suite counts */
4459                        /*Count = *(u16 *)pTmp; */
4460                        Count = (pTmp[1] << 8) + pTmp[0];
4461                        pTmp += sizeof(u16);
4462
4463                        /* 5. Get AKM ciphers */
4464                        /* Parsing all AKM ciphers */
4465                        while (Count > 0) {
4466                                pAKM = (struct rt_akm_suite *) pTmp;
4467                                if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4468                                        break;
4469
4470                                switch (pAKM->Type) {
4471                                case 1:
4472                                        /* Set AP support WPA-enterprise mode */
4473                                        if (pBss->AuthMode ==
4474                                            Ndis802_11AuthModeOpen)
4475                                                pBss->AuthMode =
4476                                                    Ndis802_11AuthModeWPA2;
4477                                        else
4478                                                pBss->AuthModeAux =
4479                                                    Ndis802_11AuthModeWPA2;
4480                                        break;
4481                                case 2:
4482                                        /* Set AP support WPA-PSK mode */
4483                                        if (pBss->AuthMode ==
4484                                            Ndis802_11AuthModeOpen)
4485                                                pBss->AuthMode =
4486                                                    Ndis802_11AuthModeWPA2PSK;
4487                                        else
4488                                                pBss->AuthModeAux =
4489                                                    Ndis802_11AuthModeWPA2PSK;
4490                                        break;
4491                                default:
4492                                        if (pBss->AuthMode ==
4493                                            Ndis802_11AuthModeOpen)
4494                                                pBss->AuthMode =
4495                                                    Ndis802_11AuthModeMax;
4496                                        else
4497                                                pBss->AuthModeAux =
4498                                                    Ndis802_11AuthModeMax;
4499                                        break;
4500                                }
4501                                pTmp += (Count * sizeof(struct rt_akm_suite));
4502                                Count--;
4503                        }
4504
4505                        /* Fixed for WPA-None */
4506                        if (pBss->BssType == BSS_ADHOC) {
4507                                pBss->AuthMode = Ndis802_11AuthModeWPANone;
4508                                pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4509                                pBss->WPA.PairCipherAux =
4510                                    pBss->WPA2.PairCipherAux;
4511                                pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4512                                pBss->WepStatus = pBss->WPA.GroupCipher;
4513                                /* Patched bugs for old driver */
4514                                if (pBss->WPA.PairCipherAux ==
4515                                    Ndis802_11WEPDisabled)
4516                                        pBss->WPA.PairCipherAux =
4517                                            pBss->WPA.GroupCipher;
4518                        }
4519                        pBss->WepStatus = pBss->WPA2.PairCipher;
4520
4521                        /* 6. Get RSN capability */
4522                        /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */
4523                        pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0];
4524                        pTmp += sizeof(u16);
4525
4526                        /* Check the Pair & Group, if different, turn on mixed mode flag */
4527                        if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4528                                pBss->WPA2.bMixMode = TRUE;
4529
4530                        break;
4531                default:
4532                        break;
4533                }
4534                Length -= (pEid->Len + 2);
4535        }
4536}
4537
4538/* =========================================================================================== */
4539/* mac_table.c */
4540/* =========================================================================================== */
4541
4542/*! \brief generates a random mac address value for IBSS BSSID
4543 *      \param Addr the bssid location
4544 *      \return none
4545 *      \pre
4546 *      \post
4547 */
4548void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr)
4549{
4550        int i;
4551
4552        for (i = 0; i < MAC_ADDR_LEN; i++) {
4553                pAddr[i] = RandomByte(pAd);
4554        }
4555
4556        pAddr[0] = (pAddr[0] & 0xfe) | 0x02;    /* the first 2 bits must be 01xxxxxxxx */
4557}
4558
4559/*! \brief init the management mac frame header
4560 *      \param p_hdr mac header
4561 *      \param subtype subtype of the frame
4562 *      \param p_ds destination address, don't care if it is a broadcast address
4563 *      \return none
4564 *      \pre the station has the following information in the pAd->StaCfg
4565 *       - bssid
4566 *       - station address
4567 *      \post
4568 *      \note this function initializes the following field
4569
4570        IRQL = PASSIVE_LEVEL
4571        IRQL = DISPATCH_LEVEL
4572
4573 */
4574void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd,
4575                      struct rt_header_802_11 * pHdr80211,
4576                      u8 SubType,
4577                      u8 ToDs, u8 *pDA, u8 *pBssid)
4578{
4579        NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
4580
4581        pHdr80211->FC.Type = BTYPE_MGMT;
4582        pHdr80211->FC.SubType = SubType;
4583/*      if (SubType == SUBTYPE_ACK)     // sample, no use, it will conflict with ACTION frame sub type */
4584/*              pHdr80211->FC.Type = BTYPE_CNTL; */
4585        pHdr80211->FC.ToDs = ToDs;
4586        COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4587        COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4588        COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4589}
4590
4591/* =========================================================================================== */
4592/* mem_mgmt.c */
4593/* =========================================================================================== */
4594
4595/*!***************************************************************************
4596 * This routine build an outgoing frame, and fill all information specified
4597 * in argument list to the frame body. The actual frame size is the summation
4598 * of all arguments.
4599 * input params:
4600 *              Buffer - pointer to a pre-allocated memory segment
4601 *              args - a list of <int arg_size, arg> pairs.
4602 *              NOTE NOTE NOTE! the last argument must be NULL, otherwise this
4603 *                                                 function will FAIL!
4604 * return:
4605 *              Size of the buffer
4606 * usage:
4607 *              MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4608
4609 IRQL = PASSIVE_LEVEL
4610        IRQL = DISPATCH_LEVEL
4611
4612 ****************************************************************************/
4613unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...)
4614{
4615        u8 *p;
4616        int leng;
4617        unsigned long TotLeng;
4618        va_list Args;
4619
4620        /* calculates the total length */
4621        TotLeng = 0;
4622        va_start(Args, FrameLen);
4623        do {
4624                leng = va_arg(Args, int);
4625                if (leng == END_OF_ARGS) {
4626                        break;
4627                }
4628                p = va_arg(Args, void *);
4629                NdisMoveMemory(&Buffer[TotLeng], p, leng);
4630                TotLeng = TotLeng + leng;
4631        } while (TRUE);
4632
4633        va_end(Args);           /* clean up */
4634        *FrameLen = TotLeng;
4635        return TotLeng;
4636}
4637
4638/* =========================================================================================== */
4639/* mlme_queue.c */
4640/* =========================================================================================== */
4641
4642/*! \brief      Initialize The MLME Queue, used by MLME Functions
4643 *      \param  *Queue     The MLME Queue
4644 *      \return Always     Return NDIS_STATE_SUCCESS in this implementation
4645 *      \pre
4646 *      \post
4647 *      \note   Because this is done only once (at the init stage), no need to be locked
4648
4649 IRQL = PASSIVE_LEVEL
4650
4651 */
4652int MlmeQueueInit(struct rt_mlme_queue *Queue)
4653{
4654        int i;
4655
4656        NdisAllocateSpinLock(&Queue->Lock);
4657
4658        Queue->Num = 0;
4659        Queue->Head = 0;
4660        Queue->Tail = 0;
4661
4662        for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) {
4663                Queue->Entry[i].Occupied = FALSE;
4664                Queue->Entry[i].MsgLen = 0;
4665                NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4666        }
4667
4668        return NDIS_STATUS_SUCCESS;
4669}
4670
4671/*! \brief       Enqueue a message for other threads, if they want to send messages to MLME thread
4672 *      \param  *Queue    The MLME Queue
4673 *      \param   Machine  The State Machine Id
4674 *      \param   MsgType  The Message Type
4675 *      \param   MsgLen   The Message length
4676 *      \param  *Msg      The message pointer
4677 *      \return  TRUE if enqueue is successful, FALSE if the queue is full
4678 *      \pre
4679 *      \post
4680 *      \note    The message has to be initialized
4681
4682        IRQL = PASSIVE_LEVEL
4683        IRQL = DISPATCH_LEVEL
4684
4685 */
4686BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd,
4687                    unsigned long Machine,
4688                    unsigned long MsgType, unsigned long MsgLen, void * Msg)
4689{
4690        int Tail;
4691        struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
4692
4693        /* Do nothing if the driver is starting halt state. */
4694        /* This might happen when timer already been fired before cancel timer with mlmehalt */
4695        if (RTMP_TEST_FLAG
4696            (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4697                return FALSE;
4698
4699        /* First check the size, it MUST not exceed the mlme queue size */
4700        if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4701                DBGPRINT_ERR("MlmeEnqueue: msg too large, size = %ld \n", MsgLen);
4702                return FALSE;
4703        }
4704
4705        if (MlmeQueueFull(Queue)) {
4706                return FALSE;
4707        }
4708
4709        NdisAcquireSpinLock(&(Queue->Lock));
4710        Tail = Queue->Tail;
4711        Queue->Tail++;
4712        Queue->Num++;
4713        if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
4714                Queue->Tail = 0;
4715        }
4716
4717        Queue->Entry[Tail].Wcid = RESERVED_WCID;
4718        Queue->Entry[Tail].Occupied = TRUE;
4719        Queue->Entry[Tail].Machine = Machine;
4720        Queue->Entry[Tail].MsgType = MsgType;
4721        Queue->Entry[Tail].MsgLen = MsgLen;
4722
4723        if (Msg != NULL) {
4724                NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4725        }
4726
4727        NdisReleaseSpinLock(&(Queue->Lock));
4728        return TRUE;
4729}
4730
4731/*! \brief       This function is used when Recv gets a MLME message
4732 *      \param  *Queue                   The MLME Queue
4733 *      \param   TimeStampHigh   The upper 32 bit of timestamp
4734 *      \param   TimeStampLow    The lower 32 bit of timestamp
4735 *      \param   Rssi                    The receiving RSSI strength
4736 *      \param   MsgLen                  The length of the message
4737 *      \param  *Msg                     The message pointer
4738 *      \return  TRUE if everything ok, FALSE otherwise (like Queue Full)
4739 *      \pre
4740 *      \post
4741
4742 IRQL = DISPATCH_LEVEL
4743
4744 */
4745BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd,
4746                           unsigned long Wcid,
4747                           unsigned long TimeStampHigh,
4748                           unsigned long TimeStampLow,
4749                           u8 Rssi0,
4750                           u8 Rssi1,
4751                           u8 Rssi2,
4752                           unsigned long MsgLen, void * Msg, u8 Signal)
4753{
4754        int Tail, Machine;
4755        struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg;
4756        int MsgType;
4757        struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
4758
4759        /* Do nothing if the driver is starting halt state. */
4760        /* This might happen when timer already been fired before cancel timer with mlmehalt */
4761        if (RTMP_TEST_FLAG
4762            (pAd,
4763             fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) {
4764                DBGPRINT_ERR("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n");
4765                return FALSE;
4766        }
4767        /* First check the size, it MUST not exceed the mlme queue size */
4768        if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4769                DBGPRINT_ERR("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen);
4770                return FALSE;
4771        }
4772
4773        if (MlmeQueueFull(Queue)) {
4774                return FALSE;
4775        }
4776
4777        {
4778                if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) {
4779                        DBGPRINT_ERR("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType);
4780                        return FALSE;
4781                }
4782        }
4783
4784        /* OK, we got all the informations, it is time to put things into queue */
4785        NdisAcquireSpinLock(&(Queue->Lock));
4786        Tail = Queue->Tail;
4787        Queue->Tail++;
4788        Queue->Num++;
4789        if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
4790                Queue->Tail = 0;
4791        }
4792        Queue->Entry[Tail].Occupied = TRUE;
4793        Queue->Entry[Tail].Machine = Machine;
4794        Queue->Entry[Tail].MsgType = MsgType;
4795        Queue->Entry[Tail].MsgLen = MsgLen;
4796        Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4797        Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4798        Queue->Entry[Tail].Rssi0 = Rssi0;
4799        Queue->Entry[Tail].Rssi1 = Rssi1;
4800        Queue->Entry[Tail].Rssi2 = Rssi2;
4801        Queue->Entry[Tail].Signal = Signal;
4802        Queue->Entry[Tail].Wcid = (u8)Wcid;
4803
4804        Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4805
4806        if (Msg != NULL) {
4807                NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4808        }
4809
4810        NdisReleaseSpinLock(&(Queue->Lock));
4811
4812        RTMP_MLME_HANDLER(pAd);
4813
4814        return TRUE;
4815}
4816
4817/*! \brief       Dequeue a message from the MLME Queue
4818 *      \param  *Queue    The MLME Queue
4819 *      \param  *Elem     The message dequeued from MLME Queue
4820 *      \return  TRUE if the Elem contains something, FALSE otherwise
4821 *      \pre
4822 *      \post
4823
4824 IRQL = DISPATCH_LEVEL
4825
4826 */
4827BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem)
4828{
4829        NdisAcquireSpinLock(&(Queue->Lock));
4830        *Elem = &(Queue->Entry[Queue->Head]);
4831        Queue->Num--;
4832        Queue->Head++;
4833        if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) {
4834                Queue->Head = 0;
4835        }
4836        NdisReleaseSpinLock(&(Queue->Lock));
4837        return TRUE;
4838}
4839
4840/* IRQL = DISPATCH_LEVEL */
4841void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd)
4842{
4843#ifdef RTMP_MAC_PCI
4844        struct rt_mlme_queue_elem *Elem = NULL;
4845#endif /* RTMP_MAC_PCI // */
4846        BOOLEAN Cancelled;
4847
4848        DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4849
4850#ifdef RTMP_MAC_PCI
4851        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4852        if (pAd->Mlme.bRunning) {
4853                NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4854                return;
4855        } else {
4856                pAd->Mlme.bRunning = TRUE;
4857        }
4858        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4859
4860        /* Remove all Mlme queues elements */
4861        while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
4862                /*From message type, determine which state machine I should drive */
4863                if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
4864                        /* free MLME element */
4865                        Elem->Occupied = FALSE;
4866                        Elem->MsgLen = 0;
4867
4868                } else {
4869                        DBGPRINT_ERR("MlmeRestartStateMachine: MlmeQueue empty\n");
4870                }
4871        }
4872#endif /* RTMP_MAC_PCI // */
4873
4874        {
4875                /* Cancel all timer events */
4876                /* Be careful to cancel new added timer */
4877                RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4878                RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4879                RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4880                RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4881                RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4882                RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4883
4884        }
4885
4886        /* Change back to original channel in case of doing scan */
4887        AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4888        AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4889
4890        /* Resume MSDU which is turned off durning scan */
4891        RTMPResumeMsduTransmission(pAd);
4892
4893        {
4894                /* Set all state machines back IDLE */
4895                pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4896                pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4897                pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4898                pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4899                pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4900                pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4901        }
4902
4903#ifdef RTMP_MAC_PCI
4904        /* Remove running state */
4905        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4906        pAd->Mlme.bRunning = FALSE;
4907        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4908#endif /* RTMP_MAC_PCI // */
4909}
4910
4911/*! \brief      test if the MLME Queue is empty
4912 *      \param  *Queue    The MLME Queue
4913 *      \return TRUE if the Queue is empty, FALSE otherwise
4914 *      \pre
4915 *      \post
4916
4917 IRQL = DISPATCH_LEVEL
4918
4919 */
4920BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue)
4921{
4922        BOOLEAN Ans;
4923
4924        NdisAcquireSpinLock(&(Queue->Lock));
4925        Ans = (Queue->Num == 0);
4926        NdisReleaseSpinLock(&(Queue->Lock));
4927
4928        return Ans;
4929}
4930
4931/*! \brief       test if the MLME Queue is full
4932 *      \param   *Queue          The MLME Queue
4933 *      \return  TRUE if the Queue is empty, FALSE otherwise
4934 *      \pre
4935 *      \post
4936
4937 IRQL = PASSIVE_LEVEL
4938 IRQL = DISPATCH_LEVEL
4939
4940 */
4941BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue)
4942{
4943        BOOLEAN Ans;
4944
4945        NdisAcquireSpinLock(&(Queue->Lock));
4946        Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE
4947               || Queue->Entry[Queue->Tail].Occupied);
4948        NdisReleaseSpinLock(&(Queue->Lock));
4949
4950        return Ans;
4951}
4952
4953/*! \brief       The destructor of MLME Queue
4954 *      \param
4955 *      \return
4956 *      \pre
4957 *      \post
4958 *      \note   Clear Mlme Queue, Set Queue->Num to Zero.
4959
4960 IRQL = PASSIVE_LEVEL
4961
4962 */
4963void MlmeQueueDestroy(struct rt_mlme_queue *pQueue)
4964{
4965        NdisAcquireSpinLock(&(pQueue->Lock));
4966        pQueue->Num = 0;
4967        pQueue->Head = 0;
4968        pQueue->Tail = 0;
4969        NdisReleaseSpinLock(&(pQueue->Lock));
4970        NdisFreeSpinLock(&(pQueue->Lock));
4971}
4972
4973/*! \brief       To substitute the message type if the message is coming from external
4974 *      \param  pFrame             The frame received
4975 *      \param  *Machine           The state machine
4976 *      \param  *MsgType           the message type for the state machine
4977 *      \return TRUE if the substitution is successful, FALSE otherwise
4978 *      \pre
4979 *      \post
4980
4981 IRQL = DISPATCH_LEVEL
4982
4983 */
4984BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd,
4985                     struct rt_frame_802_11 * pFrame,
4986                     int * Machine, int * MsgType)
4987{
4988        u16 Seq, Alg;
4989        u8 EAPType;
4990        u8 *pData;
4991
4992        /* Pointer to start of data frames including SNAP header */
4993        pData = (u8 *)pFrame + LENGTH_802_11;
4994
4995        /* The only data type will pass to this function is EAPOL frame */
4996        if (pFrame->Hdr.FC.Type == BTYPE_DATA) {
4997                {
4998                        *Machine = WPA_STATE_MACHINE;
4999                        EAPType =
5000                            *((u8 *) pFrame + LENGTH_802_11 +
5001                              LENGTH_802_1_H + 1);
5002                        return (WpaMsgTypeSubst(EAPType, (int *) MsgType));
5003                }
5004        }
5005
5006        switch (pFrame->Hdr.FC.SubType) {
5007        case SUBTYPE_ASSOC_REQ:
5008                *Machine = ASSOC_STATE_MACHINE;
5009                *MsgType = MT2_PEER_ASSOC_REQ;
5010                break;
5011        case SUBTYPE_ASSOC_RSP:
5012                *Machine = ASSOC_STATE_MACHINE;
5013                *MsgType = MT2_PEER_ASSOC_RSP;
5014                break;
5015        case SUBTYPE_REASSOC_REQ:
5016                *Machine = ASSOC_STATE_MACHINE;
5017                *MsgType = MT2_PEER_REASSOC_REQ;
5018                break;
5019        case SUBTYPE_REASSOC_RSP:
5020                *Machine = ASSOC_STATE_MACHINE;
5021                *MsgType = MT2_PEER_REASSOC_RSP;
5022                break;
5023        case SUBTYPE_PROBE_REQ:
5024                *Machine = SYNC_STATE_MACHINE;
5025                *MsgType = MT2_PEER_PROBE_REQ;
5026                break;
5027        case SUBTYPE_PROBE_RSP:
5028                *Machine = SYNC_STATE_MACHINE;
5029                *MsgType = MT2_PEER_PROBE_RSP;
5030                break;
5031        case SUBTYPE_BEACON:
5032                *Machine = SYNC_STATE_MACHINE;
5033                *MsgType = MT2_PEER_BEACON;
5034                break;
5035        case SUBTYPE_ATIM:
5036                *Machine = SYNC_STATE_MACHINE;
5037                *MsgType = MT2_PEER_ATIM;
5038                break;
5039        case SUBTYPE_DISASSOC:
5040                *Machine = ASSOC_STATE_MACHINE;
5041                *MsgType = MT2_PEER_DISASSOC_REQ;
5042                break;
5043        case SUBTYPE_AUTH:
5044                /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
5045                NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16));
5046                NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16));
5047                if (Seq == 1 || Seq == 3) {
5048                        *Machine = AUTH_RSP_STATE_MACHINE;
5049                        *MsgType = MT2_PEER_AUTH_ODD;
5050                } else if (Seq == 2 || Seq == 4) {
5051                        if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) {
5052                                *Machine = AUTH_STATE_MACHINE;
5053                                *MsgType = MT2_PEER_AUTH_EVEN;
5054                        }
5055                } else {
5056                        return FALSE;
5057                }
5058                break;
5059        case SUBTYPE_DEAUTH:
5060                *Machine = AUTH_RSP_STATE_MACHINE;
5061                *MsgType = MT2_PEER_DEAUTH;
5062                break;
5063        case SUBTYPE_ACTION:
5064                *Machine = ACTION_STATE_MACHINE;
5065                /*  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
5066                if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) {
5067                        *MsgType = MT2_ACT_INVALID;
5068                } else {
5069                        *MsgType = (pFrame->Octet[0] & 0x7F);
5070                }
5071                break;
5072        default:
5073                return FALSE;
5074                break;
5075        }
5076
5077        return TRUE;
5078}
5079
5080/* =========================================================================================== */
5081/* state_machine.c */
5082/* =========================================================================================== */
5083
5084/*! \brief Initialize the state machine.
5085 *      \param *S                       pointer to the state machine
5086 *      \param  Trans           State machine transition function
5087 *      \param  StNr            number of states
5088 *      \param  MsgNr           number of messages
5089 *      \param  DefFunc         default function, when there is invalid state/message combination
5090 *      \param  InitState       initial state of the state machine
5091 *      \param  Base            StateMachine base, internal use only
5092 *      \pre p_sm should be a legal pointer
5093 *      \post
5094
5095 IRQL = PASSIVE_LEVEL
5096
5097 */
5098void StateMachineInit(struct rt_state_machine *S,
5099                      IN STATE_MACHINE_FUNC Trans[],
5100                      unsigned long StNr,
5101                      unsigned long MsgNr,
5102                      IN STATE_MACHINE_FUNC DefFunc,
5103                      unsigned long InitState, unsigned long Base)
5104{
5105        unsigned long i, j;
5106
5107        /* set number of states and messages */
5108        S->NrState = StNr;
5109        S->NrMsg = MsgNr;
5110        S->Base = Base;
5111
5112        S->TransFunc = Trans;
5113
5114        /* init all state transition to default function */
5115        for (i = 0; i < StNr; i++) {
5116                for (j = 0; j < MsgNr; j++) {
5117                        S->TransFunc[i * MsgNr + j] = DefFunc;
5118                }
5119        }
5120
5121        /* set the starting state */
5122        S->CurrState = InitState;
5123}
5124
5125/*! \brief This function fills in the function pointer into the cell in the state machine
5126 *      \param *S       pointer to the state machine
5127 *      \param St       state
5128 *      \param Msg      incoming message
5129 *      \param f        the function to be executed when (state, message) combination occurs at the state machine
5130 *      \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
5131 *      \post
5132
5133 IRQL = PASSIVE_LEVEL
5134
5135 */
5136void StateMachineSetAction(struct rt_state_machine *S,
5137                           unsigned long St,
5138                           unsigned long Msg, IN STATE_MACHINE_FUNC Func)
5139{
5140        unsigned long MsgIdx;
5141
5142        MsgIdx = Msg - S->Base;
5143
5144        if (St < S->NrState && MsgIdx < S->NrMsg) {
5145                /* boundary checking before setting the action */
5146                S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5147        }
5148}
5149
5150/*! \brief       This function does the state transition
5151 *      \param   *Adapter the NIC adapter pointer
5152 *      \param   *S       the state machine
5153 *      \param   *Elem    the message to be executed
5154 *      \return   None
5155
5156 IRQL = DISPATCH_LEVEL
5157
5158 */
5159void StateMachinePerformAction(struct rt_rtmp_adapter *pAd,
5160                               struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem)
5161{
5162        (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))
5163            (pAd, Elem);
5164}
5165
5166/*
5167        ==========================================================================
5168        Description:
5169                The drop function, when machine executes this, the message is simply
5170                ignored. This function does nothing, the message is freed in
5171                StateMachinePerformAction()
5172        ==========================================================================
5173 */
5174void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
5175{
5176}
5177
5178/* =========================================================================================== */
5179/* lfsr.c */
5180/* =========================================================================================== */
5181
5182/*
5183        ==========================================================================
5184        Description:
5185
5186        IRQL = PASSIVE_LEVEL
5187
5188        ==========================================================================
5189 */
5190void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed)
5191{
5192        if (Seed == 0)
5193                pAd->Mlme.ShiftReg = 1;
5194        else
5195                pAd->Mlme.ShiftReg = Seed;
5196}
5197
5198/*
5199        ==========================================================================
5200        Description:
5201        ==========================================================================
5202 */
5203u8 RandomByte(struct rt_rtmp_adapter *pAd)
5204{
5205        unsigned long i;
5206        u8 R, Result;
5207
5208        R = 0;
5209
5210        if (pAd->Mlme.ShiftReg == 0)
5211                NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg);
5212
5213        for (i = 0; i < 8; i++) {
5214                if (pAd->Mlme.ShiftReg & 0x00000001) {
5215                        pAd->Mlme.ShiftReg =
5216                            ((pAd->Mlme.
5217                              ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5218                        Result = 1;
5219                } else {
5220                        pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5221                        Result = 0;
5222                }
5223                R = (R << 1) | Result;
5224        }
5225
5226        return R;
5227}
5228
5229/*
5230        ========================================================================
5231
5232        Routine Description:
5233                Verify the support rate for different PHY type
5234
5235        Arguments:
5236                pAd                             Pointer to our adapter
5237
5238        Return Value:
5239                None
5240
5241        IRQL = PASSIVE_LEVEL
5242
5243        ========================================================================
5244*/
5245void RTMPCheckRates(struct rt_rtmp_adapter *pAd,
5246                    IN u8 SupRate[], IN u8 * SupRateLen)
5247{
5248        u8 RateIdx, i, j;
5249        u8 NewRate[12], NewRateLen;
5250
5251        NewRateLen = 0;
5252
5253        if (pAd->CommonCfg.PhyMode == PHY_11B)
5254                RateIdx = 4;
5255        else
5256                RateIdx = 12;
5257
5258        /* Check for support rates exclude basic rate bit */
5259        for (i = 0; i < *SupRateLen; i++)
5260                for (j = 0; j < RateIdx; j++)
5261                        if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5262                                NewRate[NewRateLen++] = SupRate[i];
5263
5264        *SupRateLen = NewRateLen;
5265        NdisMoveMemory(SupRate, NewRate, NewRateLen);
5266}
5267
5268BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd,
5269                         u8 CentralChannel, u8 Channel)
5270{
5271        u8 k;
5272        u8 UpperChannel = 0, LowerChannel = 0;
5273        u8 NoEffectChannelinList = 0;
5274
5275        /* Find upper and lower channel according to 40MHz current operation. */
5276        if (CentralChannel < Channel) {
5277                UpperChannel = Channel;
5278                if (CentralChannel > 2)
5279                        LowerChannel = CentralChannel - 2;
5280                else
5281                        return FALSE;
5282        } else if (CentralChannel > Channel) {
5283                UpperChannel = CentralChannel + 2;
5284                LowerChannel = Channel;
5285        }
5286
5287        for (k = 0; k < pAd->ChannelListNum; k++) {
5288                if (pAd->ChannelList[k].Channel == UpperChannel) {
5289                        NoEffectChannelinList++;
5290                }
5291                if (pAd->ChannelList[k].Channel == LowerChannel) {
5292                        NoEffectChannelinList++;
5293                }
5294        }
5295
5296        DBGPRINT(RT_DEBUG_TRACE,
5297                 ("Total Channel in Channel List = [%d]\n",
5298                  NoEffectChannelinList));
5299        if (NoEffectChannelinList == 2)
5300                return TRUE;
5301        else
5302                return FALSE;
5303}
5304
5305/*
5306        ========================================================================
5307
5308        Routine Description:
5309                Verify the support rate for HT phy type
5310
5311        Arguments:
5312                pAd                             Pointer to our adapter
5313
5314        Return Value:
5315                FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
5316
5317        IRQL = PASSIVE_LEVEL
5318
5319        ========================================================================
5320*/
5321BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd,
5322                    u8 Wcid,
5323                    struct rt_ht_capability_ie * pHtCapability,
5324                    struct rt_add_ht_info_ie * pAddHtInfo)
5325{
5326        if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5327                return FALSE;
5328
5329        /* If use AMSDU, set flag. */
5330        if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
5331                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5332                                       fCLIENT_STATUS_AMSDU_INUSED);
5333        /* Save Peer Capability */
5334        if (pHtCapability->HtCapInfo.ShortGIfor20)
5335                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5336                                       fCLIENT_STATUS_SGI20_CAPABLE);
5337        if (pHtCapability->HtCapInfo.ShortGIfor40)
5338                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5339                                       fCLIENT_STATUS_SGI40_CAPABLE);
5340        if (pHtCapability->HtCapInfo.TxSTBC)
5341                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5342                                       fCLIENT_STATUS_TxSTBC_CAPABLE);
5343        if (pHtCapability->HtCapInfo.RxSTBC)
5344                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5345                                       fCLIENT_STATUS_RxSTBC_CAPABLE);
5346        if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) {
5347                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5348                                       fCLIENT_STATUS_RDG_CAPABLE);
5349        }
5350
5351        if (Wcid < MAX_LEN_OF_MAC_TABLE) {
5352                pAd->MacTab.Content[Wcid].MpduDensity =
5353                    pHtCapability->HtCapParm.MpduDensity;
5354        }
5355        /* Will check ChannelWidth for MCSSet[4] below */
5356        pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
5357        switch (pAd->CommonCfg.RxStream) {
5358        case 1:
5359                pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5360                pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5361                pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5362                pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5363                break;
5364        case 2:
5365                pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5366                pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5367                pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5368                pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5369                break;
5370        case 3:
5371                pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5372                pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5373                pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5374                pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5375                break;
5376        }
5377
5378        pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth =
5379            pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.
5380            ChannelWidth;
5381
5382        DBGPRINT(RT_DEBUG_TRACE,
5383                 ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5384                  pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth,
5385                  pAddHtInfo->AddHtInfo.RecomWidth,
5386                  pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5387                  pAd->NicConfig2.field.BW40MAvailForA,
5388                  pAd->NicConfig2.field.BW40MAvailForG,
5389                  pAd->CommonCfg.PhyMode));
5390
5391        pAd->MlmeAux.HtCapability.HtCapInfo.GF =
5392            pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF;
5393
5394        /* Send Assoc Req with my HT capability. */
5395        pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =
5396            pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5397        pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =
5398            pAd->CommonCfg.DesiredHtPhy.MimoPs;
5399        pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =
5400            (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->
5401                                                          HtCapInfo.
5402                                                          ShortGIfor20);
5403        pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =
5404            (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->
5405                                                          HtCapInfo.
5406                                                          ShortGIfor40);
5407        pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =
5408            (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo.
5409                                                    RxSTBC);
5410        pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =
5411            (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo.
5412                                                    TxSTBC);
5413        pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor =
5414            pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5415        pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity =
5416            pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5417        pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC =
5418            pHtCapability->ExtHtCapInfo.PlusHTC;
5419        pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC =
5420            pHtCapability->ExtHtCapInfo.PlusHTC;
5421        if (pAd->CommonCfg.bRdg) {
5422                pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport =
5423                    pHtCapability->ExtHtCapInfo.RDGSupport;
5424                pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5425        }
5426
5427        if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
5428                pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;      /* BW20 can't transmit MCS32 */
5429
5430        COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5431        return TRUE;
5432}
5433
5434/*
5435        ========================================================================
5436
5437        Routine Description:
5438                Verify the support rate for different PHY type
5439
5440        Arguments:
5441                pAd                             Pointer to our adapter
5442
5443        Return Value:
5444                None
5445
5446        IRQL = PASSIVE_LEVEL
5447
5448        ========================================================================
5449*/
5450void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd)
5451{
5452        u8 MinimumRate;
5453        u8 ProperMlmeRate;      /*= RATE_54; */
5454        u8 i, j, RateIdx = 12;  /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
5455        BOOLEAN bMatch = FALSE;
5456
5457        switch (pAd->CommonCfg.PhyMode) {
5458        case PHY_11B:
5459                ProperMlmeRate = RATE_11;
5460                MinimumRate = RATE_1;
5461                break;
5462        case PHY_11BG_MIXED:
5463        case PHY_11ABGN_MIXED:
5464        case PHY_11BGN_MIXED:
5465                if ((pAd->MlmeAux.SupRateLen == 4) &&
5466                    (pAd->MlmeAux.ExtRateLen == 0))
5467                        /* B only AP */
5468                        ProperMlmeRate = RATE_11;
5469                else
5470                        ProperMlmeRate = RATE_24;
5471
5472                if (pAd->MlmeAux.Channel <= 14)
5473                        MinimumRate = RATE_1;
5474                else
5475                        MinimumRate = RATE_6;
5476                break;
5477        case PHY_11A:
5478        case PHY_11N_2_4G:      /* rt2860 need to check mlmerate for 802.11n */
5479        case PHY_11GN_MIXED:
5480        case PHY_11AGN_MIXED:
5481        case PHY_11AN_MIXED:
5482        case PHY_11N_5G:
5483                ProperMlmeRate = RATE_24;
5484                MinimumRate = RATE_6;
5485                break;
5486        case PHY_11ABG_MIXED:
5487                ProperMlmeRate = RATE_24;
5488                if (pAd->MlmeAux.Channel <= 14)
5489                        MinimumRate = RATE_1;
5490                else
5491                        MinimumRate = RATE_6;
5492                break;
5493        default:                /* error */
5494                ProperMlmeRate = RATE_1;
5495                MinimumRate = RATE_1;
5496                break;
5497        }
5498
5499        for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) {
5500                for (j = 0; j < RateIdx; j++) {
5501                        if ((pAd->MlmeAux.SupRate[i] & 0x7f) ==
5502                            RateIdTo500Kbps[j]) {
5503                                if (j == ProperMlmeRate) {
5504                                        bMatch = TRUE;
5505                                        break;
5506                                }
5507                        }
5508                }
5509
5510                if (bMatch)
5511                        break;
5512        }
5513
5514        if (bMatch == FALSE) {
5515                for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) {
5516                        for (j = 0; j < RateIdx; j++) {
5517                                if ((pAd->MlmeAux.ExtRate[i] & 0x7f) ==
5518                                    RateIdTo500Kbps[j]) {
5519                                        if (j == ProperMlmeRate) {
5520                                                bMatch = TRUE;
5521                                                break;
5522                                        }
5523                                }
5524                        }
5525
5526                        if (bMatch)
5527                                break;
5528                }
5529        }
5530
5531        if (bMatch == FALSE) {
5532                ProperMlmeRate = MinimumRate;
5533        }
5534
5535        pAd->CommonCfg.MlmeRate = MinimumRate;
5536        pAd->CommonCfg.RtsRate = ProperMlmeRate;
5537        if (pAd->CommonCfg.MlmeRate >= RATE_6) {
5538                pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
5539                pAd->CommonCfg.MlmeTransmit.field.MCS =
5540                    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5541                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5542                    MODE_OFDM;
5543                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5544                    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5545        } else {
5546                pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5547                pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
5548                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5549                    MODE_CCK;
5550                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5551                    pAd->CommonCfg.MlmeRate;
5552        }
5553
5554        DBGPRINT(RT_DEBUG_TRACE,
5555                 ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n",
5556                  pAd->CommonCfg.MlmeTransmit.word));
5557}
5558
5559char RTMPMaxRssi(struct rt_rtmp_adapter *pAd,
5560                 char Rssi0, char Rssi1, char Rssi2)
5561{
5562        char larger = -127;
5563
5564        if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) {
5565                larger = Rssi0;
5566        }
5567
5568        if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) {
5569                larger = max(Rssi0, Rssi1);
5570        }
5571
5572        if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) {
5573                larger = max(larger, Rssi2);
5574        }
5575
5576        if (larger == -127)
5577                larger = 0;
5578
5579        return larger;
5580}
5581
5582/*
5583    ========================================================================
5584    Routine Description:
5585        Periodic evaluate antenna link status
5586
5587    Arguments:
5588        pAd         - Adapter pointer
5589
5590    Return Value:
5591        None
5592
5593    ========================================================================
5594*/
5595void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd)
5596{
5597        u8 BBPR3 = 0;
5598
5599        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5600                           fRTMP_ADAPTER_HALT_IN_PROGRESS |
5601                           fRTMP_ADAPTER_RADIO_OFF |
5602                           fRTMP_ADAPTER_NIC_NOT_EXIST |
5603                           fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5604            OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5605#ifdef RT30xx
5606            || (pAd->EepromAccess)
5607#endif /* RT30xx // */
5608#ifdef RT3090
5609            || (pAd->bPCIclkOff == TRUE)
5610#endif /* RT3090 // */
5611            )
5612                return;
5613
5614        {
5615                /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5616                /*      return; */
5617
5618                {
5619
5620                        if (pAd->StaCfg.Psm == PWR_SAVE)
5621                                return;
5622
5623                        RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5624                        BBPR3 &= (~0x18);
5625                        if (pAd->Antenna.field.RxPath == 3) {
5626                                BBPR3 |= (0x10);
5627                        } else if (pAd->Antenna.field.RxPath == 2) {
5628                                BBPR3 |= (0x8);
5629                        } else if (pAd->Antenna.field.RxPath == 1) {
5630                                BBPR3 |= (0x0);
5631                        }
5632                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5633#ifdef RTMP_MAC_PCI
5634                        pAd->StaCfg.BBPR3 = BBPR3;
5635#endif /* RTMP_MAC_PCI // */
5636                        if (OPSTATUS_TEST_FLAG
5637                            (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5638                            ) {
5639                                unsigned long TxTotalCnt =
5640                                    pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5641                                    pAd->RalinkCounters.OneSecTxRetryOkCount +
5642                                    pAd->RalinkCounters.OneSecTxFailCount;
5643
5644                                /* dynamic adjust antenna evaluation period according to the traffic */
5645                                if (TxTotalCnt > 50) {
5646                                        RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5647                                                     20);
5648                                        pAd->Mlme.bLowThroughput = FALSE;
5649                                } else {
5650                                        RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5651                                                     300);
5652                                        pAd->Mlme.bLowThroughput = TRUE;
5653                                }
5654                        }
5655                }
5656
5657        }
5658
5659}
5660
5661/*
5662    ========================================================================
5663    Routine Description:
5664        After evaluation, check antenna link status
5665
5666    Arguments:
5667        pAd         - Adapter pointer
5668
5669    Return Value:
5670        None
5671
5672    ========================================================================
5673*/
5674void AsicRxAntEvalTimeout(void *SystemSpecific1,
5675                          void *FunctionContext,
5676                          void *SystemSpecific2, void *SystemSpecific3)
5677{
5678        struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
5679        u8 BBPR3 = 0;
5680        char larger = -127, rssi0, rssi1, rssi2;
5681
5682        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5683                           fRTMP_ADAPTER_HALT_IN_PROGRESS |
5684                           fRTMP_ADAPTER_RADIO_OFF |
5685                           fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5686            OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5687#ifdef RT30xx
5688            || (pAd->EepromAccess)
5689#endif /* RT30xx // */
5690#ifdef RT3090
5691            || (pAd->bPCIclkOff == TRUE)
5692#endif /* RT3090 // */
5693            )
5694                return;
5695
5696        {
5697                /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5698                /*      return; */
5699                {
5700                        if (pAd->StaCfg.Psm == PWR_SAVE)
5701                                return;
5702
5703                        /* if the traffic is low, use average rssi as the criteria */
5704                        if (pAd->Mlme.bLowThroughput == TRUE) {
5705                                rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5706                                rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5707                                rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
5708                        } else {
5709                                rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5710                                rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5711                                rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5712                        }
5713
5714                        if (pAd->Antenna.field.RxPath == 3) {
5715                                larger = max(rssi0, rssi1);
5716
5717                                if (larger > (rssi2 + 20))
5718                                        pAd->Mlme.RealRxPath = 2;
5719                                else
5720                                        pAd->Mlme.RealRxPath = 3;
5721                        } else if (pAd->Antenna.field.RxPath == 2) {
5722                                if (rssi0 > (rssi1 + 20))
5723                                        pAd->Mlme.RealRxPath = 1;
5724                                else
5725                                        pAd->Mlme.RealRxPath = 2;
5726                        }
5727
5728                        RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5729                        BBPR3 &= (~0x18);
5730                        if (pAd->Mlme.RealRxPath == 3) {
5731                                BBPR3 |= (0x10);
5732                        } else if (pAd->Mlme.RealRxPath == 2) {
5733                                BBPR3 |= (0x8);
5734                        } else if (pAd->Mlme.RealRxPath == 1) {
5735                                BBPR3 |= (0x0);
5736                        }
5737                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
5738#ifdef RTMP_MAC_PCI
5739                        pAd->StaCfg.BBPR3 = BBPR3;
5740#endif /* RTMP_MAC_PCI // */
5741                }
5742        }
5743
5744}
5745
5746void APSDPeriodicExec(void *SystemSpecific1,
5747                      void *FunctionContext,
5748                      void *SystemSpecific2, void *SystemSpecific3)
5749{
5750        struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
5751
5752        if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5753                return;
5754
5755        pAd->CommonCfg.TriggerTimerCount++;
5756
5757/* Driver should not send trigger frame, it should be send by application layer */
5758/*
5759        if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5760                && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5761                (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5762        {
5763                DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5764                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5765                pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5766                pAd->CommonCfg.TriggerTimerCount = 0;
5767                pAd->CommonCfg.bInServicePeriod = TRUE;
5768        }*/
5769}
5770
5771/*
5772    ========================================================================
5773    Routine Description:
5774        Set/reset MAC registers according to bPiggyBack parameter
5775
5776    Arguments:
5777        pAd         - Adapter pointer
5778        bPiggyBack  - Enable / Disable Piggy-Back
5779
5780    Return Value:
5781        None
5782
5783    ========================================================================
5784*/
5785void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack)
5786{
5787        TX_LINK_CFG_STRUC TxLinkCfg;
5788
5789        RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5790
5791        TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5792        RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5793}
5794
5795/*
5796    ========================================================================
5797    Routine Description:
5798        check if this entry need to switch rate automatically
5799
5800    Arguments:
5801        pAd
5802        pEntry
5803
5804    Return Value:
5805        TURE
5806        FALSE
5807
5808    ========================================================================
5809*/
5810BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd,
5811                                           struct rt_mac_table_entry *pEntry)
5812{
5813        BOOLEAN result = TRUE;
5814
5815        {
5816                /* only associated STA counts */
5817                if (pEntry && (pEntry->ValidAsCLI)
5818                    && (pEntry->Sst == SST_ASSOC)) {
5819                        result = pAd->StaCfg.bAutoTxRateSwitch;
5820                } else
5821                        result = FALSE;
5822        }
5823
5824        return result;
5825}
5826
5827BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd)
5828{
5829        {
5830                if (pAd->StaCfg.bAutoTxRateSwitch)
5831                        return TRUE;
5832        }
5833        return FALSE;
5834}
5835
5836/*
5837    ========================================================================
5838    Routine Description:
5839        check if this entry need to fix tx legacy rate
5840
5841    Arguments:
5842        pAd
5843        pEntry
5844
5845    Return Value:
5846        TURE
5847        FALSE
5848
5849    ========================================================================
5850*/
5851u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
5852{
5853        u8 tx_mode = FIXED_TXMODE_HT;
5854
5855        {
5856                tx_mode =
5857                    (u8)pAd->StaCfg.DesiredTransmitSetting.field.
5858                    FixedTxMode;
5859        }
5860
5861        return tx_mode;
5862}
5863
5864/*
5865    ========================================================================
5866    Routine Description:
5867        Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5868
5869    Arguments:
5870        pAd
5871        pEntry
5872
5873    Return Value:
5874        TURE
5875        FALSE
5876
5877    ========================================================================
5878*/
5879void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry)
5880{
5881        HTTRANSMIT_SETTING TransmitSetting;
5882
5883        if (fixed_tx_mode == FIXED_TXMODE_HT)
5884                return;
5885
5886        TransmitSetting.word = 0;
5887
5888        TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5889        TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5890
5891        if (fixed_tx_mode == FIXED_TXMODE_CCK) {
5892                TransmitSetting.field.MODE = MODE_CCK;
5893                /* CCK mode allow MCS 0~3 */
5894                if (TransmitSetting.field.MCS > MCS_3)
5895                        TransmitSetting.field.MCS = MCS_3;
5896        } else {
5897                TransmitSetting.field.MODE = MODE_OFDM;
5898                /* OFDM mode allow MCS 0~7 */
5899                if (TransmitSetting.field.MCS > MCS_7)
5900                        TransmitSetting.field.MCS = MCS_7;
5901        }
5902
5903        if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) {
5904                pEntry->HTPhyMode.word = TransmitSetting.word;
5905                DBGPRINT(RT_DEBUG_TRACE,
5906                         ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5907                          pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE),
5908                          pEntry->HTPhyMode.field.MCS));
5909        }
5910}
5911
5912/*
5913        ==========================================================================
5914        Description:
5915                dynamic tune BBP R66 to find a balance between sensibility and
5916                noise isolation
5917
5918        IRQL = DISPATCH_LEVEL
5919
5920        ==========================================================================
5921 */
5922void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd)
5923{
5924        u8 OrigR66Value = 0, R66;       /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */
5925        char Rssi;
5926
5927        /* 2860C did not support Fase CCA, therefore can't tune */
5928        if (pAd->MACVersion == 0x28600100)
5929                return;
5930
5931        /* */
5932        /* work as a STA */
5933        /* */
5934        if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)       /* no R66 tuning when SCANNING */
5935                return;
5936
5937        if ((pAd->OpMode == OPMODE_STA)
5938            && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5939            )
5940            && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
5941#ifdef RTMP_MAC_PCI
5942            && (pAd->bPCIclkOff == FALSE)
5943#endif /* RTMP_MAC_PCI // */
5944            ) {
5945                RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5946                R66 = OrigR66Value;
5947
5948                if (pAd->Antenna.field.RxPath > 1)
5949                        Rssi =
5950                            (pAd->StaCfg.RssiSample.AvgRssi0 +
5951                             pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
5952                else
5953                        Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5954
5955                if (pAd->LatchRfRegs.Channel <= 14) {   /*BG band */
5956#ifdef RT30xx
5957                        /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */
5958                        /* Otherwise, it will have some throughput side effect when low RSSI */
5959
5960                        if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
5961                            || IS_RT3390(pAd)) {
5962                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5963                                        R66 =
5964                                            0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20;
5965                                        if (OrigR66Value != R66) {
5966                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
5967                                                    (pAd, BBP_R66, R66);
5968                                        }
5969                                } else {
5970                                        R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
5971                                        if (OrigR66Value != R66) {
5972                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
5973                                                    (pAd, BBP_R66, R66);
5974                                        }
5975                                }
5976                        } else
5977#endif /* RT30xx // */
5978                        {
5979                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5980                                        R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
5981                                        if (OrigR66Value != R66) {
5982                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
5983                                                    (pAd, BBP_R66, R66);
5984                                        }
5985                                } else {
5986                                        R66 = 0x2E + GET_LNA_GAIN(pAd);
5987                                        if (OrigR66Value != R66) {
5988                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
5989                                                    (pAd, BBP_R66, R66);
5990                                        }
5991                                }
5992                        }
5993                } else {        /*A band */
5994                        if (pAd->CommonCfg.BBPCurrentBW == BW_20) {
5995                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5996                                        R66 =
5997                                            0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 +
5998                                            0x10;
5999                                        if (OrigR66Value != R66) {
6000                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
6001                                                    (pAd, BBP_R66, R66);
6002                                        }
6003                                } else {
6004                                        R66 =
6005                                            0x32 + (GET_LNA_GAIN(pAd) * 5) / 3;
6006                                        if (OrigR66Value != R66) {
6007                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
6008                                                    (pAd, BBP_R66, R66);
6009                                        }
6010                                }
6011                        } else {
6012                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6013                                        R66 =
6014                                            0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 +
6015                                            0x10;
6016                                        if (OrigR66Value != R66) {
6017                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
6018                                                    (pAd, BBP_R66, R66);
6019                                        }
6020                                } else {
6021                                        R66 =
6022                                            0x3A + (GET_LNA_GAIN(pAd) * 5) / 3;
6023                                        if (OrigR66Value != R66) {
6024                                                RTMP_BBP_IO_WRITE8_BY_REG_ID
6025                                                    (pAd, BBP_R66, R66);
6026                                        }
6027                                }
6028                        }
6029                }
6030
6031        }
6032}
6033
6034void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth)
6035{
6036        u8 R66 = 0x30;
6037
6038        if (pAd->LatchRfRegs.Channel <= 14) {   /* BG band */
6039#ifdef RT30xx
6040                /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6041
6042                if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
6043                    || IS_RT3390(pAd)) {
6044                        R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
6045                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6046                } else
6047#endif /* RT30xx // */
6048                {
6049                        R66 = 0x2E + GET_LNA_GAIN(pAd);
6050                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6051                }
6052        } else {                /*A band */
6053                {
6054                        if (BandWidth == BW_20) {
6055                                R66 =
6056                                    (u8)(0x32 +
6057                                             (GET_LNA_GAIN(pAd) * 5) / 3);
6058                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6059                        } else {
6060                                R66 =
6061                                    (u8)(0x3A +
6062                                             (GET_LNA_GAIN(pAd) * 5) / 3);
6063                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6064                        }
6065                }
6066        }
6067
6068}
6069