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