linux/drivers/staging/rt2860/common/mlme.c
<<
>>
Prefs
   1/*
   2 *************************************************************************
   3 * Ralink Tech Inc.
   4 * 5F., No.36, Taiyuan St., Jhubei City,
   5 * Hsinchu County 302,
   6 * Taiwan, R.O.C.
   7 *
   8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify  *
  11 * it under the terms of the GNU General Public License as published by  *
  12 * the Free Software Foundation; either version 2 of the License, or     *
  13 * (at your option) any later version.                                   *
  14 *                                                                       *
  15 * This program is distributed in the hope that it will be useful,       *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  18 * GNU General Public License for more details.                          *
  19 *                                                                       *
  20 * You should have received a copy of the GNU General Public License     *
  21 * along with this program; if not, write to the                         *
  22 * Free Software Foundation, Inc.,                                       *
  23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  24 *                                                                       *
  25 *************************************************************************
  26
  27        Module Name:
  28        mlme.c
  29
  30        Abstract:
  31
  32        Revision History:
  33        Who                     When                    What
  34        --------        ----------              ----------------------------------------------
  35        John Chang      2004-08-25              Modify from RT2500 code base
  36        John Chang      2004-09-06              modified for RT2600
  37*/
  38
  39#include "../rt_config.h"
  40#include <stdarg.h>
  41
  42UCHAR   CISCO_OUI[] = {0x00, 0x40, 0x96};
  43
  44UCHAR   WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
  45UCHAR   RSN_OUI[] = {0x00, 0x0f, 0xac};
  46UCHAR   WME_INFO_ELEM[]  = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
  47UCHAR   WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  48UCHAR   Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
  49UCHAR   RALINK_OUI[]  = {0x00, 0x0c, 0x43};
  50UCHAR   BROADCOM_OUI[]  = {0x00, 0x90, 0x4c};
  51UCHAR   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
  52UCHAR   PRE_N_HT_OUI[]  = {0x00, 0x90, 0x4c};
  53
  54UCHAR RateSwitchTable[] = {
  55// 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)
  56    0x11, 0x00,  0,  0,  0,                                             // Initial used item after association
  57    0x00, 0x00,  0, 40, 101,
  58    0x01, 0x00,  1, 40, 50,
  59    0x02, 0x00,  2, 35, 45,
  60    0x03, 0x00,  3, 20, 45,
  61    0x04, 0x21,  0, 30, 50,
  62    0x05, 0x21,  1, 20, 50,
  63    0x06, 0x21,  2, 20, 50,
  64    0x07, 0x21,  3, 15, 50,
  65    0x08, 0x21,  4, 15, 30,
  66    0x09, 0x21,  5, 10, 25,
  67    0x0a, 0x21,  6,  8, 25,
  68    0x0b, 0x21,  7,  8, 25,
  69    0x0c, 0x20, 12,  15, 30,
  70    0x0d, 0x20, 13,  8, 20,
  71    0x0e, 0x20, 14,  8, 20,
  72    0x0f, 0x20, 15,  8, 25,
  73    0x10, 0x22, 15,  8, 25,
  74    0x11, 0x00,  0,  0,  0,
  75    0x12, 0x00,  0,  0,  0,
  76    0x13, 0x00,  0,  0,  0,
  77    0x14, 0x00,  0,  0,  0,
  78    0x15, 0x00,  0,  0,  0,
  79    0x16, 0x00,  0,  0,  0,
  80    0x17, 0x00,  0,  0,  0,
  81    0x18, 0x00,  0,  0,  0,
  82    0x19, 0x00,  0,  0,  0,
  83    0x1a, 0x00,  0,  0,  0,
  84    0x1b, 0x00,  0,  0,  0,
  85    0x1c, 0x00,  0,  0,  0,
  86    0x1d, 0x00,  0,  0,  0,
  87    0x1e, 0x00,  0,  0,  0,
  88    0x1f, 0x00,  0,  0,  0,
  89};
  90
  91UCHAR RateSwitchTable11B[] = {
  92// 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)
  93    0x04, 0x03,  0,  0,  0,                                             // Initial used item after association
  94    0x00, 0x00,  0, 40, 101,
  95    0x01, 0x00,  1, 40, 50,
  96    0x02, 0x00,  2, 35, 45,
  97    0x03, 0x00,  3, 20, 45,
  98};
  99
 100UCHAR RateSwitchTable11BG[] = {
 101// 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)
 102    0x0a, 0x00,  0,  0,  0,                                             // Initial used item after association
 103    0x00, 0x00,  0, 40, 101,
 104    0x01, 0x00,  1, 40, 50,
 105    0x02, 0x00,  2, 35, 45,
 106    0x03, 0x00,  3, 20, 45,
 107    0x04, 0x10,  2, 20, 35,
 108    0x05, 0x10,  3, 16, 35,
 109    0x06, 0x10,  4, 10, 25,
 110    0x07, 0x10,  5, 16, 25,
 111    0x08, 0x10,  6, 10, 25,
 112    0x09, 0x10,  7, 10, 13,
 113};
 114
 115UCHAR RateSwitchTable11G[] = {
 116// 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)
 117    0x08, 0x00,  0,  0,  0,                                             // Initial used item after association
 118    0x00, 0x10,  0, 20, 101,
 119    0x01, 0x10,  1, 20, 35,
 120    0x02, 0x10,  2, 20, 35,
 121    0x03, 0x10,  3, 16, 35,
 122    0x04, 0x10,  4, 10, 25,
 123    0x05, 0x10,  5, 16, 25,
 124    0x06, 0x10,  6, 10, 25,
 125    0x07, 0x10,  7, 10, 13,
 126};
 127
 128UCHAR RateSwitchTable11N1S[] = {
 129// 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)
 130    0x09, 0x00,  0,  0,  0,                                             // Initial used item after association
 131    0x00, 0x21,  0, 30, 101,
 132    0x01, 0x21,  1, 20, 50,
 133    0x02, 0x21,  2, 20, 50,
 134    0x03, 0x21,  3, 15, 50,
 135    0x04, 0x21,  4, 15, 30,
 136    0x05, 0x21,  5, 10, 25,
 137    0x06, 0x21,  6,  8, 14,
 138    0x07, 0x21,  7,  8, 14,
 139    0x08, 0x23,  7,  8, 14,
 140};
 141
 142UCHAR RateSwitchTable11N2S[] = {
 143// 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)
 144    0x0a, 0x00,  0,  0,  0,      // Initial used item after association
 145    0x00, 0x21,  0, 30, 101,
 146    0x01, 0x21,  1, 20, 50,
 147    0x02, 0x21,  2, 20, 50,
 148    0x03, 0x21,  3, 15, 50,
 149    0x04, 0x21,  4, 15, 30,
 150    0x05, 0x20, 12,  15, 30,
 151    0x06, 0x20, 13,  8, 20,
 152    0x07, 0x20, 14,  8, 20,
 153    0x08, 0x20, 15,  8, 25,
 154    0x09, 0x22, 15,  8, 25,
 155};
 156
 157UCHAR RateSwitchTable11N3S[] = {
 158// 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)
 159    0x0a, 0x00,  0,  0,  0,      // Initial used item after association
 160    0x00, 0x21,  0, 30, 101,
 161    0x01, 0x21,  1, 20, 50,
 162    0x02, 0x21,  2, 20, 50,
 163    0x03, 0x21,  3, 15, 50,
 164    0x04, 0x21,  4, 15, 30,
 165    0x05, 0x20, 12,  15, 30,
 166    0x06, 0x20, 13,  8, 20,
 167    0x07, 0x20, 14,  8, 20,
 168    0x08, 0x20, 15,  8, 25,
 169    0x09, 0x22, 15,  8, 25,
 170};
 171
 172UCHAR RateSwitchTable11N2SForABand[] = {
 173// 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)
 174    0x0b, 0x09,  0,  0,  0,                                             // Initial used item after association
 175    0x00, 0x21,  0, 30, 101,
 176    0x01, 0x21,  1, 20, 50,
 177    0x02, 0x21,  2, 20, 50,
 178    0x03, 0x21,  3, 15, 50,
 179    0x04, 0x21,  4, 15, 30,
 180    0x05, 0x21,  5, 15, 30,
 181    0x06, 0x20, 12,  15, 30,
 182    0x07, 0x20, 13,  8, 20,
 183    0x08, 0x20, 14,  8, 20,
 184    0x09, 0x20, 15,  8, 25,
 185    0x0a, 0x22, 15,  8, 25,
 186};
 187
 188UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
 189// 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)
 190    0x0b, 0x09,  0,  0,  0,                                             // Initial used item after association
 191    0x00, 0x21,  0, 30, 101,
 192    0x01, 0x21,  1, 20, 50,
 193    0x02, 0x21,  2, 20, 50,
 194    0x03, 0x21,  3, 15, 50,
 195    0x04, 0x21,  4, 15, 30,
 196    0x05, 0x21,  5, 15, 30,
 197    0x06, 0x20, 12,  15, 30,
 198    0x07, 0x20, 13,  8, 20,
 199    0x08, 0x20, 14,  8, 20,
 200    0x09, 0x20, 15,  8, 25,
 201    0x0a, 0x22, 15,  8, 25,
 202};
 203
 204UCHAR RateSwitchTable11BGN1S[] = {
 205// 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)
 206    0x0d, 0x00,  0,  0,  0,                                             // Initial used item after association
 207    0x00, 0x00,  0, 40, 101,
 208    0x01, 0x00,  1, 40, 50,
 209    0x02, 0x00,  2, 35, 45,
 210    0x03, 0x00,  3, 20, 45,
 211    0x04, 0x21,  0, 30,101,     //50
 212    0x05, 0x21,  1, 20, 50,
 213    0x06, 0x21,  2, 20, 50,
 214    0x07, 0x21,  3, 15, 50,
 215    0x08, 0x21,  4, 15, 30,
 216    0x09, 0x21,  5, 10, 25,
 217    0x0a, 0x21,  6,  8, 14,
 218    0x0b, 0x21,  7,  8, 14,
 219        0x0c, 0x23,  7,  8, 14,
 220};
 221
 222UCHAR RateSwitchTable11BGN2S[] = {
 223// 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)
 224    0x0a, 0x00,  0,  0,  0,                                             // Initial used item after association
 225    0x00, 0x21,  0, 30,101,     //50
 226    0x01, 0x21,  1, 20, 50,
 227    0x02, 0x21,  2, 20, 50,
 228    0x03, 0x21,  3, 15, 50,
 229    0x04, 0x21,  4, 15, 30,
 230    0x05, 0x20, 12, 15, 30,
 231    0x06, 0x20, 13,  8, 20,
 232    0x07, 0x20, 14,  8, 20,
 233    0x08, 0x20, 15,  8, 25,
 234    0x09, 0x22, 15,  8, 25,
 235};
 236
 237UCHAR RateSwitchTable11BGN3S[] = { // 3*3
 238// 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)
 239    0x0a, 0x00,  0,  0,  0,                                             // Initial used item after association
 240    0x00, 0x21,  0, 30,101,     //50
 241    0x01, 0x21,  1, 20, 50,
 242    0x02, 0x21,  2, 20, 50,
 243    0x03, 0x21,  3, 20, 50,
 244    0x04, 0x21,  4, 15, 50,
 245    0x05, 0x20, 20, 15, 30,
 246    0x06, 0x20, 21,  8, 20,
 247    0x07, 0x20, 22,  8, 20,
 248    0x08, 0x20, 23,  8, 25,
 249    0x09, 0x22, 23,  8, 25,
 250};
 251
 252UCHAR RateSwitchTable11BGN2SForABand[] = {
 253// 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)
 254    0x0b, 0x09,  0,  0,  0,                                             // Initial used item after association
 255    0x00, 0x21,  0, 30,101,     //50
 256    0x01, 0x21,  1, 20, 50,
 257    0x02, 0x21,  2, 20, 50,
 258    0x03, 0x21,  3, 15, 50,
 259    0x04, 0x21,  4, 15, 30,
 260    0x05, 0x21,  5, 15, 30,
 261    0x06, 0x20, 12, 15, 30,
 262    0x07, 0x20, 13,  8, 20,
 263    0x08, 0x20, 14,  8, 20,
 264    0x09, 0x20, 15,  8, 25,
 265    0x0a, 0x22, 15,  8, 25,
 266};
 267
 268UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
 269// 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)
 270    0x0c, 0x09,  0,  0,  0,                                             // Initial used item after association
 271    0x00, 0x21,  0, 30,101,     //50
 272    0x01, 0x21,  1, 20, 50,
 273    0x02, 0x21,  2, 20, 50,
 274    0x03, 0x21,  3, 15, 50,
 275    0x04, 0x21,  4, 15, 30,
 276    0x05, 0x21,  5, 15, 30,
 277    0x06, 0x21, 12, 15, 30,
 278    0x07, 0x20, 20, 15, 30,
 279    0x08, 0x20, 21,  8, 20,
 280    0x09, 0x20, 22,  8, 20,
 281    0x0a, 0x20, 23,  8, 25,
 282    0x0b, 0x22, 23,  8, 25,
 283};
 284
 285PUCHAR ReasonString[] = {
 286        /* 0  */         "Reserved",
 287        /* 1  */         "Unspecified Reason",
 288        /* 2  */         "Previous Auth no longer valid",
 289        /* 3  */         "STA is leaving / has left",
 290        /* 4  */         "DIS-ASSOC due to inactivity",
 291        /* 5  */         "AP unable to hanle all associations",
 292        /* 6  */         "class 2 error",
 293        /* 7  */         "class 3 error",
 294        /* 8  */         "STA is leaving / has left",
 295        /* 9  */         "require auth before assoc/re-assoc",
 296        /* 10 */         "Reserved",
 297        /* 11 */         "Reserved",
 298        /* 12 */         "Reserved",
 299        /* 13 */         "invalid IE",
 300        /* 14 */         "MIC error",
 301        /* 15 */         "4-way handshake timeout",
 302        /* 16 */         "2-way (group key) handshake timeout",
 303        /* 17 */         "4-way handshake IE diff among AssosReq/Rsp/Beacon",
 304        /* 18 */
 305};
 306
 307extern UCHAR     OfdmRateToRxwiMCS[];
 308// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
 309// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
 310ULONG BasicRateMask[12]                         = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
 311                                                                          0xfffff01f /* 6 */     , 0xfffff03f /* 9 */     , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
 312                                                                          0xfffff1ff /* 24 */    , 0xfffff3ff /* 36 */    , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
 313
 314UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1,  0x00, 0x00, 0x00, 0x00, 0x00};
 315UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 316UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]  = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 317
 318// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
 319//              this value, then it's quaranteed capable of operating in 36 mbps TX rate in
 320//              clean environment.
 321//                                                                TxRate: 1   2   5.5   11       6        9    12       18       24   36   48   54       72  100
 322CHAR RssiSafeLevelForTxRate[] ={  -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
 323
 324UCHAR  RateIdToMbps[]    = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
 325USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
 326
 327UCHAR  SsidIe    = IE_SSID;
 328UCHAR  SupRateIe = IE_SUPP_RATES;
 329UCHAR  ExtRateIe = IE_EXT_SUPP_RATES;
 330UCHAR  HtCapIe = IE_HT_CAP;
 331UCHAR  AddHtInfoIe = IE_ADD_HT;
 332UCHAR  NewExtChanIe = IE_SECONDARY_CH_OFFSET;
 333UCHAR  ErpIe     = IE_ERP;
 334UCHAR  DsIe      = IE_DS_PARM;
 335UCHAR  TimIe     = IE_TIM;
 336UCHAR  WpaIe     = IE_WPA;
 337UCHAR  Wpa2Ie    = IE_WPA2;
 338UCHAR  IbssIe    = IE_IBSS_PARM;
 339UCHAR  Ccx2Ie    = IE_CCX_V2;
 340
 341extern UCHAR    WPA_OUI[];
 342
 343UCHAR   SES_OUI[] = {0x00, 0x90, 0x4c};
 344
 345UCHAR   ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 346        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 347
 348// Reset the RFIC setting to new series
 349RTMP_RF_REGS RF2850RegTable[] = {
 350//              ch       R1              R2              R3(TX0~4=0) R4
 351                {1,  0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
 352                {2,  0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
 353                {3,  0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
 354                {4,  0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
 355                {5,  0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
 356                {6,  0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
 357                {7,  0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
 358                {8,  0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
 359                {9,  0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
 360                {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
 361                {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
 362                {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
 363                {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
 364                {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
 365
 366                // 802.11 UNI / HyperLan 2
 367                {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
 368                {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
 369                {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
 370                {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
 371                {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
 372                {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
 373                {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
 374                {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
 375                {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
 376                {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
 377                {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
 378                {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
 379
 380                // 802.11 HyperLan 2
 381                {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
 382
 383                // 2008.04.30 modified
 384                // The system team has AN to improve the EVM value
 385                // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
 386                {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
 387                {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
 388                {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
 389
 390                {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
 391                {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
 392                {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
 393                {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
 394                {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
 395                {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
 396                {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
 397                {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
 398                {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
 399                {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
 400                {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
 401                {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
 402
 403                // 802.11 UNII
 404                {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
 405                {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
 406                {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
 407                {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
 408                {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
 409                {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
 410                {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
 411
 412                // Japan
 413                {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
 414                {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
 415                {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
 416                {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
 417                {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
 418                {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
 419                {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
 420
 421                // still lack of MMAC(Japan) ch 34,38,42,46
 422};
 423UCHAR   NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
 424
 425FREQUENCY_ITEM FreqItems3020[] =
 426{
 427        /**************************************************/
 428        // ISM : 2.4 to 2.483 GHz                         //
 429        /**************************************************/
 430        // 11g
 431        /**************************************************/
 432        //-CH---N-------R---K-----------
 433        {1,    241,  2,  2},
 434        {2,    241,      2,  7},
 435        {3,    242,      2,  2},
 436        {4,    242,      2,  7},
 437        {5,    243,      2,  2},
 438        {6,    243,      2,  7},
 439        {7,    244,      2,  2},
 440        {8,    244,      2,  7},
 441        {9,    245,      2,  2},
 442        {10,   245,      2,  7},
 443        {11,   246,      2,  2},
 444        {12,   246,      2,  7},
 445        {13,   247,      2,  2},
 446        {14,   248,      2,  4},
 447};
 448UCHAR   NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
 449
 450/*
 451        ==========================================================================
 452        Description:
 453                initialize the MLME task and its data structure (queue, spinlock,
 454                timer, state machines).
 455
 456        IRQL = PASSIVE_LEVEL
 457
 458        Return:
 459                always return NDIS_STATUS_SUCCESS
 460
 461        ==========================================================================
 462*/
 463NDIS_STATUS MlmeInit(
 464        IN PRTMP_ADAPTER pAd)
 465{
 466        NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
 467
 468        DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
 469
 470        do
 471        {
 472                Status = MlmeQueueInit(&pAd->Mlme.Queue);
 473                if(Status != NDIS_STATUS_SUCCESS)
 474                        break;
 475
 476                pAd->Mlme.bRunning = FALSE;
 477                NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
 478
 479                {
 480                        BssTableInit(&pAd->ScanTab);
 481
 482                        // init STA state machines
 483                        AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
 484                        AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
 485                        AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
 486                        SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
 487                        WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
 488                        AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
 489
 490                        // Since we are using switch/case to implement it, the init is different from the above
 491                        // state machine init
 492                        MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
 493                }
 494
 495                ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
 496
 497                // Init mlme periodic timer
 498                RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
 499
 500                // Set mlme periodic timer
 501                RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
 502
 503                // software-based RX Antenna diversity
 504                RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
 505
 506#ifdef RT2860
 507                {
 508                if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
 509                {
 510                    // only PCIe cards need these two timers
 511                        RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
 512                        RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
 513                }
 514                }
 515#endif
 516        } while (FALSE);
 517
 518        DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
 519
 520        return Status;
 521}
 522
 523/*
 524        ==========================================================================
 525        Description:
 526                main loop of the MLME
 527        Pre:
 528                Mlme has to be initialized, and there are something inside the queue
 529        Note:
 530                This function is invoked from MPSetInformation and MPReceive;
 531                This task guarantee only one MlmeHandler will run.
 532
 533        IRQL = DISPATCH_LEVEL
 534
 535        ==========================================================================
 536 */
 537VOID MlmeHandler(
 538        IN PRTMP_ADAPTER pAd)
 539{
 540        MLME_QUEUE_ELEM            *Elem = NULL;
 541
 542        // Only accept MLME and Frame from peer side, no other (control/data) frame should
 543        // get into this state machine
 544
 545        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
 546        if(pAd->Mlme.bRunning)
 547        {
 548                NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
 549                return;
 550        }
 551        else
 552        {
 553                pAd->Mlme.bRunning = TRUE;
 554        }
 555        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
 556
 557        while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
 558        {
 559                if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
 560                        RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
 561                        RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
 562                {
 563                        DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
 564                        break;
 565                }
 566
 567                //From message type, determine which state machine I should drive
 568                if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
 569                {
 570#ifdef RT2870
 571                        if (Elem->MsgType == MT2_RESET_CONF)
 572                        {
 573                                DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
 574                                MlmeRestartStateMachine(pAd);
 575                                Elem->Occupied = FALSE;
 576                                Elem->MsgLen = 0;
 577                                continue;
 578                        }
 579#endif // RT2870 //
 580
 581                        // if dequeue success
 582                        switch (Elem->Machine)
 583                        {
 584                                // STA state machines
 585                                case ASSOC_STATE_MACHINE:
 586                                        StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
 587                                        break;
 588                                case AUTH_STATE_MACHINE:
 589                                        StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
 590                                        break;
 591                                case AUTH_RSP_STATE_MACHINE:
 592                                        StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
 593                                        break;
 594                                case SYNC_STATE_MACHINE:
 595                                        StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
 596                                        break;
 597                                case MLME_CNTL_STATE_MACHINE:
 598                                        MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
 599                                        break;
 600                                case WPA_PSK_STATE_MACHINE:
 601                                        StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
 602                                        break;
 603                                case AIRONET_STATE_MACHINE:
 604                                        StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
 605                                        break;
 606                                case ACTION_STATE_MACHINE:
 607                                        StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
 608                                        break;
 609
 610
 611
 612
 613                                default:
 614                                        DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
 615                                        break;
 616                        } // end of switch
 617
 618                        // free MLME element
 619                        Elem->Occupied = FALSE;
 620                        Elem->MsgLen = 0;
 621
 622                }
 623                else {
 624                        DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
 625                }
 626        }
 627
 628        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
 629        pAd->Mlme.bRunning = FALSE;
 630        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
 631}
 632
 633/*
 634        ==========================================================================
 635        Description:
 636                Destructor of MLME (Destroy queue, state machine, spin lock and timer)
 637        Parameters:
 638                Adapter - NIC Adapter pointer
 639        Post:
 640                The MLME task will no longer work properly
 641
 642        IRQL = PASSIVE_LEVEL
 643
 644        ==========================================================================
 645 */
 646VOID MlmeHalt(
 647        IN PRTMP_ADAPTER pAd)
 648{
 649        BOOLEAN           Cancelled;
 650#ifdef RT3070
 651        UINT32          TxPinCfg = 0x00050F0F;
 652#endif // RT3070 //
 653
 654        DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
 655
 656        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
 657        {
 658                // disable BEACON generation and other BEACON related hardware timers
 659                AsicDisableSync(pAd);
 660        }
 661
 662        {
 663                // Cancel pending timers
 664                RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,               &Cancelled);
 665                RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,             &Cancelled);
 666                RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,    &Cancelled);
 667                RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,                &Cancelled);
 668                RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,              &Cancelled);
 669                RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,                &Cancelled);
 670#ifdef RT2860
 671            if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
 672            {
 673                    RTMPCancelTimer(&pAd->Mlme.PsPollTimer,             &Cancelled);
 674                    RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,         &Cancelled);
 675                }
 676#endif
 677        }
 678
 679        RTMPCancelTimer(&pAd->Mlme.PeriodicTimer,               &Cancelled);
 680        RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer,              &Cancelled);
 681
 682
 683
 684        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
 685        {
 686                // Set LED
 687                RTMPSetLED(pAd, LED_HALT);
 688        RTMPSetSignalLED(pAd, -100);    // Force signal strength Led to be turned off, firmware is not done it.
 689#ifdef RT2870
 690        {
 691            LED_CFG_STRUC LedCfg;
 692            RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
 693            LedCfg.field.LedPolar = 0;
 694            LedCfg.field.RLedMode = 0;
 695            LedCfg.field.GLedMode = 0;
 696            LedCfg.field.YLedMode = 0;
 697            RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
 698        }
 699#endif // RT2870 //
 700#ifdef RT3070
 701                //
 702                // Turn off LNA_PE
 703                //
 704                if (IS_RT3070(pAd) || IS_RT3071(pAd))
 705                {
 706                        TxPinCfg &= 0xFFFFF0F0;
 707                        RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
 708                }
 709#endif // RT3070 //
 710        }
 711
 712        RTMPusecDelay(5000);    //  5 msec to gurantee Ant Diversity timer canceled
 713
 714        MlmeQueueDestroy(&pAd->Mlme.Queue);
 715        NdisFreeSpinLock(&pAd->Mlme.TaskLock);
 716
 717        DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
 718}
 719
 720VOID MlmeResetRalinkCounters(
 721        IN  PRTMP_ADAPTER   pAd)
 722{
 723        pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
 724        // clear all OneSecxxx counters.
 725        pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
 726        pAd->RalinkCounters.OneSecFalseCCACnt = 0;
 727        pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
 728        pAd->RalinkCounters.OneSecRxOkCnt = 0;
 729        pAd->RalinkCounters.OneSecTxFailCount = 0;
 730        pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
 731        pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
 732        pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
 733
 734        // TODO: for debug only. to be removed
 735        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
 736        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
 737        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
 738        pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
 739        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
 740        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
 741        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
 742        pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
 743        pAd->RalinkCounters.OneSecTxDoneCount = 0;
 744        pAd->RalinkCounters.OneSecRxCount = 0;
 745        pAd->RalinkCounters.OneSecTxAggregationCount = 0;
 746        pAd->RalinkCounters.OneSecRxAggregationCount = 0;
 747
 748        return;
 749}
 750
 751unsigned long rx_AMSDU;
 752unsigned long rx_Total;
 753
 754/*
 755        ==========================================================================
 756        Description:
 757                This routine is executed periodically to -
 758                1. Decide if it's a right time to turn on PwrMgmt bit of all
 759                   outgoiing frames
 760                2. Calculate ChannelQuality based on statistics of the last
 761                   period, so that TX rate won't toggling very frequently between a
 762                   successful TX and a failed TX.
 763                3. If the calculated ChannelQuality indicated current connection not
 764                   healthy, then a ROAMing attempt is tried here.
 765
 766        IRQL = DISPATCH_LEVEL
 767
 768        ==========================================================================
 769 */
 770#define ADHOC_BEACON_LOST_TIME          (8*OS_HZ)  // 8 sec
 771VOID MlmePeriodicExec(
 772        IN PVOID SystemSpecific1,
 773        IN PVOID FunctionContext,
 774        IN PVOID SystemSpecific2,
 775        IN PVOID SystemSpecific3)
 776{
 777        ULONG                   TxTotalCnt;
 778        PRTMP_ADAPTER   pAd = (RTMP_ADAPTER *)FunctionContext;
 779
 780#ifdef RT2860
 781        //Baron 2008/07/10
 782        //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
 783        //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
 784        //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
 785        if(pAd->StaCfg.WepStatus<2)
 786        {
 787                pAd->StaCfg.WpaSupplicantUP = 0;
 788        }
 789        else
 790        {
 791                pAd->StaCfg.WpaSupplicantUP = 1;
 792        }
 793
 794        {
 795            // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
 796                // Move code to here, because following code will return when radio is off
 797                if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
 798                        (pAd->StaCfg.bHardwareRadio == TRUE) &&
 799                        (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
 800                        (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
 801                        (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
 802                {
 803                        UINT32                          data = 0;
 804
 805                        // Read GPIO pin2 as Hardware controlled radio state
 806                        RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
 807                        if (data & 0x04)
 808                        {
 809                                pAd->StaCfg.bHwRadio = TRUE;
 810                        }
 811                        else
 812                        {
 813                                pAd->StaCfg.bHwRadio = FALSE;
 814                        }
 815                        if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
 816                        {
 817                                pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
 818                                if (pAd->StaCfg.bRadio == TRUE)
 819                                {
 820                                        MlmeRadioOn(pAd);
 821                                        // Update extra information
 822                                        pAd->ExtraInfo = EXTRA_INFO_CLEAR;
 823                                }
 824                                else
 825                                {
 826                                        MlmeRadioOff(pAd);
 827                                        // Update extra information
 828                                        pAd->ExtraInfo = HW_RADIO_OFF;
 829                                }
 830                        }
 831                }
 832        }
 833#endif /* RT2860 */
 834
 835        // Do nothing if the driver is starting halt state.
 836        // This might happen when timer already been fired before cancel timer with mlmehalt
 837        if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
 838                                                                fRTMP_ADAPTER_RADIO_OFF |
 839                                                                fRTMP_ADAPTER_RADIO_MEASUREMENT |
 840                                                                fRTMP_ADAPTER_RESET_IN_PROGRESS))))
 841                return;
 842
 843#ifdef RT2860
 844        {
 845                if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
 846                {
 847                        // If ReceiveByteCount doesn't change,  increase SameRxByteCount by 1.
 848                        pAd->SameRxByteCount++;
 849                }
 850                else
 851                        pAd->SameRxByteCount = 0;
 852
 853                // If after BBP, still not work...need to check to reset PBF&MAC.
 854                if (pAd->SameRxByteCount == 702)
 855                {
 856                        pAd->SameRxByteCount = 0;
 857                        AsicResetPBF(pAd);
 858                        AsicResetMAC(pAd);
 859                }
 860
 861                // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
 862                if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
 863                {
 864                        if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
 865                        {
 866                                DBGPRINT(RT_DEBUG_TRACE, ("--->  SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
 867                                pAd->SameRxByteCount = 700;
 868                                AsicResetBBP(pAd);
 869                        }
 870                }
 871
 872                // Update lastReceiveByteCount.
 873                pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
 874
 875                if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
 876                {
 877                        pAd->CheckDmaBusyCount = 0;
 878                        AsicResetFromDMABusy(pAd);
 879                }
 880        }
 881#endif /* RT2860 */
 882        RT28XX_MLME_PRE_SANITY_CHECK(pAd);
 883
 884        {
 885                // Do nothing if monitor mode is on
 886                if (MONITOR_ON(pAd))
 887                        return;
 888
 889                if (pAd->Mlme.PeriodicRound & 0x1)
 890                {
 891                        // This is the fix for wifi 11n extension channel overlapping test case.  for 2860D
 892                        if (((pAd->MACVersion & 0xffff) == 0x0101) &&
 893                                (STA_TGN_WIFI_ON(pAd)) &&
 894                                (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
 895
 896                                {
 897                                        RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
 898                                        pAd->CommonCfg.IOTestParm.bToggle = TRUE;
 899                                }
 900                                else if ((STA_TGN_WIFI_ON(pAd)) &&
 901                                                ((pAd->MACVersion & 0xffff) == 0x0101))
 902                                {
 903                                        RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
 904                                        pAd->CommonCfg.IOTestParm.bToggle = FALSE;
 905                                }
 906                }
 907        }
 908
 909        pAd->bUpdateBcnCntDone = FALSE;
 910
 911//      RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
 912        pAd->Mlme.PeriodicRound ++;
 913
 914#ifdef RT3070
 915        // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
 916        NICUpdateFifoStaCounters(pAd);
 917#endif // RT3070 //
 918        // execute every 500ms
 919        if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
 920        {
 921                // perform dynamic tx rate switching based on past TX history
 922                {
 923                        if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
 924                                        )
 925                                && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
 926                                MlmeDynamicTxRateSwitching(pAd);
 927                }
 928        }
 929
 930        // Normal 1 second Mlme PeriodicExec.
 931        if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
 932        {
 933                pAd->Mlme.OneSecPeriodicRound ++;
 934
 935                if (rx_Total)
 936                {
 937
 938                        // reset counters
 939                        rx_AMSDU = 0;
 940                        rx_Total = 0;
 941                }
 942
 943                // Media status changed, report to NDIS
 944                if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
 945                {
 946                        RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
 947                        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
 948                        {
 949                                pAd->IndicateMediaState = NdisMediaStateConnected;
 950                                RTMP_IndicateMediaState(pAd);
 951
 952                        }
 953                        else
 954                        {
 955                                pAd->IndicateMediaState = NdisMediaStateDisconnected;
 956                                RTMP_IndicateMediaState(pAd);
 957                        }
 958                }
 959
 960                NdisGetSystemUpTime(&pAd->Mlme.Now32);
 961
 962                // add the most up-to-date h/w raw counters into software variable, so that
 963                // the dynamic tuning mechanism below are based on most up-to-date information
 964                NICUpdateRawCounters(pAd);
 965
 966#ifdef RT2870
 967                RT2870_WatchDog(pAd);
 968#endif // RT2870 //
 969
 970                // Need statistics after read counter. So put after NICUpdateRawCounters
 971                ORIBATimerTimeout(pAd);
 972
 973                // The time period for checking antenna is according to traffic
 974                if (pAd->Mlme.bEnableAutoAntennaCheck)
 975                {
 976                        TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
 977                                                         pAd->RalinkCounters.OneSecTxRetryOkCount +
 978                                                         pAd->RalinkCounters.OneSecTxFailCount;
 979
 980                        // dynamic adjust antenna evaluation period according to the traffic
 981                        if (TxTotalCnt > 50)
 982                        {
 983                                if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
 984                                {
 985                                        AsicEvaluateRxAnt(pAd);
 986                                }
 987                        }
 988                        else
 989                        {
 990                                if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
 991                                {
 992                                        AsicEvaluateRxAnt(pAd);
 993                                }
 994                        }
 995                }
 996
 997                STAMlmePeriodicExec(pAd);
 998
 999                MlmeResetRalinkCounters(pAd);
1000
1001                {
1002#ifdef RT2860
1003                        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1004#endif
1005                        {
1006                                // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1007                                // and sending CTS-to-self over and over.
1008                                // Software Patch Solution:
1009                                // 1. Polling debug state register 0x10F4 every one second.
1010                                // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1011                                // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1012
1013                                UINT32  MacReg = 0;
1014
1015                                RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1016                                if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1017                                {
1018                                        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1019                                        RTMPusecDelay(1);
1020                                        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1021
1022                                        DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1023                                }
1024                        }
1025                }
1026
1027                RT28XX_MLME_HANDLER(pAd);
1028        }
1029
1030        pAd->bUpdateBcnCntDone = FALSE;
1031}
1032
1033VOID STAMlmePeriodicExec(
1034        PRTMP_ADAPTER pAd)
1035{
1036#ifdef RT2860
1037        ULONG                       TxTotalCnt;
1038#endif
1039#ifdef RT2870
1040        ULONG   TxTotalCnt;
1041        int     i;
1042#endif
1043
1044    if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1045    {
1046        // WPA MIC error should block association attempt for 60 seconds
1047        if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1048                pAd->StaCfg.bBlockAssoc = FALSE;
1049    }
1050
1051#ifdef RT2860
1052        //Baron 2008/07/10
1053        //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1054        //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1055        //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1056        if(pAd->StaCfg.WepStatus<2)
1057        {
1058                pAd->StaCfg.WpaSupplicantUP = 0;
1059        }
1060        else
1061        {
1062                pAd->StaCfg.WpaSupplicantUP = 1;
1063        }
1064#endif
1065
1066    if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1067        {
1068                if (pAd->IndicateMediaState == NdisMediaStateConnected)
1069                {
1070                        RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1071                }
1072                pAd->PreMediaState = pAd->IndicateMediaState;
1073        }
1074
1075#ifdef RT2860
1076        if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1077        (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1078                (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1079                (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1080                (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1081                (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1082        {
1083                RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1084        }
1085#endif
1086
1087
1088
1089        AsicStaBbpTuning(pAd);
1090
1091        TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1092                                         pAd->RalinkCounters.OneSecTxRetryOkCount +
1093                                         pAd->RalinkCounters.OneSecTxFailCount;
1094
1095        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1096        {
1097                // update channel quality for Roaming and UI LinkQuality display
1098                MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1099        }
1100
1101        // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1102        // Radio is currently in noisy environment
1103        if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1104                AsicAdjustTxPower(pAd);
1105
1106        if (INFRA_ON(pAd))
1107        {
1108                // Is PSM bit consistent with user power management policy?
1109                // This is the only place that will set PSM bit ON.
1110                if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1111                MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1112
1113                pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1114
1115                if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1116                        (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1117                        ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1118                {
1119                        RTMPSetAGCInitValue(pAd, BW_20);
1120                        DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1121                }
1122
1123        {
1124                if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1125                {
1126                    // When APSD is enabled, the period changes as 20 sec
1127                        if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1128                                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1129                }
1130                else
1131                {
1132                    // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1133                        if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1134                {
1135                    if (pAd->CommonCfg.bWmmCapable)
1136                                        RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1137                    else
1138                                                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1139                }
1140                }
1141        }
1142
1143                if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1144                        {
1145                        DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1146                        pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1147                        pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1148
1149                        // Lost AP, send disconnect & link down event
1150                        LinkDown(pAd, FALSE);
1151
1152            {
1153                union iwreq_data    wrqu;
1154                memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1155                wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1156            }
1157
1158                        MlmeAutoReconnectLastSSID(pAd);
1159                }
1160                else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1161                {
1162                        pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1163                        DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1164                        MlmeAutoReconnectLastSSID(pAd);
1165                }
1166
1167                // Add auto seamless roaming
1168                if (pAd->StaCfg.bFastRoaming)
1169                {
1170                        SHORT   dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1171
1172                        DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
1173
1174                        if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1175                        {
1176                                MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1177                        }
1178                }
1179        }
1180        else if (ADHOC_ON(pAd))
1181        {
1182#ifdef RT2860
1183                // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1184                // the "TX BEACON competition" for the entire past 1 sec.
1185                // So that even when ASIC's BEACONgen engine been blocked
1186                // by peer's BEACON due to slower system clock, this STA still can send out
1187                // minimum BEACON to tell the peer I'm alive.
1188                // drawback is that this BEACON won't be well aligned at TBTT boundary.
1189                // EnqueueBeaconFrame(pAd);                       // software send BEACON
1190
1191                // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1192                // restore outgoing BEACON to support B/G-mixed mode
1193                if ((pAd->CommonCfg.Channel <= 14)                         &&
1194                        (pAd->CommonCfg.MaxTxRate <= RATE_11)      &&
1195                        (pAd->CommonCfg.MaxDesiredRate > RATE_11)  &&
1196                        ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1197                {
1198                        DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1199                        NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1200                        pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1201                        MlmeUpdateTxRates(pAd, FALSE, 0);
1202                        MakeIbssBeacon(pAd);            // re-build BEACON frame
1203                        AsicEnableIbssSync(pAd);        // copy to on-chip memory
1204                        pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1205                }
1206
1207                if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1208                {
1209                        if ((pAd->StaCfg.AdhocBGJoined) &&
1210                                ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1211                        {
1212                                DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1213                                pAd->StaCfg.AdhocBGJoined = FALSE;
1214                        }
1215
1216                        if ((pAd->StaCfg.Adhoc20NJoined) &&
1217                                ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1218                        {
1219                                DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1220                                pAd->StaCfg.Adhoc20NJoined = FALSE;
1221                        }
1222                }
1223#endif /* RT2860 */
1224
1225                //radar detect
1226                if ((pAd->CommonCfg.Channel > 14)
1227                        && (pAd->CommonCfg.bIEEE80211H == 1)
1228                        && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1229                {
1230                        RadarDetectPeriodic(pAd);
1231                }
1232
1233                // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1234                // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1235                // join later.
1236                if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1237                        OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1238                {
1239                        MLME_START_REQ_STRUCT     StartReq;
1240
1241                        DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1242                        LinkDown(pAd, FALSE);
1243
1244                        StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1245                        MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1246                        pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1247                }
1248
1249#ifdef RT2870
1250                for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1251                {
1252                        MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1253
1254                        if (pEntry->ValidAsCLI == FALSE)
1255                                continue;
1256
1257                        if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1258                                MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1259                }
1260#endif
1261        }
1262        else // no INFRA nor ADHOC connection
1263        {
1264
1265                if (pAd->StaCfg.bScanReqIsFromWebUI &&
1266            ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1267                        goto SKIP_AUTO_SCAN_CONN;
1268        else
1269            pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1270
1271                if ((pAd->StaCfg.bAutoReconnect == TRUE)
1272                        && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1273                        && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1274                {
1275                        if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1276                        {
1277                                MLME_SCAN_REQ_STRUCT       ScanReq;
1278
1279                                if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1280                                {
1281                                        DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1282                                        ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1283                                        MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1284                                        pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1285                                        // Reset Missed scan number
1286                                        pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1287                                }
1288                                else if (pAd->StaCfg.BssType == BSS_ADHOC)      // Quit the forever scan when in a very clean room
1289                                        MlmeAutoReconnectLastSSID(pAd);
1290                        }
1291                        else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1292                        {
1293                                if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1294                                {
1295                                        MlmeAutoScan(pAd);
1296                                        pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1297                                }
1298                                else
1299                                {
1300                                                MlmeAutoReconnectLastSSID(pAd);
1301                                }
1302                        }
1303                }
1304        }
1305
1306SKIP_AUTO_SCAN_CONN:
1307
1308    if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1309        {
1310                pAd->MacTab.fAnyBASession = TRUE;
1311                AsicUpdateProtect(pAd, HT_FORCERTSCTS,  ALLN_SETPROTECT, FALSE, FALSE);
1312        }
1313        else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1314        {
1315                pAd->MacTab.fAnyBASession = FALSE;
1316                AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode,  ALLN_SETPROTECT, FALSE, FALSE);
1317        }
1318
1319        return;
1320}
1321
1322// Link down report
1323VOID LinkDownExec(
1324        IN PVOID SystemSpecific1,
1325        IN PVOID FunctionContext,
1326        IN PVOID SystemSpecific2,
1327        IN PVOID SystemSpecific3)
1328{
1329
1330        RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1331
1332        pAd->IndicateMediaState = NdisMediaStateDisconnected;
1333        RTMP_IndicateMediaState(pAd);
1334    pAd->ExtraInfo = GENERAL_LINK_DOWN;
1335}
1336
1337// IRQL = DISPATCH_LEVEL
1338VOID MlmeAutoScan(
1339        IN PRTMP_ADAPTER pAd)
1340{
1341        // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1342        if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1343        {
1344                DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1345                MlmeEnqueue(pAd,
1346                                        MLME_CNTL_STATE_MACHINE,
1347                                        OID_802_11_BSSID_LIST_SCAN,
1348                                        0,
1349                                        NULL);
1350                RT28XX_MLME_HANDLER(pAd);
1351        }
1352}
1353
1354// IRQL = DISPATCH_LEVEL
1355VOID MlmeAutoReconnectLastSSID(
1356        IN PRTMP_ADAPTER pAd)
1357{
1358
1359
1360        // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1361        if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1362                (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1363        {
1364                NDIS_802_11_SSID OidSsid;
1365                OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1366                NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1367
1368                DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1369                MlmeEnqueue(pAd,
1370                                        MLME_CNTL_STATE_MACHINE,
1371                                        OID_802_11_SSID,
1372                                        sizeof(NDIS_802_11_SSID),
1373                                        &OidSsid);
1374                RT28XX_MLME_HANDLER(pAd);
1375        }
1376}
1377
1378/*
1379        ==========================================================================
1380        Validate SSID for connection try and rescan purpose
1381        Valid SSID will have visible chars only.
1382        The valid length is from 0 to 32.
1383        IRQL = DISPATCH_LEVEL
1384        ==========================================================================
1385 */
1386BOOLEAN MlmeValidateSSID(
1387        IN PUCHAR       pSsid,
1388        IN UCHAR        SsidLen)
1389{
1390        int     index;
1391
1392        if (SsidLen > MAX_LEN_OF_SSID)
1393                return (FALSE);
1394
1395        // Check each character value
1396        for (index = 0; index < SsidLen; index++)
1397        {
1398                if (pSsid[index] < 0x20)
1399                        return (FALSE);
1400        }
1401
1402        // All checked
1403        return (TRUE);
1404}
1405
1406VOID MlmeSelectTxRateTable(
1407        IN PRTMP_ADAPTER                pAd,
1408        IN PMAC_TABLE_ENTRY             pEntry,
1409        IN PUCHAR                               *ppTable,
1410        IN PUCHAR                               pTableSize,
1411        IN PUCHAR                               pInitTxRateIdx)
1412{
1413        do
1414        {
1415                // decide the rate table for tuning
1416                if (pAd->CommonCfg.TxRateTableSize > 0)
1417                {
1418                        *ppTable = RateSwitchTable;
1419                        *pTableSize = RateSwitchTable[0];
1420                        *pInitTxRateIdx = RateSwitchTable[1];
1421
1422                        break;
1423                }
1424
1425                if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1426                {
1427                        if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1428#ifdef RT2860
1429                                !pAd->StaCfg.AdhocBOnlyJoined &&
1430                                !pAd->StaCfg.AdhocBGJoined &&
1431                                (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1432                                ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1433#endif
1434#ifdef RT2870
1435                                (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1436                                ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1437#endif
1438                        {// 11N 1S Adhoc
1439                                *ppTable = RateSwitchTable11N1S;
1440                                *pTableSize = RateSwitchTable11N1S[0];
1441                                *pInitTxRateIdx = RateSwitchTable11N1S[1];
1442
1443                        }
1444                        else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1445#ifdef RT2860
1446                                        !pAd->StaCfg.AdhocBOnlyJoined &&
1447                                        !pAd->StaCfg.AdhocBGJoined &&
1448                                        (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1449                                        (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1450#endif
1451#ifdef RT2870
1452                                        (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1453                                        (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1454#endif
1455                                        (pAd->Antenna.field.TxPath == 2))
1456                        {// 11N 2S Adhoc
1457                                if (pAd->LatchRfRegs.Channel <= 14)
1458                                {
1459                                        *ppTable = RateSwitchTable11N2S;
1460                                        *pTableSize = RateSwitchTable11N2S[0];
1461                                        *pInitTxRateIdx = RateSwitchTable11N2S[1];
1462                                }
1463                                else
1464                                {
1465                                        *ppTable = RateSwitchTable11N2SForABand;
1466                                        *pTableSize = RateSwitchTable11N2SForABand[0];
1467                                        *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1468                                }
1469
1470                        }
1471                        else
1472#ifdef RT2860
1473                                if (pAd->CommonCfg.PhyMode == PHY_11B)
1474                        {
1475                                *ppTable = RateSwitchTable11B;
1476                                *pTableSize = RateSwitchTable11B[0];
1477                                *pInitTxRateIdx = RateSwitchTable11B[1];
1478
1479                        }
1480                else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1481#endif
1482#ifdef RT2870
1483                                if ((pEntry->RateLen == 4)
1484                                        && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1485                                        )
1486#endif
1487                        {
1488                                // USe B Table when Only b-only Station in my IBSS .
1489                                *ppTable = RateSwitchTable11B;
1490                                *pTableSize = RateSwitchTable11B[0];
1491                                *pInitTxRateIdx = RateSwitchTable11B[1];
1492
1493                        }
1494                        else if (pAd->LatchRfRegs.Channel <= 14)
1495                        {
1496                                *ppTable = RateSwitchTable11BG;
1497                                *pTableSize = RateSwitchTable11BG[0];
1498                                *pInitTxRateIdx = RateSwitchTable11BG[1];
1499
1500                        }
1501                        else
1502                        {
1503                                *ppTable = RateSwitchTable11G;
1504                                *pTableSize = RateSwitchTable11G[0];
1505                                *pInitTxRateIdx = RateSwitchTable11G[1];
1506
1507                        }
1508                        break;
1509                }
1510
1511                if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1512                        ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1513                {// 11BGN 1S AP
1514                        *ppTable = RateSwitchTable11BGN1S;
1515                        *pTableSize = RateSwitchTable11BGN1S[0];
1516                        *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1517
1518                        break;
1519                }
1520
1521                if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1522                        (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1523                {// 11BGN 2S AP
1524                        if (pAd->LatchRfRegs.Channel <= 14)
1525                        {
1526                                *ppTable = RateSwitchTable11BGN2S;
1527                                *pTableSize = RateSwitchTable11BGN2S[0];
1528                                *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1529
1530                        }
1531                        else
1532                        {
1533                                *ppTable = RateSwitchTable11BGN2SForABand;
1534                                *pTableSize = RateSwitchTable11BGN2SForABand[0];
1535                                *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1536
1537                        }
1538                        break;
1539                }
1540
1541                if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1542                {// 11N 1S AP
1543                        *ppTable = RateSwitchTable11N1S;
1544                        *pTableSize = RateSwitchTable11N1S[0];
1545                        *pInitTxRateIdx = RateSwitchTable11N1S[1];
1546
1547                        break;
1548                }
1549
1550                if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1551                {// 11N 2S AP
1552                        if (pAd->LatchRfRegs.Channel <= 14)
1553                        {
1554                        *ppTable = RateSwitchTable11N2S;
1555                        *pTableSize = RateSwitchTable11N2S[0];
1556                        *pInitTxRateIdx = RateSwitchTable11N2S[1];
1557            }
1558                        else
1559                        {
1560                                *ppTable = RateSwitchTable11N2SForABand;
1561                                *pTableSize = RateSwitchTable11N2SForABand[0];
1562                                *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1563                        }
1564
1565                        break;
1566                }
1567
1568                //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1569                if (pEntry->RateLen == 4)
1570                {// B only AP
1571                        *ppTable = RateSwitchTable11B;
1572                        *pTableSize = RateSwitchTable11B[0];
1573                        *pInitTxRateIdx = RateSwitchTable11B[1];
1574
1575                        break;
1576                }
1577
1578                //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1579                if ((pEntry->RateLen > 8)
1580                        && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1581                        )
1582                {// B/G  mixed AP
1583                        *ppTable = RateSwitchTable11BG;
1584                        *pTableSize = RateSwitchTable11BG[0];
1585                        *pInitTxRateIdx = RateSwitchTable11BG[1];
1586
1587                        break;
1588                }
1589
1590                //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1591                if ((pEntry->RateLen == 8)
1592                        && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1593                        )
1594                {// G only AP
1595                        *ppTable = RateSwitchTable11G;
1596                        *pTableSize = RateSwitchTable11G[0];
1597                        *pInitTxRateIdx = RateSwitchTable11G[1];
1598
1599                        break;
1600                }
1601
1602                {
1603                        //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1604                        if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1605                        {       // Legacy mode
1606                                if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1607                                {
1608                                        *ppTable = RateSwitchTable11B;
1609                                        *pTableSize = RateSwitchTable11B[0];
1610                                        *pInitTxRateIdx = RateSwitchTable11B[1];
1611                                }
1612                                else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1613                                {
1614                                        *ppTable = RateSwitchTable11G;
1615                                        *pTableSize = RateSwitchTable11G[0];
1616                                        *pInitTxRateIdx = RateSwitchTable11G[1];
1617
1618                                }
1619                                else
1620                                {
1621                                        *ppTable = RateSwitchTable11BG;
1622                                        *pTableSize = RateSwitchTable11BG[0];
1623                                        *pInitTxRateIdx = RateSwitchTable11BG[1];
1624                                }
1625                                break;
1626                        }
1627
1628                        if (pAd->LatchRfRegs.Channel <= 14)
1629                        {
1630                                if (pAd->CommonCfg.TxStream == 1)
1631                                {
1632                                        *ppTable = RateSwitchTable11N1S;
1633                                        *pTableSize = RateSwitchTable11N1S[0];
1634                                        *pInitTxRateIdx = RateSwitchTable11N1S[1];
1635                                        DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1636                                }
1637                                else
1638                                {
1639                                        *ppTable = RateSwitchTable11N2S;
1640                                        *pTableSize = RateSwitchTable11N2S[0];
1641                                        *pInitTxRateIdx = RateSwitchTable11N2S[1];
1642                                        DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1643                                }
1644                        }
1645                        else
1646                        {
1647                                if (pAd->CommonCfg.TxStream == 1)
1648                                {
1649                                        *ppTable = RateSwitchTable11N1S;
1650                                        *pTableSize = RateSwitchTable11N1S[0];
1651                                        *pInitTxRateIdx = RateSwitchTable11N1S[1];
1652                                        DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1653                                }
1654                                else
1655                                {
1656                                        *ppTable = RateSwitchTable11N2SForABand;
1657                                        *pTableSize = RateSwitchTable11N2SForABand[0];
1658                                        *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1659                                        DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1660                                }
1661                        }
1662
1663                        DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1664                                pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1665                }
1666        } while(FALSE);
1667}
1668
1669/*
1670        ==========================================================================
1671        Description:
1672                This routine checks if there're other APs out there capable for
1673                roaming. Caller should call this routine only when Link up in INFRA mode
1674                and channel quality is below CQI_GOOD_THRESHOLD.
1675
1676        IRQL = DISPATCH_LEVEL
1677
1678        Output:
1679        ==========================================================================
1680 */
1681VOID MlmeCheckForRoaming(
1682        IN PRTMP_ADAPTER pAd,
1683        IN ULONG        Now32)
1684{
1685        USHORT     i;
1686        BSS_TABLE  *pRoamTab = &pAd->MlmeAux.RoamTab;
1687        BSS_ENTRY  *pBss;
1688
1689        DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1690        // put all roaming candidates into RoamTab, and sort in RSSI order
1691        BssTableInit(pRoamTab);
1692        for (i = 0; i < pAd->ScanTab.BssNr; i++)
1693        {
1694                pBss = &pAd->ScanTab.BssEntry[i];
1695
1696                if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1697                        continue;        // AP disappear
1698                if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1699                        continue;        // RSSI too weak. forget it.
1700                if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1701                        continue;        // skip current AP
1702                if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1703                        continue;        // only AP with stronger RSSI is eligible for roaming
1704
1705                // AP passing all above rules is put into roaming candidate table
1706                NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1707                pRoamTab->BssNr += 1;
1708        }
1709
1710        if (pRoamTab->BssNr > 0)
1711        {
1712                // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1713                if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1714                {
1715                        pAd->RalinkCounters.PoorCQIRoamingCount ++;
1716                        DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1717                        MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1718                        RT28XX_MLME_HANDLER(pAd);
1719                }
1720        }
1721        DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1722}
1723
1724/*
1725        ==========================================================================
1726        Description:
1727                This routine checks if there're other APs out there capable for
1728                roaming. Caller should call this routine only when link up in INFRA mode
1729                and channel quality is below CQI_GOOD_THRESHOLD.
1730
1731        IRQL = DISPATCH_LEVEL
1732
1733        Output:
1734        ==========================================================================
1735 */
1736VOID MlmeCheckForFastRoaming(
1737        IN      PRTMP_ADAPTER   pAd,
1738        IN      ULONG                   Now)
1739{
1740        USHORT          i;
1741        BSS_TABLE       *pRoamTab = &pAd->MlmeAux.RoamTab;
1742        BSS_ENTRY       *pBss;
1743
1744        DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1745        // put all roaming candidates into RoamTab, and sort in RSSI order
1746        BssTableInit(pRoamTab);
1747        for (i = 0; i < pAd->ScanTab.BssNr; i++)
1748        {
1749                pBss = &pAd->ScanTab.BssEntry[i];
1750
1751        if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1752                        continue;        // RSSI too weak. forget it.
1753                if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1754                        continue;        // skip current AP
1755                if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1756                        continue;        // skip different SSID
1757        if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1758                        continue;        // skip AP without better RSSI
1759
1760        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));
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                        RT28XX_MLME_HANDLER(pAd);
1775                }
1776        }
1777        // Maybe site survey required
1778        else
1779        {
1780                if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1781                {
1782                        // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1783                        DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1784                        pAd->StaCfg.ScanCnt = 2;
1785                        pAd->StaCfg.LastScanTime = Now;
1786                        MlmeAutoScan(pAd);
1787                }
1788        }
1789
1790    DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1791}
1792
1793/*
1794        ==========================================================================
1795        Description:
1796                This routine calculates TxPER, RxPER of the past N-sec period. And
1797                according to the calculation result, ChannelQuality is calculated here
1798                to decide if current AP is still doing the job.
1799
1800                If ChannelQuality is not good, a ROAMing attempt may be tried later.
1801        Output:
1802                StaCfg.ChannelQuality - 0..100
1803
1804        IRQL = DISPATCH_LEVEL
1805
1806        NOTE: This routine decide channle quality based on RX CRC error ratio.
1807                Caller should make sure a function call to NICUpdateRawCounters(pAd)
1808                is performed right before this routine, so that this routine can decide
1809                channel quality based on the most up-to-date information
1810        ==========================================================================
1811 */
1812VOID MlmeCalculateChannelQuality(
1813        IN PRTMP_ADAPTER pAd,
1814        IN ULONG Now32)
1815{
1816        ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1817        ULONG RxCnt, RxPER;
1818        UCHAR NorRssi;
1819        CHAR  MaxRssi;
1820        ULONG BeaconLostTime = BEACON_LOST_TIME;
1821
1822        MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1823
1824        //
1825        // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1826        //
1827        TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1828        TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1829        if (TxCnt < 5)
1830        {
1831                TxPER = 0;
1832                TxPRR = 0;
1833        }
1834        else
1835        {
1836                TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1837                TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1838        }
1839
1840        //
1841        // calculate RX PER - don't take RxPER into consideration if too few sample
1842        //
1843        RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1844        if (RxCnt < 5)
1845                RxPER = 0;
1846        else
1847                RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1848
1849        //
1850        // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1851        //
1852        if (INFRA_ON(pAd) &&
1853                (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1854                (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1855        {
1856                DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1857                pAd->Mlme.ChannelQuality = 0;
1858        }
1859        else
1860        {
1861                // Normalize Rssi
1862                if (MaxRssi > -40)
1863                        NorRssi = 100;
1864                else if (MaxRssi < -90)
1865                        NorRssi = 0;
1866                else
1867                        NorRssi = (MaxRssi + 90) * 2;
1868
1869                // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER        (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1870                pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1871                                                                   TX_WEIGHTING * (100 - TxPRR) +
1872                                                                   RX_WEIGHTING* (100 - RxPER)) / 100;
1873                if (pAd->Mlme.ChannelQuality >= 100)
1874                        pAd->Mlme.ChannelQuality = 100;
1875        }
1876
1877}
1878
1879VOID MlmeSetTxRate(
1880        IN PRTMP_ADAPTER                pAd,
1881        IN PMAC_TABLE_ENTRY             pEntry,
1882        IN PRTMP_TX_RATE_SWITCH pTxRate)
1883{
1884        UCHAR   MaxMode = MODE_OFDM;
1885
1886        MaxMode = MODE_HTGREENFIELD;
1887
1888        if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1889                pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1890        else
1891                pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1892
1893        if (pTxRate->CurrMCS < MCS_AUTO)
1894                pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1895
1896        if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1897                pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1898
1899        if (ADHOC_ON(pAd))
1900        {
1901                // If peer adhoc is b-only mode, we can't send 11g rate.
1902                pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1903                pEntry->HTPhyMode.field.STBC    = STBC_NONE;
1904
1905                //
1906                // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1907                //
1908                pEntry->HTPhyMode.field.MODE    = pTxRate->Mode;
1909                pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1910                pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1911
1912                // Patch speed error in status page
1913                pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1914        }
1915        else
1916        {
1917                if (pTxRate->Mode <= MaxMode)
1918                        pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1919
1920                if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1921                        pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1922                else
1923                        pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1924
1925                // Reexam each bandwidth's SGI support.
1926                if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1927                {
1928                        if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1929                                pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1930                        if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1931                                pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1932                }
1933
1934                // Turn RTS/CTS rate to 6Mbps.
1935                if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1936                {
1937                        pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1938                        if (pAd->MacTab.fAnyBASession)
1939                        {
1940                                AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1941                        }
1942                        else
1943                        {
1944                                AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1945                        }
1946                }
1947                else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1948                {
1949                        pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1950                        if (pAd->MacTab.fAnyBASession)
1951                        {
1952                                AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1953                        }
1954                        else
1955                        {
1956                                AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1957                        }
1958                }
1959                else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1960                {
1961                        AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1962
1963                }
1964                else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1965                {
1966                        AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1967                }
1968
1969                pEntry->HTPhyMode.field.STBC    = pAd->StaCfg.HTPhyMode.field.STBC;
1970                pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1971                pEntry->HTPhyMode.field.MCS             = pAd->StaCfg.HTPhyMode.field.MCS;
1972                pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
1973
1974                if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1975                    pAd->WIFItestbed.bGreenField)
1976                    pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1977        }
1978
1979        pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1980}
1981
1982/*
1983        ==========================================================================
1984        Description:
1985                This routine calculates the acumulated TxPER of eaxh TxRate. And
1986                according to the calculation result, change CommonCfg.TxRate which
1987                is the stable TX Rate we expect the Radio situation could sustained.
1988
1989                CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1990        Output:
1991                CommonCfg.TxRate -
1992
1993        IRQL = DISPATCH_LEVEL
1994
1995        NOTE:
1996                call this routine every second
1997        ==========================================================================
1998 */
1999VOID MlmeDynamicTxRateSwitching(
2000        IN PRTMP_ADAPTER pAd)
2001{
2002        UCHAR                                   UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2003        ULONG                                   i, AccuTxTotalCnt = 0, TxTotalCnt;
2004        ULONG                                   TxErrorRatio = 0;
2005        BOOLEAN                                 bTxRateChanged, bUpgradeQuality = FALSE;
2006        PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate = NULL;
2007        PUCHAR                                  pTable;
2008        UCHAR                                   TableSize = 0;
2009        UCHAR                                   InitTxRateIdx = 0, TrainUp, TrainDown;
2010        CHAR                                    Rssi, RssiOffset = 0;
2011        TX_STA_CNT1_STRUC               StaTx1;
2012        TX_STA_CNT0_STRUC               TxStaCnt0;
2013        ULONG                                   TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2014        MAC_TABLE_ENTRY                 *pEntry;
2015
2016        //
2017        // walk through MAC table, see if need to change AP's TX rate toward each entry
2018        //
2019        for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2020        {
2021                pEntry = &pAd->MacTab.Content[i];
2022
2023                // check if this entry need to switch rate automatically
2024                if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2025                        continue;
2026
2027                if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2028                {
2029#ifdef RT2860
2030                        Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2031#endif
2032#ifdef RT2870
2033                        Rssi = RTMPMaxRssi(pAd,
2034                                                           pAd->StaCfg.RssiSample.AvgRssi0,
2035                                                           pAd->StaCfg.RssiSample.AvgRssi1,
2036                                                           pAd->StaCfg.RssiSample.AvgRssi2);
2037#endif
2038
2039                        // Update statistic counter
2040                        RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2041                        RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2042                        pAd->bUpdateBcnCntDone = TRUE;
2043                        TxRetransmit = StaTx1.field.TxRetransmit;
2044                        TxSuccess = StaTx1.field.TxSuccess;
2045                        TxFailCount = TxStaCnt0.field.TxFailCount;
2046                        TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2047
2048                        pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2049                        pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2050                        pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2051                        pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2052                        pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2053                        pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2054
2055                        // if no traffic in the past 1-sec period, don't change TX rate,
2056                        // but clear all bad history. because the bad history may affect the next
2057                        // Chariot throughput test
2058                        AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2059                                                 pAd->RalinkCounters.OneSecTxRetryOkCount +
2060                                                 pAd->RalinkCounters.OneSecTxFailCount;
2061
2062                        if (TxTotalCnt)
2063                                TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2064                }
2065                else
2066                {
2067#ifdef RT2860
2068                        Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2069#endif
2070#ifdef RT2870
2071                        if (INFRA_ON(pAd) && (i == 1))
2072                                Rssi = RTMPMaxRssi(pAd,
2073                                                                   pAd->StaCfg.RssiSample.AvgRssi0,
2074                                                                   pAd->StaCfg.RssiSample.AvgRssi1,
2075                                                                   pAd->StaCfg.RssiSample.AvgRssi2);
2076                        else
2077                                Rssi = RTMPMaxRssi(pAd,
2078                                                                   pEntry->RssiSample.AvgRssi0,
2079                                                                   pEntry->RssiSample.AvgRssi1,
2080                                                                   pEntry->RssiSample.AvgRssi2);
2081#endif
2082
2083                        TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2084                                 pEntry->OneSecTxRetryOkCount +
2085                                 pEntry->OneSecTxFailCount;
2086
2087                        if (TxTotalCnt)
2088                                TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2089                }
2090
2091                CurrRateIdx = pEntry->CurrTxRateIndex;
2092
2093                MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2094
2095                if (CurrRateIdx >= TableSize)
2096                {
2097                        CurrRateIdx = TableSize - 1;
2098                }
2099
2100                // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2101                // So need to sync here.
2102                pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2103                if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2104                        //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2105                        )
2106                {
2107
2108                        // Need to sync Real Tx rate and our record.
2109                        // Then return for next DRS.
2110                        pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2111                        pEntry->CurrTxRateIndex = InitTxRateIdx;
2112                        MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2113
2114                        // reset all OneSecTx counters
2115                        RESET_ONE_SEC_TX_CNT(pEntry);
2116                        continue;
2117                }
2118
2119                // decide the next upgrade rate and downgrade rate, if any
2120                if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2121                {
2122                        UpRateIdx = CurrRateIdx + 1;
2123                        DownRateIdx = CurrRateIdx -1;
2124                }
2125                else if (CurrRateIdx == 0)
2126                {
2127                        UpRateIdx = CurrRateIdx + 1;
2128                        DownRateIdx = CurrRateIdx;
2129                }
2130                else if (CurrRateIdx == (TableSize - 1))
2131                {
2132                        UpRateIdx = CurrRateIdx;
2133                        DownRateIdx = CurrRateIdx - 1;
2134                }
2135
2136                pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2137
2138                if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2139                {
2140                        TrainUp         = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2141                        TrainDown       = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2142                }
2143                else
2144                {
2145                        TrainUp         = pCurrTxRate->TrainUp;
2146                        TrainDown       = pCurrTxRate->TrainDown;
2147                }
2148
2149                //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2150
2151                //
2152                // Keep the last time TxRateChangeAction status.
2153                //
2154                pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2155
2156
2157
2158                //
2159                // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2160                //         (criteria copied from RT2500 for Netopia case)
2161                //
2162                if (TxTotalCnt <= 15)
2163                {
2164                        CHAR    idx = 0;
2165                        UCHAR   TxRateIdx;
2166                        //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2167                        UCHAR   MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0,  MCS5 =0, MCS6 = 0, MCS7 = 0;
2168                UCHAR   MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2169                        UCHAR   MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2170
2171                        // check the existence and index of each needed MCS
2172                        while (idx < pTable[0])
2173                        {
2174                                pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2175
2176                                if (pCurrTxRate->CurrMCS == MCS_0)
2177                                {
2178                                        MCS0 = idx;
2179                                }
2180                                else if (pCurrTxRate->CurrMCS == MCS_1)
2181                                {
2182                                        MCS1 = idx;
2183                                }
2184                                else if (pCurrTxRate->CurrMCS == MCS_2)
2185                                {
2186                                        MCS2 = idx;
2187                                }
2188                                else if (pCurrTxRate->CurrMCS == MCS_3)
2189                                {
2190                                        MCS3 = idx;
2191                                }
2192                                else if (pCurrTxRate->CurrMCS == MCS_4)
2193                                {
2194                                        MCS4 = idx;
2195                                }
2196                    else if (pCurrTxRate->CurrMCS == MCS_5)
2197                    {
2198                        MCS5 = idx;
2199                    }
2200                    else if (pCurrTxRate->CurrMCS == MCS_6)
2201                    {
2202                        MCS6 = idx;
2203                    }
2204                                //else if (pCurrTxRate->CurrMCS == MCS_7)
2205                                else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800))   // prevent the highest MCS using short GI when 1T and low throughput
2206                                {
2207                                        MCS7 = idx;
2208                                }
2209                                else if (pCurrTxRate->CurrMCS == MCS_12)
2210                                {
2211                                        MCS12 = idx;
2212                                }
2213                                else if (pCurrTxRate->CurrMCS == MCS_13)
2214                                {
2215                                        MCS13 = idx;
2216                                }
2217                                else if (pCurrTxRate->CurrMCS == MCS_14)
2218                                {
2219                                        MCS14 = idx;
2220                                }
2221                                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
2222                                {
2223                                        MCS15 = idx;
2224                                }
2225                                else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2226                                {
2227                                        MCS20 = idx;
2228                                }
2229                                else if (pCurrTxRate->CurrMCS == MCS_21)
2230                                {
2231                                        MCS21 = idx;
2232                                }
2233                                else if (pCurrTxRate->CurrMCS == MCS_22)
2234                                {
2235                                        MCS22 = idx;
2236                                }
2237                                else if (pCurrTxRate->CurrMCS == MCS_23)
2238                                {
2239                                        MCS23 = idx;
2240                                }
2241                                idx ++;
2242                        }
2243
2244                        if (pAd->LatchRfRegs.Channel <= 14)
2245                        {
2246                                if (pAd->NicConfig2.field.ExternalLNAForG)
2247                                {
2248                                        RssiOffset = 2;
2249                                }
2250                                else
2251                                {
2252                                        RssiOffset = 5;
2253                                }
2254                        }
2255                        else
2256                        {
2257                                if (pAd->NicConfig2.field.ExternalLNAForA)
2258                                {
2259                                        RssiOffset = 5;
2260                                }
2261                                else
2262                                {
2263                                        RssiOffset = 8;
2264                                }
2265                        }
2266
2267                        /*if (MCS15)*/
2268                        if ((pTable == RateSwitchTable11BGN3S) ||
2269                                (pTable == RateSwitchTable11N3S) ||
2270                                (pTable == RateSwitchTable))
2271                        {// N mode with 3 stream // 3*3
2272                                if (MCS23 && (Rssi >= -70))
2273                                        TxRateIdx = MCS15;
2274                                else if (MCS22 && (Rssi >= -72))
2275                                        TxRateIdx = MCS14;
2276                    else if (MCS21 && (Rssi >= -76))
2277                                        TxRateIdx = MCS13;
2278                                else if (MCS20 && (Rssi >= -78))
2279                                        TxRateIdx = MCS12;
2280                        else if (MCS4 && (Rssi >= -82))
2281                                TxRateIdx = MCS4;
2282                        else if (MCS3 && (Rssi >= -84))
2283                                TxRateIdx = MCS3;
2284                        else if (MCS2 && (Rssi >= -86))
2285                                TxRateIdx = MCS2;
2286                        else if (MCS1 && (Rssi >= -88))
2287                                TxRateIdx = MCS1;
2288                        else
2289                                TxRateIdx = MCS0;
2290                }
2291                else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2292                        {// N mode with 2 stream
2293                                if (MCS15 && (Rssi >= (-70+RssiOffset)))
2294                                        TxRateIdx = MCS15;
2295                                else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2296                                        TxRateIdx = MCS14;
2297                                else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2298                                        TxRateIdx = MCS13;
2299                                else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2300                                        TxRateIdx = MCS12;
2301                                else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2302                                        TxRateIdx = MCS4;
2303                                else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2304                                        TxRateIdx = MCS3;
2305                                else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2306                                        TxRateIdx = MCS2;
2307                                else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2308                                        TxRateIdx = MCS1;
2309                                else
2310                                        TxRateIdx = MCS0;
2311                        }
2312                        else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2313                        {// N mode with 1 stream
2314                                if (MCS7 && (Rssi > (-72+RssiOffset)))
2315                                        TxRateIdx = MCS7;
2316                                else if (MCS6 && (Rssi > (-74+RssiOffset)))
2317                                        TxRateIdx = MCS6;
2318                                else if (MCS5 && (Rssi > (-77+RssiOffset)))
2319                                        TxRateIdx = MCS5;
2320                                else if (MCS4 && (Rssi > (-79+RssiOffset)))
2321                                        TxRateIdx = MCS4;
2322                                else if (MCS3 && (Rssi > (-81+RssiOffset)))
2323                                        TxRateIdx = MCS3;
2324                                else if (MCS2 && (Rssi > (-83+RssiOffset)))
2325                                        TxRateIdx = MCS2;
2326                                else if (MCS1 && (Rssi > (-86+RssiOffset)))
2327                                        TxRateIdx = MCS1;
2328                                else
2329                                        TxRateIdx = MCS0;
2330                        }
2331                        else
2332                        {// Legacy mode
2333                                if (MCS7 && (Rssi > -70))
2334                                        TxRateIdx = MCS7;
2335                                else if (MCS6 && (Rssi > -74))
2336                                        TxRateIdx = MCS6;
2337                                else if (MCS5 && (Rssi > -78))
2338                                        TxRateIdx = MCS5;
2339                                else if (MCS4 && (Rssi > -82))
2340                                        TxRateIdx = MCS4;
2341                                else if (MCS4 == 0)     // for B-only mode
2342                                        TxRateIdx = MCS3;
2343                                else if (MCS3 && (Rssi > -85))
2344                                        TxRateIdx = MCS3;
2345                                else if (MCS2 && (Rssi > -87))
2346                                        TxRateIdx = MCS2;
2347                                else if (MCS1 && (Rssi > -90))
2348                                        TxRateIdx = MCS1;
2349                                else
2350                                        TxRateIdx = MCS0;
2351                        }
2352
2353                        {
2354                                pEntry->CurrTxRateIndex = TxRateIdx;
2355                                pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2356                                MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2357                        }
2358
2359                        NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2360                        NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2361                        pEntry->fLastSecAccordingRSSI = TRUE;
2362                        // reset all OneSecTx counters
2363                        RESET_ONE_SEC_TX_CNT(pEntry);
2364
2365                        continue;
2366                }
2367
2368                if (pEntry->fLastSecAccordingRSSI == TRUE)
2369                {
2370                        pEntry->fLastSecAccordingRSSI = FALSE;
2371                        pEntry->LastSecTxRateChangeAction = 0;
2372                        // reset all OneSecTx counters
2373                        RESET_ONE_SEC_TX_CNT(pEntry);
2374
2375                        continue;
2376                }
2377
2378                do
2379                {
2380                        BOOLEAN bTrainUpDown = FALSE;
2381
2382                        pEntry->CurrTxRateStableTime ++;
2383
2384                        // downgrade TX quality if PER >= Rate-Down threshold
2385                        if (TxErrorRatio >= TrainDown)
2386                        {
2387                                bTrainUpDown = TRUE;
2388                                pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2389                        }
2390                        // upgrade TX quality if PER <= Rate-Up threshold
2391                        else if (TxErrorRatio <= TrainUp)
2392                        {
2393                                bTrainUpDown = TRUE;
2394                                bUpgradeQuality = TRUE;
2395                                if (pEntry->TxQuality[CurrRateIdx])
2396                                        pEntry->TxQuality[CurrRateIdx] --;  // quality very good in CurrRate
2397
2398                                if (pEntry->TxRateUpPenalty)
2399                                        pEntry->TxRateUpPenalty --;
2400                                else if (pEntry->TxQuality[UpRateIdx])
2401                                        pEntry->TxQuality[UpRateIdx] --;    // may improve next UP rate's quality
2402                        }
2403
2404                        pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2405
2406                        if (bTrainUpDown)
2407                        {
2408                                // perform DRS - consider TxRate Down first, then rate up.
2409                                if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2410                                {
2411                                        pEntry->CurrTxRateIndex = DownRateIdx;
2412                                }
2413                                else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2414                                {
2415                                        pEntry->CurrTxRateIndex = UpRateIdx;
2416                                }
2417                        }
2418                } while (FALSE);
2419
2420                // if rate-up happen, clear all bad history of all TX rates
2421                if (pEntry->CurrTxRateIndex > CurrRateIdx)
2422                {
2423                        pEntry->CurrTxRateStableTime = 0;
2424                        pEntry->TxRateUpPenalty = 0;
2425                        pEntry->LastSecTxRateChangeAction = 1; // rate UP
2426                        NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2427                        NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2428
2429                        //
2430                        // For TxRate fast train up
2431                        //
2432                        if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2433                        {
2434                                RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2435
2436                                pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2437                        }
2438                        bTxRateChanged = TRUE;
2439                }
2440                // if rate-down happen, only clear DownRate's bad history
2441                else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2442                {
2443                        pEntry->CurrTxRateStableTime = 0;
2444                        pEntry->TxRateUpPenalty = 0;           // no penalty
2445                        pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2446                        pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2447                        pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2448
2449                        //
2450                        // For TxRate fast train down
2451                        //
2452                        if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2453                        {
2454                                RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2455
2456                                pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2457                        }
2458                        bTxRateChanged = TRUE;
2459                }
2460                else
2461                {
2462                        pEntry->LastSecTxRateChangeAction = 0; // rate no change
2463                        bTxRateChanged = FALSE;
2464                }
2465
2466                pEntry->LastTxOkCount = TxSuccess;
2467
2468                // reset all OneSecTx counters
2469                RESET_ONE_SEC_TX_CNT(pEntry);
2470
2471                pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2472                if (bTxRateChanged && pNextTxRate)
2473                {
2474                        MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2475                }
2476        }
2477}
2478
2479/*
2480        ========================================================================
2481        Routine Description:
2482                Station side, Auto TxRate faster train up timer call back function.
2483
2484        Arguments:
2485                SystemSpecific1                 - Not used.
2486                FunctionContext                 - Pointer to our Adapter context.
2487                SystemSpecific2                 - Not used.
2488                SystemSpecific3                 - Not used.
2489
2490        Return Value:
2491                None
2492
2493        ========================================================================
2494*/
2495VOID StaQuickResponeForRateUpExec(
2496        IN PVOID SystemSpecific1,
2497        IN PVOID FunctionContext,
2498        IN PVOID SystemSpecific2,
2499        IN PVOID SystemSpecific3)
2500{
2501        PRTMP_ADAPTER                   pAd = (PRTMP_ADAPTER)FunctionContext;
2502        UCHAR                                   UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2503        ULONG                                   TxTotalCnt;
2504        ULONG                                   TxErrorRatio = 0;
2505#ifdef RT2860
2506        BOOLEAN                                 bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2507#endif
2508#ifdef RT2870
2509        BOOLEAN                                 bTxRateChanged; //, bUpgradeQuality = FALSE;
2510#endif
2511        PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate = NULL;
2512        PUCHAR                                  pTable;
2513        UCHAR                                   TableSize = 0;
2514        UCHAR                                   InitTxRateIdx = 0, TrainUp, TrainDown;
2515        TX_STA_CNT1_STRUC               StaTx1;
2516        TX_STA_CNT0_STRUC               TxStaCnt0;
2517        CHAR                                    Rssi, ratio;
2518        ULONG                                   TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2519        MAC_TABLE_ENTRY                 *pEntry;
2520        ULONG                                   i;
2521
2522        pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2523
2524    //
2525    // walk through MAC table, see if need to change AP's TX rate toward each entry
2526    //
2527        for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2528        {
2529                pEntry = &pAd->MacTab.Content[i];
2530
2531                // check if this entry need to switch rate automatically
2532                if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2533                        continue;
2534
2535#ifdef RT2860
2536                //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2537            if (pAd->Antenna.field.TxPath > 1)
2538                        Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2539                else
2540                        Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2541#endif
2542#ifdef RT2870
2543                if (INFRA_ON(pAd) && (i == 1))
2544                        Rssi = RTMPMaxRssi(pAd,
2545                                                           pAd->StaCfg.RssiSample.AvgRssi0,
2546                                                           pAd->StaCfg.RssiSample.AvgRssi1,
2547                                                           pAd->StaCfg.RssiSample.AvgRssi2);
2548                else
2549                        Rssi = RTMPMaxRssi(pAd,
2550                                                           pEntry->RssiSample.AvgRssi0,
2551                                                           pEntry->RssiSample.AvgRssi1,
2552                                                           pEntry->RssiSample.AvgRssi2);
2553#endif
2554
2555                CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2556
2557                        MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2558
2559                // decide the next upgrade rate and downgrade rate, if any
2560                if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2561                {
2562                        UpRateIdx = CurrRateIdx + 1;
2563                        DownRateIdx = CurrRateIdx -1;
2564                }
2565                else if (CurrRateIdx == 0)
2566                {
2567                        UpRateIdx = CurrRateIdx + 1;
2568                        DownRateIdx = CurrRateIdx;
2569                }
2570                else if (CurrRateIdx == (TableSize - 1))
2571                {
2572                        UpRateIdx = CurrRateIdx;
2573                        DownRateIdx = CurrRateIdx - 1;
2574                }
2575
2576                pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2577
2578                if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2579                {
2580                        TrainUp         = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2581                        TrainDown       = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2582                }
2583                else
2584                {
2585                        TrainUp         = pCurrTxRate->TrainUp;
2586                        TrainDown       = pCurrTxRate->TrainDown;
2587                }
2588
2589                if (pAd->MacTab.Size == 1)
2590                {
2591                        // Update statistic counter
2592                        RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2593                        RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2594
2595                        TxRetransmit = StaTx1.field.TxRetransmit;
2596                        TxSuccess = StaTx1.field.TxSuccess;
2597                        TxFailCount = TxStaCnt0.field.TxFailCount;
2598                        TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2599
2600                        pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2601                        pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2602                        pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2603                        pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2604                        pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2605                        pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2606
2607                        if (TxTotalCnt)
2608                                TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2609                }
2610                else
2611                {
2612                        TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2613                                 pEntry->OneSecTxRetryOkCount +
2614                                 pEntry->OneSecTxFailCount;
2615
2616                        if (TxTotalCnt)
2617                                TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2618                }
2619
2620
2621                //
2622                // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2623                //         (criteria copied from RT2500 for Netopia case)
2624                //
2625                if (TxTotalCnt <= 12)
2626                {
2627                        NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2628                        NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2629
2630                        if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2631                        {
2632                                pAd->CommonCfg.TxRateIndex = DownRateIdx;
2633                                pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2634                        }
2635                        else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2636                        {
2637                                pAd->CommonCfg.TxRateIndex = UpRateIdx;
2638                        }
2639
2640                        DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2641                        return;
2642                }
2643
2644                do
2645                {
2646                        ULONG OneSecTxNoRetryOKRationCount;
2647
2648                        if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2649                                ratio = 5;
2650                        else
2651                                ratio = 4;
2652
2653                        // downgrade TX quality if PER >= Rate-Down threshold
2654                        if (TxErrorRatio >= TrainDown)
2655                        {
2656                                pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2657                        }
2658
2659                        pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2660
2661                        OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2662
2663                        // perform DRS - consider TxRate Down first, then rate up.
2664                        if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2665                        {
2666                                if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2667                                {
2668                                        pAd->CommonCfg.TxRateIndex = DownRateIdx;
2669                                        pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2670
2671                                }
2672
2673                        }
2674                        else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2675                        {
2676                                if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2677                                {
2678
2679                                }
2680                                else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2681                                {
2682                                        pAd->CommonCfg.TxRateIndex = UpRateIdx;
2683                                }
2684                        }
2685                }while (FALSE);
2686
2687                // if rate-up happen, clear all bad history of all TX rates
2688                if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2689                {
2690                        pAd->DrsCounters.TxRateUpPenalty = 0;
2691                        NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2692                        NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2693#ifdef RT2870
2694                        bTxRateChanged = TRUE;
2695#endif
2696                }
2697                // if rate-down happen, only clear DownRate's bad history
2698                else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2699                {
2700                        DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2701
2702                        pAd->DrsCounters.TxRateUpPenalty = 0;           // no penalty
2703                        pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2704                        pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2705#ifdef RT2870
2706                        bTxRateChanged = TRUE;
2707#endif
2708                }
2709                else
2710                {
2711                        bTxRateChanged = FALSE;
2712                }
2713
2714                pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2715                if (bTxRateChanged && pNextTxRate)
2716                {
2717                        MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2718                }
2719        }
2720}
2721
2722/*
2723        ==========================================================================
2724        Description:
2725                This routine is executed periodically inside MlmePeriodicExec() after
2726                association with an AP.
2727                It checks if StaCfg.Psm is consistent with user policy (recorded in
2728                StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2729                there're some conditions to consider:
2730                1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2731                   the time when Mibss==TRUE
2732                2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2733                   if outgoing traffic available in TxRing or MgmtRing.
2734        Output:
2735                1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2736
2737        IRQL = DISPATCH_LEVEL
2738
2739        ==========================================================================
2740 */
2741VOID MlmeCheckPsmChange(
2742        IN PRTMP_ADAPTER pAd,
2743        IN ULONG        Now32)
2744{
2745        ULONG   PowerMode;
2746
2747        // condition -
2748        // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2749        // 2. user wants either MAX_PSP or FAST_PSP
2750        // 3. but current psm is not in PWR_SAVE
2751        // 4. CNTL state machine is not doing SCANning
2752        // 5. no TX SUCCESS event for the past 1-sec period
2753#ifdef NDIS51_MINIPORT
2754        if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2755                PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2756        else
2757#endif
2758                PowerMode = pAd->StaCfg.WindowsPowerMode;
2759
2760        if (INFRA_ON(pAd) &&
2761                (PowerMode != Ndis802_11PowerModeCAM) &&
2762                (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2763#ifdef RT2860
2764                RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2765#else
2766                (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2767#endif
2768        {
2769                // add by johnli, use Rx OK data count per second to calculate throughput
2770                // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2771                // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2772                if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2773                                (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2774                        ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2775                        (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2776                {
2777                                // Get this time
2778                        NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2779                        pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2780                        MlmeSetPsmBit(pAd, PWR_SAVE);
2781                        if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2782                        {
2783                                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2784                        }
2785                        else
2786                        {
2787                                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2788                        }
2789                }
2790        }
2791}
2792
2793// IRQL = PASSIVE_LEVEL
2794// IRQL = DISPATCH_LEVEL
2795VOID MlmeSetPsmBit(
2796        IN PRTMP_ADAPTER pAd,
2797        IN USHORT psm)
2798{
2799        AUTO_RSP_CFG_STRUC csr4;
2800
2801        pAd->StaCfg.Psm = psm;
2802        RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2803        csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2804        RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2805
2806        DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2807}
2808
2809// IRQL = DISPATCH_LEVEL
2810VOID MlmeSetTxPreamble(
2811        IN PRTMP_ADAPTER pAd,
2812        IN USHORT TxPreamble)
2813{
2814        AUTO_RSP_CFG_STRUC csr4;
2815
2816        //
2817        // Always use Long preamble before verifiation short preamble functionality works well.
2818        // Todo: remove the following line if short preamble functionality works
2819        //
2820        //TxPreamble = Rt802_11PreambleLong;
2821
2822        RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2823        if (TxPreamble == Rt802_11PreambleLong)
2824        {
2825                DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2826                OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2827                csr4.field.AutoResponderPreamble = 0;
2828        }
2829        else
2830        {
2831                // NOTE: 1Mbps should always use long preamble
2832                DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2833                OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2834                csr4.field.AutoResponderPreamble = 1;
2835        }
2836
2837        RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2838}
2839
2840/*
2841    ==========================================================================
2842    Description:
2843        Update basic rate bitmap
2844    ==========================================================================
2845 */
2846
2847VOID UpdateBasicRateBitmap(
2848    IN  PRTMP_ADAPTER   pAdapter)
2849{
2850    INT  i, j;
2851                  /* 1  2  5.5, 11,  6,  9, 12, 18, 24, 36, 48,  54 */
2852    UCHAR rate[] = { 2, 4,  11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2853    UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2854    UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2855    ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2856
2857
2858    /* if A mode, always use fix BasicRateBitMap */
2859    //if (pAdapter->CommonCfg.Channel == PHY_11A)
2860        if (pAdapter->CommonCfg.Channel > 14)
2861        pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2862    /* End of if */
2863
2864    if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2865    {
2866        /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2867        return;
2868    } /* End of if */
2869
2870    for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2871    {
2872        sup_p[i] &= 0x7f;
2873        ext_p[i] &= 0x7f;
2874    } /* End of for */
2875
2876    for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2877    {
2878        if (bitmap & (1 << i))
2879        {
2880            for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2881            {
2882                if (sup_p[j] == rate[i])
2883                    sup_p[j] |= 0x80;
2884                /* End of if */
2885            } /* End of for */
2886
2887            for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2888            {
2889                if (ext_p[j] == rate[i])
2890                    ext_p[j] |= 0x80;
2891                /* End of if */
2892            } /* End of for */
2893        } /* End of if */
2894    } /* End of for */
2895} /* End of UpdateBasicRateBitmap */
2896
2897// IRQL = PASSIVE_LEVEL
2898// IRQL = DISPATCH_LEVEL
2899// bLinkUp is to identify the inital link speed.
2900// TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2901VOID MlmeUpdateTxRates(
2902        IN PRTMP_ADAPTER                pAd,
2903        IN      BOOLEAN                         bLinkUp,
2904        IN      UCHAR                           apidx)
2905{
2906        int i, num;
2907        UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2908        UCHAR MinSupport = RATE_54;
2909        ULONG BasicRateBitmap = 0;
2910        UCHAR CurrBasicRate = RATE_1;
2911        UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2912        PHTTRANSMIT_SETTING             pHtPhy = NULL;
2913        PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
2914        PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
2915        BOOLEAN                                 *auto_rate_cur_p;
2916        UCHAR                                   HtMcs = MCS_AUTO;
2917
2918        // find max desired rate
2919        UpdateBasicRateBitmap(pAd);
2920
2921        num = 0;
2922        auto_rate_cur_p = NULL;
2923        for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2924        {
2925                switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2926                {
2927                        case 2:  Rate = RATE_1;   num++;   break;
2928                        case 4:  Rate = RATE_2;   num++;   break;
2929                        case 11: Rate = RATE_5_5; num++;   break;
2930                        case 22: Rate = RATE_11;  num++;   break;
2931                        case 12: Rate = RATE_6;   num++;   break;
2932                        case 18: Rate = RATE_9;   num++;   break;
2933                        case 24: Rate = RATE_12;  num++;   break;
2934                        case 36: Rate = RATE_18;  num++;   break;
2935                        case 48: Rate = RATE_24;  num++;   break;
2936                        case 72: Rate = RATE_36;  num++;   break;
2937                        case 96: Rate = RATE_48;  num++;   break;
2938                        case 108: Rate = RATE_54; num++;   break;
2939                        //default: Rate = RATE_1;   break;
2940                }
2941                if (MaxDesire < Rate)  MaxDesire = Rate;
2942        }
2943
2944//===========================================================================
2945//===========================================================================
2946        {
2947                pHtPhy          = &pAd->StaCfg.HTPhyMode;
2948                pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
2949                pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
2950
2951                auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2952                HtMcs           = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2953
2954                if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2955                        (pAd->CommonCfg.PhyMode == PHY_11B) &&
2956                        (MaxDesire > RATE_11))
2957                {
2958                        MaxDesire = RATE_11;
2959                }
2960        }
2961
2962        pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2963        pMinHtPhy->word = 0;
2964        pMaxHtPhy->word = 0;
2965        pHtPhy->word = 0;
2966
2967        // Auto rate switching is enabled only if more than one DESIRED RATES are
2968        // specified; otherwise disabled
2969        if (num <= 1)
2970        {
2971                *auto_rate_cur_p = FALSE;
2972        }
2973        else
2974        {
2975                *auto_rate_cur_p = TRUE;
2976        }
2977
2978#if 1
2979        if (HtMcs != MCS_AUTO)
2980        {
2981                *auto_rate_cur_p = FALSE;
2982        }
2983        else
2984        {
2985                *auto_rate_cur_p = TRUE;
2986        }
2987#endif
2988
2989        if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2990        {
2991                pSupRate = &pAd->StaActive.SupRate[0];
2992                pExtRate = &pAd->StaActive.ExtRate[0];
2993                SupRateLen = pAd->StaActive.SupRateLen;
2994                ExtRateLen = pAd->StaActive.ExtRateLen;
2995        }
2996        else
2997        {
2998                pSupRate = &pAd->CommonCfg.SupRate[0];
2999                pExtRate = &pAd->CommonCfg.ExtRate[0];
3000                SupRateLen = pAd->CommonCfg.SupRateLen;
3001                ExtRateLen = pAd->CommonCfg.ExtRateLen;
3002        }
3003
3004        // find max supported rate
3005        for (i=0; i<SupRateLen; i++)
3006        {
3007                switch (pSupRate[i] & 0x7f)
3008                {
3009                        case 2:   Rate = RATE_1;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
3010                        case 4:   Rate = RATE_2;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
3011                        case 11:  Rate = RATE_5_5;      if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
3012                        case 22:  Rate = RATE_11;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
3013                        case 12:  Rate = RATE_6;        /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
3014                        case 18:  Rate = RATE_9;        if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
3015                        case 24:  Rate = RATE_12;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
3016                        case 36:  Rate = RATE_18;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
3017                        case 48:  Rate = RATE_24;       /*if (pSupRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
3018                        case 72:  Rate = RATE_36;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
3019                        case 96:  Rate = RATE_48;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
3020                        case 108: Rate = RATE_54;       if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
3021                        default:  Rate = RATE_1;        break;
3022                }
3023                if (MaxSupport < Rate)  MaxSupport = Rate;
3024
3025                if (MinSupport > Rate) MinSupport = Rate;
3026        }
3027
3028        for (i=0; i<ExtRateLen; i++)
3029        {
3030                switch (pExtRate[i] & 0x7f)
3031                {
3032                        case 2:   Rate = RATE_1;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001;       break;
3033                        case 4:   Rate = RATE_2;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002;       break;
3034                        case 11:  Rate = RATE_5_5;      if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004;       break;
3035                        case 22:  Rate = RATE_11;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008;       break;
3036                        case 12:  Rate = RATE_6;        /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0010;  break;
3037                        case 18:  Rate = RATE_9;        if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020;       break;
3038                        case 24:  Rate = RATE_12;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0040;  break;
3039                        case 36:  Rate = RATE_18;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080;       break;
3040                        case 48:  Rate = RATE_24;       /*if (pExtRate[i] & 0x80)*/  BasicRateBitmap |= 0x0100;  break;
3041                        case 72:  Rate = RATE_36;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200;       break;
3042                        case 96:  Rate = RATE_48;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400;       break;
3043                        case 108: Rate = RATE_54;       if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800;       break;
3044                        default:  Rate = RATE_1;        break;
3045                }
3046                if (MaxSupport < Rate)  MaxSupport = Rate;
3047
3048                if (MinSupport > Rate) MinSupport = Rate;
3049        }
3050
3051        RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3052
3053        // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3054        // the DURATION field of outgoing uniicast DATA/MGMT frame
3055        for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3056        {
3057                if (BasicRateBitmap & (0x01 << i))
3058                        CurrBasicRate = (UCHAR)i;
3059                pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3060        }
3061
3062        DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3063        // max tx rate = min {max desire rate, max supported rate}
3064        if (MaxSupport < MaxDesire)
3065                pAd->CommonCfg.MaxTxRate = MaxSupport;
3066        else
3067                pAd->CommonCfg.MaxTxRate = MaxDesire;
3068
3069        pAd->CommonCfg.MinTxRate = MinSupport;
3070        if (*auto_rate_cur_p)
3071        {
3072                short dbm = 0;
3073
3074                dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3075
3076                if (bLinkUp == TRUE)
3077                        pAd->CommonCfg.TxRate = RATE_24;
3078                else
3079                        pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3080
3081                if (dbm < -75)
3082                        pAd->CommonCfg.TxRate = RATE_11;
3083                else if (dbm < -70)
3084                        pAd->CommonCfg.TxRate = RATE_24;
3085
3086                // should never exceed MaxTxRate (consider 11B-only mode)
3087                if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3088                        pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3089
3090                pAd->CommonCfg.TxRateIndex = 0;
3091        }
3092        else
3093        {
3094                pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3095                pHtPhy->field.MCS       = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3096                pHtPhy->field.MODE      = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3097
3098                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC    = pHtPhy->field.STBC;
3099                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3100                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS             = pHtPhy->field.MCS;
3101                pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE    = pHtPhy->field.MODE;
3102        }
3103
3104        if (pAd->CommonCfg.TxRate <= RATE_11)
3105        {
3106                pMaxHtPhy->field.MODE = MODE_CCK;
3107                pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3108                pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3109        }
3110        else
3111        {
3112                pMaxHtPhy->field.MODE = MODE_OFDM;
3113                pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3114                if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3115                        {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3116                else
3117                        {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3118        }
3119
3120        pHtPhy->word = (pMaxHtPhy->word);
3121        if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3122        {
3123                        pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3124                        pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3125                        pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3126        }
3127        else
3128        {
3129                switch (pAd->CommonCfg.PhyMode)
3130                {
3131                        case PHY_11BG_MIXED:
3132                        case PHY_11B:
3133                        case PHY_11BGN_MIXED:
3134                                pAd->CommonCfg.MlmeRate = RATE_1;
3135                                pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3136                                pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3137                                pAd->CommonCfg.RtsRate = RATE_11;
3138                                break;
3139                        case PHY_11G:
3140                        case PHY_11A:
3141                        case PHY_11AGN_MIXED:
3142                        case PHY_11GN_MIXED:
3143                        case PHY_11N_2_4G:
3144                        case PHY_11AN_MIXED:
3145                        case PHY_11N_5G:
3146                                pAd->CommonCfg.MlmeRate = RATE_6;
3147                                pAd->CommonCfg.RtsRate = RATE_6;
3148                                pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3149                                pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3150                                break;
3151                        case PHY_11ABG_MIXED:
3152                        case PHY_11ABGN_MIXED:
3153                                if (pAd->CommonCfg.Channel <= 14)
3154                                {
3155                                        pAd->CommonCfg.MlmeRate = RATE_1;
3156                                        pAd->CommonCfg.RtsRate = RATE_1;
3157                                        pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3158                                        pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3159                                }
3160                                else
3161                                {
3162                                        pAd->CommonCfg.MlmeRate = RATE_6;
3163                                        pAd->CommonCfg.RtsRate = RATE_6;
3164                                        pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3165                                        pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3166                                }
3167                                break;
3168                        default: // error
3169                                pAd->CommonCfg.MlmeRate = RATE_6;
3170                                pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3171                                pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3172                                pAd->CommonCfg.RtsRate = RATE_1;
3173                                break;
3174                }
3175                //
3176                // Keep Basic Mlme Rate.
3177                //
3178                pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3179                if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3180                        pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3181                else
3182                        pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3183                pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3184        }
3185
3186        DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3187                         RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3188                         /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3189        DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3190                         RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3191        DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3192                         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 ));
3193}
3194
3195/*
3196        ==========================================================================
3197        Description:
3198                This function update HT Rate setting.
3199                Input Wcid value is valid for 2 case :
3200                1. it's used for Station in infra mode that copy AP rate to Mactable.
3201                2. OR Station   in adhoc mode to copy peer's HT rate to Mactable.
3202
3203        IRQL = DISPATCH_LEVEL
3204
3205        ==========================================================================
3206 */
3207VOID MlmeUpdateHtTxRates(
3208        IN PRTMP_ADAPTER                pAd,
3209        IN      UCHAR                           apidx)
3210{
3211        UCHAR   StbcMcs; //j, StbcMcs, bitmask;
3212        CHAR    i; // 3*3
3213        RT_HT_CAPABILITY        *pRtHtCap = NULL;
3214        RT_HT_PHY_INFO          *pActiveHtPhy = NULL;
3215        ULONG           BasicMCS;
3216        UCHAR j, bitmask;
3217        PRT_HT_PHY_INFO                 pDesireHtPhy = NULL;
3218        PHTTRANSMIT_SETTING             pHtPhy = NULL;
3219        PHTTRANSMIT_SETTING             pMaxHtPhy = NULL;
3220        PHTTRANSMIT_SETTING             pMinHtPhy = NULL;
3221        BOOLEAN                                 *auto_rate_cur_p;
3222
3223        DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3224
3225        auto_rate_cur_p = NULL;
3226
3227        {
3228                pDesireHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
3229                pActiveHtPhy    = &pAd->StaCfg.DesiredHtPhyInfo;
3230                pHtPhy          = &pAd->StaCfg.HTPhyMode;
3231                pMaxHtPhy       = &pAd->StaCfg.MaxHTPhyMode;
3232                pMinHtPhy       = &pAd->StaCfg.MinHTPhyMode;
3233
3234                auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3235        }
3236
3237        if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3238        {
3239                if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3240                        return;
3241
3242                pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3243                pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3244                StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3245                BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3246                if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3247                        pMaxHtPhy->field.STBC = STBC_USE;
3248                else
3249                        pMaxHtPhy->field.STBC = STBC_NONE;
3250        }
3251        else
3252        {
3253                if (pDesireHtPhy->bHtEnable == FALSE)
3254                        return;
3255
3256                pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3257                StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3258                BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3259                if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3260                        pMaxHtPhy->field.STBC = STBC_USE;
3261                else
3262                        pMaxHtPhy->field.STBC = STBC_NONE;
3263        }
3264
3265        // Decide MAX ht rate.
3266        if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3267                pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3268        else
3269                pMaxHtPhy->field.MODE = MODE_HTMIX;
3270
3271    if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3272                pMaxHtPhy->field.BW = BW_40;
3273        else
3274                pMaxHtPhy->field.BW = BW_20;
3275
3276    if (pMaxHtPhy->field.BW == BW_20)
3277                pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3278        else
3279                pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3280
3281        for (i=23; i>=0; i--) // 3*3
3282        {
3283                j = i/8;
3284                bitmask = (1<<(i-(j*8)));
3285
3286                if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3287                {
3288                        pMaxHtPhy->field.MCS = i;
3289                        break;
3290                }
3291
3292                if (i==0)
3293                        break;
3294        }
3295
3296        // Copy MIN ht rate.  rt2860???
3297        pMinHtPhy->field.BW = BW_20;
3298        pMinHtPhy->field.MCS = 0;
3299        pMinHtPhy->field.STBC = 0;
3300        pMinHtPhy->field.ShortGI = 0;
3301        //If STA assigns fixed rate. update to fixed here.
3302        if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3303        {
3304                if (pDesireHtPhy->MCSSet[4] != 0)
3305                {
3306                        pMaxHtPhy->field.MCS = 32;
3307                        pMinHtPhy->field.MCS = 32;
3308                        DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3309                }
3310
3311                for (i=23; (CHAR)i >= 0; i--) // 3*3
3312                {
3313                        j = i/8;
3314                        bitmask = (1<<(i-(j*8)));
3315                        if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3316                        {
3317                                pMaxHtPhy->field.MCS = i;
3318                                pMinHtPhy->field.MCS = i;
3319                                break;
3320                        }
3321                        if (i==0)
3322                                break;
3323                }
3324        }
3325
3326        // Decide ht rate
3327        pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3328        pHtPhy->field.BW = pMaxHtPhy->field.BW;
3329        pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3330        pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3331        pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3332
3333        // use default now. rt2860
3334        if (pDesireHtPhy->MCSSet[0] != 0xff)
3335                *auto_rate_cur_p = FALSE;
3336        else
3337                *auto_rate_cur_p = TRUE;
3338
3339        DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d  \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3340        DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d,  \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3341                pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3342        DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3343}
3344
3345// IRQL = DISPATCH_LEVEL
3346VOID MlmeRadioOff(
3347        IN PRTMP_ADAPTER pAd)
3348{
3349        RT28XX_MLME_RADIO_OFF(pAd);
3350}
3351
3352// IRQL = DISPATCH_LEVEL
3353VOID MlmeRadioOn(
3354        IN PRTMP_ADAPTER pAd)
3355{
3356        RT28XX_MLME_RADIO_ON(pAd);
3357}
3358
3359// ===========================================================================================
3360// bss_table.c
3361// ===========================================================================================
3362
3363
3364/*! \brief initialize BSS table
3365 *      \param p_tab pointer to the table
3366 *      \return none
3367 *      \pre
3368 *      \post
3369
3370 IRQL = PASSIVE_LEVEL
3371 IRQL = DISPATCH_LEVEL
3372
3373 */
3374VOID BssTableInit(
3375        IN BSS_TABLE *Tab)
3376{
3377        int i;
3378
3379        Tab->BssNr = 0;
3380    Tab->BssOverlapNr = 0;
3381        for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3382        {
3383                NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3384                Tab->BssEntry[i].Rssi = -127;   // initial the rssi as a minimum value
3385        }
3386}
3387
3388VOID BATableInit(
3389        IN PRTMP_ADAPTER pAd,
3390    IN BA_TABLE *Tab)
3391{
3392        int i;
3393
3394        Tab->numAsOriginator = 0;
3395        Tab->numAsRecipient = 0;
3396        NdisAllocateSpinLock(&pAd->BATabLock);
3397        for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3398        {
3399                Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3400                NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3401        }
3402        for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3403        {
3404                Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3405        }
3406}
3407
3408/*! \brief search the BSS table by SSID
3409 *      \param p_tab pointer to the bss table
3410 *      \param ssid SSID string
3411 *      \return index of the table, BSS_NOT_FOUND if not in the table
3412 *      \pre
3413 *      \post
3414 *      \note search by sequential search
3415
3416 IRQL = DISPATCH_LEVEL
3417
3418 */
3419ULONG BssTableSearch(
3420        IN BSS_TABLE *Tab,
3421        IN PUCHAR        pBssid,
3422        IN UCHAR         Channel)
3423{
3424        UCHAR i;
3425
3426        for (i = 0; i < Tab->BssNr; i++)
3427        {
3428                //
3429                // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3430                // We should distinguish this case.
3431                //
3432                if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3433                         ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3434                        MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3435                {
3436                        return i;
3437                }
3438        }
3439        return (ULONG)BSS_NOT_FOUND;
3440}
3441
3442ULONG BssSsidTableSearch(
3443        IN BSS_TABLE *Tab,
3444        IN PUCHAR        pBssid,
3445        IN PUCHAR        pSsid,
3446        IN UCHAR         SsidLen,
3447        IN UCHAR         Channel)
3448{
3449        UCHAR i;
3450
3451        for (i = 0; i < Tab->BssNr; i++)
3452        {
3453                //
3454                // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3455                // We should distinguish this case.
3456                //
3457                if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3458                         ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3459                        MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3460                        SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3461                {
3462                        return i;
3463                }
3464        }
3465        return (ULONG)BSS_NOT_FOUND;
3466}
3467
3468ULONG BssTableSearchWithSSID(
3469        IN BSS_TABLE *Tab,
3470        IN PUCHAR        Bssid,
3471        IN PUCHAR        pSsid,
3472        IN UCHAR         SsidLen,
3473        IN UCHAR         Channel)
3474{
3475        UCHAR i;
3476
3477        for (i = 0; i < Tab->BssNr; i++)
3478        {
3479                if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3480                        ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3481                        MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3482                        (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3483                        (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3484                        (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3485                {
3486                        return i;
3487                }
3488        }
3489        return (ULONG)BSS_NOT_FOUND;
3490}
3491
3492// IRQL = DISPATCH_LEVEL
3493VOID BssTableDeleteEntry(
3494        IN OUT  BSS_TABLE *Tab,
3495        IN              PUCHAR    pBssid,
3496        IN              UCHAR     Channel)
3497{
3498        UCHAR i, j;
3499
3500        for (i = 0; i < Tab->BssNr; i++)
3501        {
3502                if ((Tab->BssEntry[i].Channel == Channel) &&
3503                        (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3504                {
3505                        for (j = i; j < Tab->BssNr - 1; j++)
3506                        {
3507                                NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3508                        }
3509                        NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3510                        Tab->BssNr -= 1;
3511                        return;
3512                }
3513        }
3514}
3515
3516/*
3517        ========================================================================
3518        Routine Description:
3519                Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3520
3521        Arguments:
3522        // IRQL = DISPATCH_LEVEL
3523        ========================================================================
3524*/
3525VOID BATableDeleteORIEntry(
3526        IN OUT  PRTMP_ADAPTER pAd,
3527        IN              BA_ORI_ENTRY    *pBAORIEntry)
3528{
3529
3530        if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3531        {
3532                NdisAcquireSpinLock(&pAd->BATabLock);
3533                if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3534                {
3535                        pAd->BATable.numAsOriginator -= 1;
3536                        DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3537                        // Erase Bitmap flag.
3538                }
3539                pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) ));       // If STA mode,  erase flag here
3540                pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0;    // If STA mode,  erase flag here
3541                pBAORIEntry->ORI_BA_Status = Originator_NONE;
3542                pBAORIEntry->Token = 1;
3543                // Not clear Sequence here.
3544                NdisReleaseSpinLock(&pAd->BATabLock);
3545        }
3546}
3547
3548/*! \brief
3549 *      \param
3550 *      \return
3551 *      \pre
3552 *      \post
3553
3554 IRQL = DISPATCH_LEVEL
3555
3556 */
3557VOID BssEntrySet(
3558        IN PRTMP_ADAPTER        pAd,
3559        OUT BSS_ENTRY *pBss,
3560        IN PUCHAR pBssid,
3561        IN CHAR Ssid[],
3562        IN UCHAR SsidLen,
3563        IN UCHAR BssType,
3564        IN USHORT BeaconPeriod,
3565        IN PCF_PARM pCfParm,
3566        IN USHORT AtimWin,
3567        IN USHORT CapabilityInfo,
3568        IN UCHAR SupRate[],
3569        IN UCHAR SupRateLen,
3570        IN UCHAR ExtRate[],
3571        IN UCHAR ExtRateLen,
3572        IN HT_CAPABILITY_IE *pHtCapability,
3573        IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
3574        IN UCHAR                        HtCapabilityLen,
3575        IN UCHAR                        AddHtInfoLen,
3576        IN UCHAR                        NewExtChanOffset,
3577        IN UCHAR Channel,
3578        IN CHAR Rssi,
3579        IN LARGE_INTEGER TimeStamp,
3580        IN UCHAR CkipFlag,
3581        IN PEDCA_PARM pEdcaParm,
3582        IN PQOS_CAPABILITY_PARM pQosCapability,
3583        IN PQBSS_LOAD_PARM pQbssLoad,
3584        IN USHORT LengthVIE,
3585        IN PNDIS_802_11_VARIABLE_IEs pVIE)
3586{
3587        COPY_MAC_ADDR(pBss->Bssid, pBssid);
3588        // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3589        pBss->Hidden = 1;
3590        if (SsidLen > 0)
3591        {
3592                // For hidden SSID AP, it might send beacon with SSID len equal to 0
3593                // Or send beacon /probe response with SSID len matching real SSID length,
3594                // but SSID is all zero. such as "00-00-00-00" with length 4.
3595                // We have to prevent this case overwrite correct table
3596                if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3597                {
3598                    NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3599                        NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3600                        pBss->SsidLen = SsidLen;
3601                        pBss->Hidden = 0;
3602                }
3603        }
3604        else
3605                pBss->SsidLen = 0;
3606        pBss->BssType = BssType;
3607        pBss->BeaconPeriod = BeaconPeriod;
3608        if (BssType == BSS_INFRA)
3609        {
3610                if (pCfParm->bValid)
3611                {
3612                        pBss->CfpCount = pCfParm->CfpCount;
3613                        pBss->CfpPeriod = pCfParm->CfpPeriod;
3614                        pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3615                        pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3616                }
3617        }
3618        else
3619        {
3620                pBss->AtimWin = AtimWin;
3621        }
3622
3623        pBss->CapabilityInfo = CapabilityInfo;
3624        // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3625        // Combine with AuthMode, they will decide the connection methods.
3626        pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3627        ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3628        if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3629                NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3630        else
3631                NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3632        pBss->SupRateLen = SupRateLen;
3633        ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3634        NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3635        NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3636        NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3637        pBss->NewExtChanOffset = NewExtChanOffset;
3638        pBss->ExtRateLen = ExtRateLen;
3639        pBss->Channel = Channel;
3640        pBss->CentralChannel = Channel;
3641        pBss->Rssi = Rssi;
3642        // Update CkipFlag. if not exists, the value is 0x0
3643        pBss->CkipFlag = CkipFlag;
3644
3645        // New for microsoft Fixed IEs
3646        NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3647        pBss->FixIEs.BeaconInterval = BeaconPeriod;
3648        pBss->FixIEs.Capabilities = CapabilityInfo;
3649
3650        // New for microsoft Variable IEs
3651        if (LengthVIE != 0)
3652        {
3653                pBss->VarIELen = LengthVIE;
3654                NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3655        }
3656        else
3657        {
3658                pBss->VarIELen = 0;
3659        }
3660
3661        pBss->AddHtInfoLen = 0;
3662        pBss->HtCapabilityLen = 0;
3663
3664        if (HtCapabilityLen> 0)
3665        {
3666                pBss->HtCapabilityLen = HtCapabilityLen;
3667                NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3668                if (AddHtInfoLen > 0)
3669                {
3670                        pBss->AddHtInfoLen = AddHtInfoLen;
3671                        NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3672
3673                                if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3674                                {
3675                                        pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3676                                }
3677                                else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3678                                {
3679                                                pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3680                                }
3681                }
3682        }
3683
3684        BssCipherParse(pBss);
3685
3686        // new for QOS
3687        if (pEdcaParm)
3688                NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3689        else
3690                pBss->EdcaParm.bValid = FALSE;
3691        if (pQosCapability)
3692                NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3693        else
3694                pBss->QosCapability.bValid = FALSE;
3695        if (pQbssLoad)
3696                NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3697        else
3698                pBss->QbssLoad.bValid = FALSE;
3699
3700        {
3701                PEID_STRUCT     pEid;
3702                USHORT          Length = 0;
3703
3704
3705                NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3706                NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3707
3708                pEid = (PEID_STRUCT) pVIE;
3709
3710                while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3711                {
3712                        switch(pEid->Eid)
3713                        {
3714                                case IE_WPA:
3715                                        if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3716                                        {
3717                                                if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3718                                                {
3719                                                        pBss->WpaIE.IELen = 0;
3720                                                        break;
3721                                                }
3722                                                pBss->WpaIE.IELen = pEid->Len + 2;
3723                                                NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3724                                        }
3725                                        break;
3726                case IE_RSN:
3727                    if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3728                                        {
3729                                                if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3730                                                {
3731                                                        pBss->RsnIE.IELen = 0;
3732                                                        break;
3733                                                }
3734                                                pBss->RsnIE.IELen = pEid->Len + 2;
3735                                                NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3736                        }
3737                                break;
3738            }
3739                        Length = Length + 2 + (USHORT)pEid->Len;  // Eid[1] + Len[1]+ content[Len]
3740                        pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3741                }
3742        }
3743}
3744
3745/*!
3746 *      \brief insert an entry into the bss table
3747 *      \param p_tab The BSS table
3748 *      \param Bssid BSSID
3749 *      \param ssid SSID
3750 *      \param ssid_len Length of SSID
3751 *      \param bss_type
3752 *      \param beacon_period
3753 *      \param timestamp
3754 *      \param p_cf
3755 *      \param atim_win
3756 *      \param cap
3757 *      \param rates
3758 *      \param rates_len
3759 *      \param channel_idx
3760 *      \return none
3761 *      \pre
3762 *      \post
3763 *      \note If SSID is identical, the old entry will be replaced by the new one
3764
3765 IRQL = DISPATCH_LEVEL
3766
3767 */
3768ULONG BssTableSetEntry(
3769        IN      PRTMP_ADAPTER   pAd,
3770        OUT BSS_TABLE *Tab,
3771        IN PUCHAR pBssid,
3772        IN CHAR Ssid[],
3773        IN UCHAR SsidLen,
3774        IN UCHAR BssType,
3775        IN USHORT BeaconPeriod,
3776        IN CF_PARM *CfParm,
3777        IN USHORT AtimWin,
3778        IN USHORT CapabilityInfo,
3779        IN UCHAR SupRate[],
3780        IN UCHAR SupRateLen,
3781        IN UCHAR ExtRate[],
3782        IN UCHAR ExtRateLen,
3783        IN HT_CAPABILITY_IE *pHtCapability,
3784        IN ADD_HT_INFO_IE *pAddHtInfo,  // AP might use this additional ht info IE
3785        IN UCHAR                        HtCapabilityLen,
3786        IN UCHAR                        AddHtInfoLen,
3787        IN UCHAR                        NewExtChanOffset,
3788        IN UCHAR ChannelNo,
3789        IN CHAR Rssi,
3790        IN LARGE_INTEGER TimeStamp,
3791        IN UCHAR CkipFlag,
3792        IN PEDCA_PARM pEdcaParm,
3793        IN PQOS_CAPABILITY_PARM pQosCapability,
3794        IN PQBSS_LOAD_PARM pQbssLoad,
3795        IN USHORT LengthVIE,
3796        IN PNDIS_802_11_VARIABLE_IEs pVIE)
3797{
3798        ULONG   Idx;
3799
3800        Idx = BssTableSearchWithSSID(Tab, pBssid,  Ssid, SsidLen, ChannelNo);
3801        if (Idx == BSS_NOT_FOUND)
3802        {
3803                if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3804            {
3805                        //
3806                        // It may happen when BSS Table was full.
3807                        // The desired AP will not be added into BSS Table
3808                        // In this case, if we found the desired AP then overwrite BSS Table.
3809                        //
3810                        if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3811                        {
3812                                if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3813                                        SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3814                                {
3815                                        Idx = Tab->BssOverlapNr;
3816                                        BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3817                                                CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3818                                                NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3819                    Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3820                                }
3821                                return Idx;
3822                        }
3823                        else
3824                        {
3825                        return BSS_NOT_FOUND;
3826                        }
3827                }
3828                Idx = Tab->BssNr;
3829                BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3830                                        CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3831                                        NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3832                Tab->BssNr++;
3833        }
3834        else
3835        {
3836                /* avoid  Hidden SSID form beacon to overwirite correct SSID from probe response */
3837                if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3838                        (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3839                {
3840                BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3841                                        CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3842                                        NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3843                }
3844        }
3845
3846        return Idx;
3847}
3848
3849// IRQL = DISPATCH_LEVEL
3850VOID BssTableSsidSort(
3851        IN      PRTMP_ADAPTER   pAd,
3852        OUT BSS_TABLE *OutTab,
3853        IN      CHAR Ssid[],
3854        IN      UCHAR SsidLen)
3855{
3856        INT i;
3857        BssTableInit(OutTab);
3858
3859        for (i = 0; i < pAd->ScanTab.BssNr; i++)
3860        {
3861                BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3862                BOOLEAN bIsHiddenApIncluded = FALSE;
3863
3864                if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3865            (pAd->MlmeAux.Channel > 14) &&
3866             RadarChannelCheck(pAd, pInBss->Channel))
3867            )
3868                {
3869                        if (pInBss->Hidden)
3870                                bIsHiddenApIncluded = TRUE;
3871                }
3872
3873                if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3874                        (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3875                {
3876                        BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3877
3878                        // 2.4G/5G N only mode
3879                        if ((pInBss->HtCapabilityLen == 0) &&
3880                                ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3881                        {
3882                                DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3883                                continue;
3884                        }
3885
3886                        // New for WPA2
3887                        // Check the Authmode first
3888                        if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3889                        {
3890                                // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3891                                if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3892                                        // None matched
3893                                        continue;
3894
3895                                // Check cipher suite, AP must have more secured cipher than station setting
3896                                if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3897                                {
3898                                        // If it's not mixed mode, we should only let BSS pass with the same encryption
3899                                        if (pInBss->WPA.bMixMode == FALSE)
3900                                                if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3901                                                        continue;
3902
3903                                        // check group cipher
3904                                        if (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3905                                            pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3906                                            pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3907                                                continue;
3908
3909                                        // check pairwise cipher, skip if none matched
3910                                        // If profile set to AES, let it pass without question.
3911                                        // If profile set to TKIP, we must find one mateched
3912                                        if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3913                                                (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3914                                                (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3915                                                continue;
3916                                }
3917                                else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3918                                {
3919                                        // If it's not mixed mode, we should only let BSS pass with the same encryption
3920                                        if (pInBss->WPA2.bMixMode == FALSE)
3921                                                if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3922                                                        continue;
3923
3924                                        // check group cipher
3925                                        if (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled &&
3926                                            pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled &&
3927                                            pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3928                                                continue;
3929
3930                                        // check pairwise cipher, skip if none matched
3931                                        // If profile set to AES, let it pass without question.
3932                                        // If profile set to TKIP, we must find one mateched
3933                                        if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3934                                                (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3935                                                (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3936                                                continue;
3937                                }
3938                        }
3939                        // Bss Type matched, SSID matched.
3940                        // We will check wepstatus for qualification Bss
3941                        else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3942                        {
3943                                DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3944                                //
3945                                // For the SESv2 case, we will not qualify WepStatus.
3946                                //
3947                                if (!pInBss->bSES)
3948                                        continue;
3949                        }
3950
3951                        // Since the AP is using hidden SSID, and we are trying to connect to ANY
3952                        // It definitely will fail. So, skip it.
3953                        // CCX also require not even try to connect it!!
3954                        if (SsidLen == 0)
3955                                continue;
3956
3957                        // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3958                        // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3959                        if ((pInBss->CentralChannel != pInBss->Channel) &&
3960                                (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3961                        {
3962                                if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3963                                {
3964                                        pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3965                                        SetCommonHT(pAd);
3966                                        pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3967                                }
3968                                else
3969                                {
3970                                        if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3971                                        {
3972                                                SetCommonHT(pAd);
3973                                        }
3974                                }
3975                        }
3976
3977                        // copy matching BSS from InTab to OutTab
3978                        NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3979
3980                        OutTab->BssNr++;
3981                }
3982                else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3983                {
3984                        BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3985
3986                        // 2.4G/5G N only mode
3987                        if ((pInBss->HtCapabilityLen == 0) &&
3988                                ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3989                        {
3990                                DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3991                                continue;
3992                        }
3993
3994                        // New for WPA2
3995                        // Check the Authmode first
3996                        if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3997                        {
3998                                // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3999                                if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4000                                        // None matched
4001                                        continue;
4002
4003                                // Check cipher suite, AP must have more secured cipher than station setting
4004                                if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4005                                {
4006                                        // If it's not mixed mode, we should only let BSS pass with the same encryption
4007                                        if (pInBss->WPA.bMixMode == FALSE)
4008                                                if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4009                                                        continue;
4010
4011                                        // check group cipher
4012                                        if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4013                                                continue;
4014
4015                                        // check pairwise cipher, skip if none matched
4016                                        // If profile set to AES, let it pass without question.
4017                                        // If profile set to TKIP, we must find one mateched
4018                                        if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4019                                                (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4020                                                (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4021                                                continue;
4022                                }
4023                                else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4024                                {
4025                                        // If it's not mixed mode, we should only let BSS pass with the same encryption
4026                                        if (pInBss->WPA2.bMixMode == FALSE)
4027                                                if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4028                                                        continue;
4029
4030                                        // check group cipher
4031                                        if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4032                                                continue;
4033
4034                                        // check pairwise cipher, skip if none matched
4035                                        // If profile set to AES, let it pass without question.
4036                                        // If profile set to TKIP, we must find one mateched
4037                                        if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4038                                                (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4039                                                (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4040                                                continue;
4041                                }
4042                        }
4043                        // Bss Type matched, SSID matched.
4044                        // We will check wepstatus for qualification Bss
4045                        else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4046                                        continue;
4047
4048                        // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4049                        // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4050                        if ((pInBss->CentralChannel != pInBss->Channel) &&
4051                                (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4052                        {
4053                                if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4054                                {
4055                                        pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4056                                        SetCommonHT(pAd);
4057                                        pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4058                                }
4059                        }
4060
4061                        // copy matching BSS from InTab to OutTab
4062                        NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4063
4064                        OutTab->BssNr++;
4065                }
4066
4067                if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4068                        break;
4069        }
4070
4071        BssTableSortByRssi(OutTab);
4072}
4073
4074
4075// IRQL = DISPATCH_LEVEL
4076VOID BssTableSortByRssi(
4077        IN OUT BSS_TABLE *OutTab)
4078{
4079        INT       i, j;
4080        BSS_ENTRY TmpBss;
4081
4082        for (i = 0; i < OutTab->BssNr - 1; i++)
4083        {
4084                for (j = i+1; j < OutTab->BssNr; j++)
4085                {
4086                        if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4087                        {
4088                                NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4089                                NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4090                                NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4091                        }
4092                }
4093        }
4094}
4095
4096VOID BssCipherParse(
4097        IN OUT  PBSS_ENTRY      pBss)
4098{
4099        PEID_STRUCT              pEid;
4100        PUCHAR                          pTmp;
4101        PRSN_IE_HEADER_STRUCT                   pRsnHeader;
4102        PCIPHER_SUITE_STRUCT                    pCipher;
4103        PAKM_SUITE_STRUCT                               pAKM;
4104        USHORT                                                  Count;
4105        INT                                                             Length;
4106        NDIS_802_11_ENCRYPTION_STATUS   TmpCipher;
4107
4108        //
4109        // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4110        //
4111        if (pBss->Privacy)
4112        {
4113                pBss->WepStatus         = Ndis802_11WEPEnabled;
4114        }
4115        else
4116        {
4117                pBss->WepStatus         = Ndis802_11WEPDisabled;
4118        }
4119        // Set default to disable & open authentication before parsing variable IE
4120        pBss->AuthMode          = Ndis802_11AuthModeOpen;
4121        pBss->AuthModeAux       = Ndis802_11AuthModeOpen;
4122
4123        // Init WPA setting
4124        pBss->WPA.PairCipher    = Ndis802_11WEPDisabled;
4125        pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4126        pBss->WPA.GroupCipher   = Ndis802_11WEPDisabled;
4127        pBss->WPA.RsnCapability = 0;
4128        pBss->WPA.bMixMode              = FALSE;
4129
4130        // Init WPA2 setting
4131        pBss->WPA2.PairCipher    = Ndis802_11WEPDisabled;
4132        pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4133        pBss->WPA2.GroupCipher   = Ndis802_11WEPDisabled;
4134        pBss->WPA2.RsnCapability = 0;
4135        pBss->WPA2.bMixMode      = FALSE;
4136
4137
4138        Length = (INT) pBss->VarIELen;
4139
4140        while (Length > 0)
4141        {
4142                // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4143                pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4144                pEid = (PEID_STRUCT) pTmp;
4145                switch (pEid->Eid)
4146                {
4147                        case IE_WPA:
4148                                //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4149                                if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4150                                {
4151                                        pTmp   += 11;
4152                                        switch (*pTmp)
4153                                        {
4154                                                case 1:
4155                                                case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4156                                                        pBss->WepStatus = Ndis802_11Encryption1Enabled;
4157                                                        pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4158                                                        pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4159                                                        break;
4160                                                case 2:
4161                                                        pBss->WepStatus = Ndis802_11Encryption2Enabled;
4162                                                        pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4163                                                        pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4164                                                        break;
4165                                                case 4:
4166                                                        pBss->WepStatus = Ndis802_11Encryption3Enabled;
4167                                                        pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4168                                                        pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4169                                                        break;
4170                                                default:
4171                                                        break;
4172                                        }
4173
4174                                        // if Cisco IE_WPA, break
4175                                        break;
4176                                }
4177                                else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4178                                {
4179                                        pBss->bSES = TRUE;
4180                                        break;
4181                                }
4182                                else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4183                                {
4184                                        // if unsupported vendor specific IE
4185                                        break;
4186                                }
4187                                // Skip OUI, version, and multicast suite
4188                                // This part should be improved in the future when AP supported multiple cipher suite.
4189                                // For now, it's OK since almost all APs have fixed cipher suite supported.
4190                                // pTmp = (PUCHAR) pEid->Octet;
4191                                pTmp   += 11;
4192
4193                                // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4194                                //      Value      Meaning
4195                                //      0                       None
4196                                //      1                       WEP-40
4197                                //      2                       Tkip
4198                                //      3                       WRAP
4199                                //      4                       AES
4200                                //      5                       WEP-104
4201                                // Parse group cipher
4202                                switch (*pTmp)
4203                                {
4204                                        case 1:
4205                                                pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4206                                                break;
4207                                        case 5:
4208                                                pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4209                                                break;
4210                                        case 2:
4211                                                pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4212                                                break;
4213                                        case 4:
4214                                                pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4215                                                break;
4216                                        default:
4217                                                break;
4218                                }
4219                                // number of unicast suite
4220                                pTmp   += 1;
4221
4222                                // skip all unicast cipher suites
4223                                //Count = *(PUSHORT) pTmp;
4224                                Count = (pTmp[1]<<8) + pTmp[0];
4225                                pTmp   += sizeof(USHORT);
4226
4227                                // Parsing all unicast cipher suite
4228                                while (Count > 0)
4229                                {
4230                                        // Skip OUI
4231                                        pTmp += 3;
4232                                        TmpCipher = Ndis802_11WEPDisabled;
4233                                        switch (*pTmp)
4234                                        {
4235                                                case 1:
4236                                                case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4237                                                        TmpCipher = Ndis802_11Encryption1Enabled;
4238                                                        break;
4239                                                case 2:
4240                                                        TmpCipher = Ndis802_11Encryption2Enabled;
4241                                                        break;
4242                                                case 4:
4243                                                        TmpCipher = Ndis802_11Encryption3Enabled;
4244                                                        break;
4245                                                default:
4246                                                        break;
4247                                        }
4248                                        if (TmpCipher > pBss->WPA.PairCipher)
4249                                        {
4250                                                // Move the lower cipher suite to PairCipherAux
4251                                                pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4252                                                pBss->WPA.PairCipher    = TmpCipher;
4253                                        }
4254                                        else
4255                                        {
4256                                                pBss->WPA.PairCipherAux = TmpCipher;
4257                                        }
4258                                        pTmp++;
4259                                        Count--;
4260                                }
4261
4262                                // 4. get AKM suite counts
4263                                //Count = *(PUSHORT) pTmp;
4264                                Count = (pTmp[1]<<8) + pTmp[0];
4265                                pTmp   += sizeof(USHORT);
4266                                pTmp   += 3;
4267
4268                                switch (*pTmp)
4269                                {
4270                                        case 1:
4271                                                // Set AP support WPA mode
4272                                                if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4273                                                        pBss->AuthMode = Ndis802_11AuthModeWPA;
4274                                                else
4275                                                        pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4276                                                break;
4277                                        case 2:
4278                                                // Set AP support WPA mode
4279                                                if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4280                                                        pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4281                                                else
4282                                                        pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4283                                                break;
4284                                        default:
4285                                                break;
4286                                }
4287                                pTmp   += 1;
4288
4289                                // Fixed for WPA-None
4290                                if (pBss->BssType == BSS_ADHOC)
4291                                {
4292                                        pBss->AuthMode    = Ndis802_11AuthModeWPANone;
4293                                        pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4294                                        pBss->WepStatus   = pBss->WPA.GroupCipher;
4295                                        if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4296                                                pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4297                                }
4298                                else
4299                                        pBss->WepStatus   = pBss->WPA.PairCipher;
4300
4301                                // Check the Pair & Group, if different, turn on mixed mode flag
4302                                if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4303                                        pBss->WPA.bMixMode = TRUE;
4304
4305                                break;
4306
4307                        case IE_RSN:
4308                                pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4309
4310                                // 0. Version must be 1
4311                                if (le2cpu16(pRsnHeader->Version) != 1)
4312                                        break;
4313                                pTmp   += sizeof(RSN_IE_HEADER_STRUCT);
4314
4315                                // 1. Check group cipher
4316                                pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4317                                if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4318                                        break;
4319
4320                                // Parse group cipher
4321                                switch (pCipher->Type)
4322                                {
4323                                        case 1:
4324                                                pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4325                                                break;
4326                                        case 5:
4327                                                pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4328                                                break;
4329                                        case 2:
4330                                                pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4331                                                break;
4332                                        case 4:
4333                                                pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4334                                                break;
4335                                        default:
4336                                                break;
4337                                }
4338                                // set to correct offset for next parsing
4339                                pTmp   += sizeof(CIPHER_SUITE_STRUCT);
4340
4341                                // 2. Get pairwise cipher counts
4342                                //Count = *(PUSHORT) pTmp;
4343                                Count = (pTmp[1]<<8) + pTmp[0];
4344                                pTmp   += sizeof(USHORT);
4345
4346                                // 3. Get pairwise cipher
4347                                // Parsing all unicast cipher suite
4348                                while (Count > 0)
4349                                {
4350                                        // Skip OUI
4351                                        pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4352                                        TmpCipher = Ndis802_11WEPDisabled;
4353                                        switch (pCipher->Type)
4354                                        {
4355                                                case 1:
4356                                                case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4357                                                        TmpCipher = Ndis802_11Encryption1Enabled;
4358                                                        break;
4359                                                case 2:
4360                                                        TmpCipher = Ndis802_11Encryption2Enabled;
4361                                                        break;
4362                                                case 4:
4363                                                        TmpCipher = Ndis802_11Encryption3Enabled;
4364                                                        break;
4365                                                default:
4366                                                        break;
4367                                        }
4368                                        if (TmpCipher > pBss->WPA2.PairCipher)
4369                                        {
4370                                                // Move the lower cipher suite to PairCipherAux
4371                                                pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4372                                                pBss->WPA2.PairCipher    = TmpCipher;
4373                                        }
4374                                        else
4375                                        {
4376                                                pBss->WPA2.PairCipherAux = TmpCipher;
4377                                        }
4378                                        pTmp += sizeof(CIPHER_SUITE_STRUCT);
4379                                        Count--;
4380                                }
4381
4382                                // 4. get AKM suite counts
4383                                //Count = *(PUSHORT) pTmp;
4384                                Count = (pTmp[1]<<8) + pTmp[0];
4385                                pTmp   += sizeof(USHORT);
4386
4387                                // 5. Get AKM ciphers
4388                                pAKM = (PAKM_SUITE_STRUCT) pTmp;
4389                                if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4390                                        break;
4391
4392                                switch (pAKM->Type)
4393                                {
4394                                        case 1:
4395                                                // Set AP support WPA mode
4396                                                if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4397                                                        pBss->AuthMode = Ndis802_11AuthModeWPA2;
4398                                                else
4399                                                        pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4400                                                break;
4401                                        case 2:
4402                                                // Set AP support WPA mode
4403                                                if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4404                                                        pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4405                                                else
4406                                                        pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4407                                                break;
4408                                        default:
4409                                                break;
4410                                }
4411                                pTmp   += (Count * sizeof(AKM_SUITE_STRUCT));
4412
4413                                // Fixed for WPA-None
4414                                if (pBss->BssType == BSS_ADHOC)
4415                                {
4416                                        pBss->AuthMode = Ndis802_11AuthModeWPANone;
4417                                        pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4418                                        pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4419                                        pBss->WPA.GroupCipher   = pBss->WPA2.GroupCipher;
4420                                        pBss->WepStatus                 = pBss->WPA.GroupCipher;
4421                                        if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4422                                                pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4423                                }
4424                                pBss->WepStatus   = pBss->WPA2.PairCipher;
4425
4426                                // 6. Get RSN capability
4427                                //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4428                                pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4429                                pTmp += sizeof(USHORT);
4430
4431                                // Check the Pair & Group, if different, turn on mixed mode flag
4432                                if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4433                                        pBss->WPA2.bMixMode = TRUE;
4434
4435                                break;
4436                        default:
4437                                break;
4438                }
4439                Length -= (pEid->Len + 2);
4440        }
4441}
4442
4443// ===========================================================================================
4444// mac_table.c
4445// ===========================================================================================
4446
4447/*! \brief generates a random mac address value for IBSS BSSID
4448 *      \param Addr the bssid location
4449 *      \return none
4450 *      \pre
4451 *      \post
4452 */
4453VOID MacAddrRandomBssid(
4454        IN PRTMP_ADAPTER pAd,
4455        OUT PUCHAR pAddr)
4456{
4457        INT i;
4458
4459        for (i = 0; i < MAC_ADDR_LEN; i++)
4460        {
4461                pAddr[i] = RandomByte(pAd);
4462        }
4463
4464        pAddr[0] = (pAddr[0] & 0xfe) | 0x02;  // the first 2 bits must be 01xxxxxxxx
4465}
4466
4467/*! \brief init the management mac frame header
4468 *      \param p_hdr mac header
4469 *      \param subtype subtype of the frame
4470 *      \param p_ds destination address, don't care if it is a broadcast address
4471 *      \return none
4472 *      \pre the station has the following information in the pAd->StaCfg
4473 *       - bssid
4474 *       - station address
4475 *      \post
4476 *      \note this function initializes the following field
4477
4478 IRQL = PASSIVE_LEVEL
4479 IRQL = DISPATCH_LEVEL
4480
4481 */
4482VOID MgtMacHeaderInit(
4483        IN      PRTMP_ADAPTER   pAd,
4484        IN OUT PHEADER_802_11 pHdr80211,
4485        IN UCHAR SubType,
4486        IN UCHAR ToDs,
4487        IN PUCHAR pDA,
4488        IN PUCHAR pBssid)
4489{
4490        NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4491
4492        pHdr80211->FC.Type = BTYPE_MGMT;
4493        pHdr80211->FC.SubType = SubType;
4494        pHdr80211->FC.ToDs = ToDs;
4495        COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4496
4497        COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4498
4499        COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4500}
4501
4502// ===========================================================================================
4503// mem_mgmt.c
4504// ===========================================================================================
4505
4506/*!***************************************************************************
4507 * This routine build an outgoing frame, and fill all information specified
4508 * in argument list to the frame body. The actual frame size is the summation
4509 * of all arguments.
4510 * input params:
4511 *              Buffer - pointer to a pre-allocated memory segment
4512 *              args - a list of <int arg_size, arg> pairs.
4513 *              NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4514 *                                                 function will FAIL!!!
4515 * return:
4516 *              Size of the buffer
4517 * usage:
4518 *              MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4519
4520 IRQL = PASSIVE_LEVEL
4521 IRQL = DISPATCH_LEVEL
4522
4523 ****************************************************************************/
4524ULONG MakeOutgoingFrame(
4525        OUT CHAR *Buffer,
4526        OUT ULONG *FrameLen, ...)
4527{
4528        CHAR   *p;
4529        int     leng;
4530        ULONG   TotLeng;
4531        va_list Args;
4532
4533        // calculates the total length
4534        TotLeng = 0;
4535        va_start(Args, FrameLen);
4536        do
4537        {
4538                leng = va_arg(Args, int);
4539                if (leng == END_OF_ARGS)
4540                {
4541                        break;
4542                }
4543                p = va_arg(Args, PVOID);
4544                NdisMoveMemory(&Buffer[TotLeng], p, leng);
4545                TotLeng = TotLeng + leng;
4546        } while(TRUE);
4547
4548        va_end(Args); /* clean up */
4549        *FrameLen = TotLeng;
4550        return TotLeng;
4551}
4552
4553// ===========================================================================================
4554// mlme_queue.c
4555// ===========================================================================================
4556
4557/*! \brief      Initialize The MLME Queue, used by MLME Functions
4558 *      \param  *Queue     The MLME Queue
4559 *      \return Always     Return NDIS_STATE_SUCCESS in this implementation
4560 *      \pre
4561 *      \post
4562 *      \note   Because this is done only once (at the init stage), no need to be locked
4563
4564 IRQL = PASSIVE_LEVEL
4565
4566 */
4567NDIS_STATUS MlmeQueueInit(
4568        IN MLME_QUEUE *Queue)
4569{
4570        INT i;
4571
4572        NdisAllocateSpinLock(&Queue->Lock);
4573
4574        Queue->Num      = 0;
4575        Queue->Head = 0;
4576        Queue->Tail = 0;
4577
4578        for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4579        {
4580                Queue->Entry[i].Occupied = FALSE;
4581                Queue->Entry[i].MsgLen = 0;
4582                NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4583        }
4584
4585        return NDIS_STATUS_SUCCESS;
4586}
4587
4588/*! \brief       Enqueue a message for other threads, if they want to send messages to MLME thread
4589 *      \param  *Queue    The MLME Queue
4590 *      \param   Machine  The State Machine Id
4591 *      \param   MsgType  The Message Type
4592 *      \param   MsgLen   The Message length
4593 *      \param  *Msg      The message pointer
4594 *      \return  TRUE if enqueue is successful, FALSE if the queue is full
4595 *      \pre
4596 *      \post
4597 *      \note    The message has to be initialized
4598
4599 IRQL = PASSIVE_LEVEL
4600 IRQL = DISPATCH_LEVEL
4601
4602 */
4603BOOLEAN MlmeEnqueue(
4604        IN      PRTMP_ADAPTER   pAd,
4605        IN ULONG Machine,
4606        IN ULONG MsgType,
4607        IN ULONG MsgLen,
4608        IN VOID *Msg)
4609{
4610        INT Tail;
4611        MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4612
4613        // Do nothing if the driver is starting halt state.
4614        // This might happen when timer already been fired before cancel timer with mlmehalt
4615        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4616                return FALSE;
4617
4618        // First check the size, it MUST not exceed the mlme queue size
4619        if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4620        {
4621                DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4622                return FALSE;
4623        }
4624
4625        if (MlmeQueueFull(Queue))
4626        {
4627                return FALSE;
4628        }
4629
4630        NdisAcquireSpinLock(&(Queue->Lock));
4631        Tail = Queue->Tail;
4632        Queue->Tail++;
4633        Queue->Num++;
4634        if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4635        {
4636                Queue->Tail = 0;
4637        }
4638
4639        Queue->Entry[Tail].Wcid = RESERVED_WCID;
4640        Queue->Entry[Tail].Occupied = TRUE;
4641        Queue->Entry[Tail].Machine = Machine;
4642        Queue->Entry[Tail].MsgType = MsgType;
4643        Queue->Entry[Tail].MsgLen  = MsgLen;
4644
4645        if (Msg != NULL)
4646        {
4647                NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4648        }
4649
4650        NdisReleaseSpinLock(&(Queue->Lock));
4651        return TRUE;
4652}
4653
4654/*! \brief       This function is used when Recv gets a MLME message
4655 *      \param  *Queue                   The MLME Queue
4656 *      \param   TimeStampHigh   The upper 32 bit of timestamp
4657 *      \param   TimeStampLow    The lower 32 bit of timestamp
4658 *      \param   Rssi                    The receiving RSSI strength
4659 *      \param   MsgLen                  The length of the message
4660 *      \param  *Msg                     The message pointer
4661 *      \return  TRUE if everything ok, FALSE otherwise (like Queue Full)
4662 *      \pre
4663 *      \post
4664
4665 IRQL = DISPATCH_LEVEL
4666
4667 */
4668BOOLEAN MlmeEnqueueForRecv(
4669        IN      PRTMP_ADAPTER   pAd,
4670        IN ULONG Wcid,
4671        IN ULONG TimeStampHigh,
4672        IN ULONG TimeStampLow,
4673        IN UCHAR Rssi0,
4674        IN UCHAR Rssi1,
4675        IN UCHAR Rssi2,
4676        IN ULONG MsgLen,
4677        IN VOID *Msg,
4678        IN UCHAR Signal)
4679{
4680        INT              Tail, Machine;
4681        PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4682        INT              MsgType;
4683        MLME_QUEUE      *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4684
4685        // Do nothing if the driver is starting halt state.
4686        // This might happen when timer already been fired before cancel timer with mlmehalt
4687        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4688        {
4689                DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4690                return FALSE;
4691        }
4692
4693        // First check the size, it MUST not exceed the mlme queue size
4694        if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4695        {
4696                DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4697                return FALSE;
4698        }
4699
4700        if (MlmeQueueFull(Queue))
4701        {
4702                return FALSE;
4703        }
4704
4705        {
4706                if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4707                {
4708                        DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4709                        return FALSE;
4710                }
4711        }
4712
4713        // OK, we got all the informations, it is time to put things into queue
4714        NdisAcquireSpinLock(&(Queue->Lock));
4715        Tail = Queue->Tail;
4716        Queue->Tail++;
4717        Queue->Num++;
4718        if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4719        {
4720                Queue->Tail = 0;
4721        }
4722        Queue->Entry[Tail].Occupied = TRUE;
4723        Queue->Entry[Tail].Machine = Machine;
4724        Queue->Entry[Tail].MsgType = MsgType;
4725        Queue->Entry[Tail].MsgLen  = MsgLen;
4726        Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4727        Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4728        Queue->Entry[Tail].Rssi0 = Rssi0;
4729        Queue->Entry[Tail].Rssi1 = Rssi1;
4730        Queue->Entry[Tail].Rssi2 = Rssi2;
4731        Queue->Entry[Tail].Signal = Signal;
4732        Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4733
4734        Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4735
4736        if (Msg != NULL)
4737        {
4738                NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4739        }
4740
4741        NdisReleaseSpinLock(&(Queue->Lock));
4742
4743        RT28XX_MLME_HANDLER(pAd);
4744
4745        return TRUE;
4746}
4747
4748
4749/*! \brief       Dequeue a message from the MLME Queue
4750 *      \param  *Queue    The MLME Queue
4751 *      \param  *Elem     The message dequeued from MLME Queue
4752 *      \return  TRUE if the Elem contains something, FALSE otherwise
4753 *      \pre
4754 *      \post
4755
4756 IRQL = DISPATCH_LEVEL
4757
4758 */
4759BOOLEAN MlmeDequeue(
4760        IN MLME_QUEUE *Queue,
4761        OUT MLME_QUEUE_ELEM **Elem)
4762{
4763        NdisAcquireSpinLock(&(Queue->Lock));
4764        *Elem = &(Queue->Entry[Queue->Head]);
4765        Queue->Num--;
4766        Queue->Head++;
4767        if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4768        {
4769                Queue->Head = 0;
4770        }
4771        NdisReleaseSpinLock(&(Queue->Lock));
4772        return TRUE;
4773}
4774
4775// IRQL = DISPATCH_LEVEL
4776VOID    MlmeRestartStateMachine(
4777        IN      PRTMP_ADAPTER   pAd)
4778{
4779#ifdef RT2860
4780        MLME_QUEUE_ELEM         *Elem = NULL;
4781#endif
4782        BOOLEAN                         Cancelled;
4783
4784        DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4785
4786#ifdef RT2860
4787        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4788        if(pAd->Mlme.bRunning)
4789        {
4790                NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4791                return;
4792        }
4793        else
4794        {
4795                pAd->Mlme.bRunning = TRUE;
4796        }
4797        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4798
4799        // Remove all Mlme queues elements
4800        while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4801        {
4802                //From message type, determine which state machine I should drive
4803                if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4804                {
4805                        // free MLME element
4806                        Elem->Occupied = FALSE;
4807                        Elem->MsgLen = 0;
4808
4809                }
4810                else {
4811                        DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4812                }
4813        }
4814#endif /* RT2860 */
4815
4816        {
4817                // Cancel all timer events
4818                // Be careful to cancel new added timer
4819                RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,         &Cancelled);
4820                RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,   &Cancelled);
4821                RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,  &Cancelled);
4822                RTMPCancelTimer(&pAd->MlmeAux.AuthTimer,           &Cancelled);
4823                RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,         &Cancelled);
4824                RTMPCancelTimer(&pAd->MlmeAux.ScanTimer,           &Cancelled);
4825        }
4826
4827        // Change back to original channel in case of doing scan
4828        AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4829        AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4830
4831        // Resume MSDU which is turned off durning scan
4832        RTMPResumeMsduTransmission(pAd);
4833
4834        {
4835                // Set all state machines back IDLE
4836                pAd->Mlme.CntlMachine.CurrState    = CNTL_IDLE;
4837                pAd->Mlme.AssocMachine.CurrState   = ASSOC_IDLE;
4838                pAd->Mlme.AuthMachine.CurrState    = AUTH_REQ_IDLE;
4839                pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4840                pAd->Mlme.SyncMachine.CurrState    = SYNC_IDLE;
4841                pAd->Mlme.ActMachine.CurrState    = ACT_IDLE;
4842        }
4843
4844#ifdef RT2860
4845        // Remove running state
4846        NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4847        pAd->Mlme.bRunning = FALSE;
4848        NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4849#endif
4850}
4851
4852/*! \brief      test if the MLME Queue is empty
4853 *      \param  *Queue    The MLME Queue
4854 *      \return TRUE if the Queue is empty, FALSE otherwise
4855 *      \pre
4856 *      \post
4857
4858 IRQL = DISPATCH_LEVEL
4859
4860 */
4861BOOLEAN MlmeQueueEmpty(
4862        IN MLME_QUEUE *Queue)
4863{
4864        BOOLEAN Ans;
4865
4866        NdisAcquireSpinLock(&(Queue->Lock));
4867        Ans = (Queue->Num == 0);
4868        NdisReleaseSpinLock(&(Queue->Lock));
4869
4870        return Ans;
4871}
4872
4873/*! \brief       test if the MLME Queue is full
4874 *      \param   *Queue          The MLME Queue
4875 *      \return  TRUE if the Queue is empty, FALSE otherwise
4876 *      \pre
4877 *      \post
4878
4879 IRQL = PASSIVE_LEVEL
4880 IRQL = DISPATCH_LEVEL
4881
4882 */
4883BOOLEAN MlmeQueueFull(
4884        IN MLME_QUEUE *Queue)
4885{
4886        BOOLEAN Ans;
4887
4888        NdisAcquireSpinLock(&(Queue->Lock));
4889        Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4890        NdisReleaseSpinLock(&(Queue->Lock));
4891
4892        return Ans;
4893}
4894
4895/*! \brief       The destructor of MLME Queue
4896 *      \param
4897 *      \return
4898 *      \pre
4899 *      \post
4900 *      \note   Clear Mlme Queue, Set Queue->Num to Zero.
4901
4902 IRQL = PASSIVE_LEVEL
4903
4904 */
4905VOID MlmeQueueDestroy(
4906        IN MLME_QUEUE *pQueue)
4907{
4908        NdisAcquireSpinLock(&(pQueue->Lock));
4909        pQueue->Num  = 0;
4910        pQueue->Head = 0;
4911        pQueue->Tail = 0;
4912        NdisReleaseSpinLock(&(pQueue->Lock));
4913        NdisFreeSpinLock(&(pQueue->Lock));
4914}
4915
4916/*! \brief       To substitute the message type if the message is coming from external
4917 *      \param  pFrame             The frame received
4918 *      \param  *Machine           The state machine
4919 *      \param  *MsgType           the message type for the state machine
4920 *      \return TRUE if the substitution is successful, FALSE otherwise
4921 *      \pre
4922 *      \post
4923
4924 IRQL = DISPATCH_LEVEL
4925
4926 */
4927BOOLEAN MsgTypeSubst(
4928        IN PRTMP_ADAPTER  pAd,
4929        IN PFRAME_802_11 pFrame,
4930        OUT INT *Machine,
4931        OUT INT *MsgType)
4932{
4933        USHORT  Seq;
4934        UCHAR   EAPType;
4935        PUCHAR  pData;
4936
4937        // Pointer to start of data frames including SNAP header
4938        pData = (PUCHAR) pFrame + LENGTH_802_11;
4939
4940        // The only data type will pass to this function is EAPOL frame
4941        if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4942        {
4943                if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4944                {
4945                        // Cisco Aironet SNAP header
4946                        *Machine = AIRONET_STATE_MACHINE;
4947                        *MsgType = MT2_AIRONET_MSG;
4948                        return (TRUE);
4949                }
4950                {
4951                        *Machine = WPA_PSK_STATE_MACHINE;
4952                        EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4953                        return(WpaMsgTypeSubst(EAPType, MsgType));
4954                }
4955        }
4956
4957        switch (pFrame->Hdr.FC.SubType)
4958        {
4959                case SUBTYPE_ASSOC_REQ:
4960                        *Machine = ASSOC_STATE_MACHINE;
4961                        *MsgType = MT2_PEER_ASSOC_REQ;
4962                        break;
4963                case SUBTYPE_ASSOC_RSP:
4964                        *Machine = ASSOC_STATE_MACHINE;
4965                        *MsgType = MT2_PEER_ASSOC_RSP;
4966                        break;
4967                case SUBTYPE_REASSOC_REQ:
4968                        *Machine = ASSOC_STATE_MACHINE;
4969                        *MsgType = MT2_PEER_REASSOC_REQ;
4970                        break;
4971                case SUBTYPE_REASSOC_RSP:
4972                        *Machine = ASSOC_STATE_MACHINE;
4973                        *MsgType = MT2_PEER_REASSOC_RSP;
4974                        break;
4975                case SUBTYPE_PROBE_REQ:
4976                        *Machine = SYNC_STATE_MACHINE;
4977                        *MsgType = MT2_PEER_PROBE_REQ;
4978                        break;
4979                case SUBTYPE_PROBE_RSP:
4980                        *Machine = SYNC_STATE_MACHINE;
4981                        *MsgType = MT2_PEER_PROBE_RSP;
4982                        break;
4983                case SUBTYPE_BEACON:
4984                        *Machine = SYNC_STATE_MACHINE;
4985                        *MsgType = MT2_PEER_BEACON;
4986                        break;
4987                case SUBTYPE_ATIM:
4988                        *Machine = SYNC_STATE_MACHINE;
4989                        *MsgType = MT2_PEER_ATIM;
4990                        break;
4991                case SUBTYPE_DISASSOC:
4992                        *Machine = ASSOC_STATE_MACHINE;
4993                        *MsgType = MT2_PEER_DISASSOC_REQ;
4994                        break;
4995                case SUBTYPE_AUTH:
4996                        // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4997                        NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4998                        if (Seq == 1 || Seq == 3)
4999                        {
5000                                *Machine = AUTH_RSP_STATE_MACHINE;
5001                                *MsgType = MT2_PEER_AUTH_ODD;
5002                        }
5003                        else if (Seq == 2 || Seq == 4)
5004                        {
5005                                *Machine = AUTH_STATE_MACHINE;
5006                                *MsgType = MT2_PEER_AUTH_EVEN;
5007                        }
5008                        else
5009                        {
5010                                return FALSE;
5011                        }
5012                        break;
5013                case SUBTYPE_DEAUTH:
5014                        *Machine = AUTH_RSP_STATE_MACHINE;
5015                        *MsgType = MT2_PEER_DEAUTH;
5016                        break;
5017                case SUBTYPE_ACTION:
5018                        *Machine = ACTION_STATE_MACHINE;
5019                        //  Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5020                        if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5021                        {
5022                                *MsgType = MT2_ACT_INVALID;
5023                        }
5024                        else
5025                        {
5026                                *MsgType = (pFrame->Octet[0]&0x7F);
5027                        }
5028                        break;
5029                default:
5030                        return FALSE;
5031                        break;
5032        }
5033
5034        return TRUE;
5035}
5036
5037// ===========================================================================================
5038// state_machine.c
5039// ===========================================================================================
5040
5041/*! \brief Initialize the state machine.
5042 *      \param *S                       pointer to the state machine
5043 *      \param  Trans           State machine transition function
5044 *      \param  StNr            number of states
5045 *      \param  MsgNr           number of messages
5046 *      \param  DefFunc         default function, when there is invalid state/message combination
5047 *      \param  InitState       initial state of the state machine
5048 *      \param  Base            StateMachine base, internal use only
5049 *      \pre p_sm should be a legal pointer
5050 *      \post
5051
5052 IRQL = PASSIVE_LEVEL
5053
5054 */
5055VOID StateMachineInit(
5056        IN STATE_MACHINE *S,
5057        IN STATE_MACHINE_FUNC Trans[],
5058        IN ULONG StNr,
5059        IN ULONG MsgNr,
5060        IN STATE_MACHINE_FUNC DefFunc,
5061        IN ULONG InitState,
5062        IN ULONG Base)
5063{
5064        ULONG i, j;
5065
5066        // set number of states and messages
5067        S->NrState = StNr;
5068        S->NrMsg   = MsgNr;
5069        S->Base    = Base;
5070
5071        S->TransFunc  = Trans;
5072
5073        // init all state transition to default function
5074        for (i = 0; i < StNr; i++)
5075        {
5076                for (j = 0; j < MsgNr; j++)
5077                {
5078                        S->TransFunc[i * MsgNr + j] = DefFunc;
5079                }
5080        }
5081
5082        // set the starting state
5083        S->CurrState = InitState;
5084}
5085
5086/*! \brief This function fills in the function pointer into the cell in the state machine
5087 *      \param *S       pointer to the state machine
5088 *      \param St       state
5089 *      \param Msg      incoming message
5090 *      \param f        the function to be executed when (state, message) combination occurs at the state machine
5091 *      \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
5092 *      \post
5093
5094 IRQL = PASSIVE_LEVEL
5095
5096 */
5097VOID StateMachineSetAction(
5098        IN STATE_MACHINE *S,
5099        IN ULONG St,
5100        IN ULONG Msg,
5101        IN STATE_MACHINE_FUNC Func)
5102{
5103        ULONG MsgIdx;
5104
5105        MsgIdx = Msg - S->Base;
5106
5107        if (St < S->NrState && MsgIdx < S->NrMsg)
5108        {
5109                // boundary checking before setting the action
5110                S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5111        }
5112}
5113
5114/*! \brief       This function does the state transition
5115 *      \param   *Adapter the NIC adapter pointer
5116 *      \param   *S       the state machine
5117 *      \param   *Elem    the message to be executed
5118 *      \return   None
5119
5120 IRQL = DISPATCH_LEVEL
5121
5122 */
5123VOID StateMachinePerformAction(
5124        IN      PRTMP_ADAPTER   pAd,
5125        IN STATE_MACHINE *S,
5126        IN MLME_QUEUE_ELEM *Elem)
5127{
5128        (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5129}
5130
5131/*
5132        ==========================================================================
5133        Description:
5134                The drop function, when machine executes this, the message is simply
5135                ignored. This function does nothing, the message is freed in
5136                StateMachinePerformAction()
5137        ==========================================================================
5138 */
5139VOID Drop(
5140        IN PRTMP_ADAPTER pAd,
5141        IN MLME_QUEUE_ELEM *Elem)
5142{
5143}
5144
5145// ===========================================================================================
5146// lfsr.c
5147// ===========================================================================================
5148
5149/*
5150        ==========================================================================
5151        Description:
5152
5153        IRQL = PASSIVE_LEVEL
5154
5155        ==========================================================================
5156 */
5157VOID LfsrInit(
5158        IN PRTMP_ADAPTER pAd,
5159        IN ULONG Seed)
5160{
5161        if (Seed == 0)
5162                pAd->Mlme.ShiftReg = 1;
5163        else
5164                pAd->Mlme.ShiftReg = Seed;
5165}
5166
5167/*
5168        ==========================================================================
5169        Description:
5170        ==========================================================================
5171 */
5172UCHAR RandomByte(
5173        IN PRTMP_ADAPTER pAd)
5174{
5175        ULONG i;
5176        UCHAR R, Result;
5177
5178        R = 0;
5179
5180        if (pAd->Mlme.ShiftReg == 0)
5181        NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5182
5183        for (i = 0; i < 8; i++)
5184        {
5185                if (pAd->Mlme.ShiftReg & 0x00000001)
5186                {
5187                        pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5188                        Result = 1;
5189                }
5190                else
5191                {
5192                        pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5193                        Result = 0;
5194                }
5195                R = (R << 1) | Result;
5196        }
5197
5198        return R;
5199}
5200
5201VOID AsicUpdateAutoFallBackTable(
5202        IN      PRTMP_ADAPTER   pAd,
5203        IN      PUCHAR                  pRateTable)
5204{
5205        UCHAR                                   i;
5206        HT_FBK_CFG0_STRUC               HtCfg0;
5207        HT_FBK_CFG1_STRUC               HtCfg1;
5208        LG_FBK_CFG0_STRUC               LgCfg0;
5209        LG_FBK_CFG1_STRUC               LgCfg1;
5210        PRTMP_TX_RATE_SWITCH    pCurrTxRate, pNextTxRate;
5211
5212        // set to initial value
5213        HtCfg0.word = 0x65432100;
5214        HtCfg1.word = 0xedcba988;
5215        LgCfg0.word = 0xedcba988;
5216        LgCfg1.word = 0x00002100;
5217
5218        pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5219        for (i = 1; i < *((PUCHAR) pRateTable); i++)
5220        {
5221                pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5222                switch (pCurrTxRate->Mode)
5223                {
5224                        case 0:         //CCK
5225                                break;
5226                        case 1:         //OFDM
5227                                {
5228                                        switch(pCurrTxRate->CurrMCS)
5229                                        {
5230                                                case 0:
5231                                                        LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5232                                                        break;
5233                                                case 1:
5234                                                        LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5235                                                        break;
5236                                                case 2:
5237                                                        LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5238                                                        break;
5239                                                case 3:
5240                                                        LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5241                                                        break;
5242                                                case 4:
5243                                                        LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5244                                                        break;
5245                                                case 5:
5246                                                        LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5247                                                        break;
5248                                                case 6:
5249                                                        LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5250                                                        break;
5251                                                case 7:
5252                                                        LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5253                                                        break;
5254                                        }
5255                                }
5256                                break;
5257                        case 2:         //HT-MIX
5258                        case 3:         //HT-GF
5259                                {
5260                                        if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5261                                        {
5262                                                switch(pCurrTxRate->CurrMCS)
5263                                                {
5264                                                        case 0:
5265                                                                HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5266                                                                break;
5267                                                        case 1:
5268                                                                HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5269                                                                break;
5270                                                        case 2:
5271                                                                HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5272                                                                break;
5273                                                        case 3:
5274                                                                HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5275                                                                break;
5276                                                        case 4:
5277                                                                HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5278                                                                break;
5279                                                        case 5:
5280                                                                HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5281                                                                break;
5282                                                        case 6:
5283                                                                HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5284                                                                break;
5285                                                        case 7:
5286                                                                HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5287                                                                break;
5288                                                        case 8:
5289                                                                HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5290                                                                break;
5291                                                        case 9:
5292                                                                HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5293                                                                break;
5294                                                        case 10:
5295                                                                HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5296                                                                break;
5297                                                        case 11:
5298                                                                HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5299                                                                break;
5300                                                        case 12:
5301                                                                HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5302                                                                break;
5303                                                        case 13:
5304                                                                HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5305                                                                break;
5306                                                        case 14:
5307                                                                HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5308                                                                break;
5309                                                        case 15:
5310                                                                HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5311                                                                break;
5312                                                        default:
5313                                                                DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5314                                                }
5315                                        }
5316                                }
5317                                break;
5318                }
5319
5320                pNextTxRate = pCurrTxRate;
5321        }
5322
5323        RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5324        RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5325        RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5326        RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5327}
5328
5329/*
5330        ========================================================================
5331
5332        Routine Description:
5333                Set MAC register value according operation mode.
5334                OperationMode AND bNonGFExist are for MM and GF Proteciton.
5335                If MM or GF mask is not set, those passing argument doesn't not take effect.
5336
5337                Operation mode meaning:
5338                = 0 : Pure HT, no preotection.
5339                = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5340                = 0x10: No Transmission in 40M is protected.
5341                = 0x11: Transmission in both 40M and 20M shall be protected
5342                if (bNonGFExist)
5343                        we should choose not to use GF. But still set correct ASIC registers.
5344        ========================================================================
5345*/
5346VOID    AsicUpdateProtect(
5347        IN              PRTMP_ADAPTER   pAd,
5348        IN              USHORT                  OperationMode,
5349        IN              UCHAR                   SetMask,
5350        IN              BOOLEAN                 bDisableBGProtect,
5351        IN              BOOLEAN                 bNonGFExist)
5352{
5353        PROT_CFG_STRUC  ProtCfg, ProtCfg4;
5354        UINT32 Protect[6];
5355        USHORT                  offset;
5356        UCHAR                   i;
5357        UINT32 MacReg = 0;
5358
5359        if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5360        {
5361                return;
5362        }
5363
5364        if (pAd->BATable.numAsOriginator)
5365        {
5366                //
5367                // enable the RTS/CTS to avoid channel collision
5368                //
5369                SetMask = ALLN_SETPROTECT;
5370                OperationMode = 8;
5371        }
5372
5373        // Config ASIC RTS threshold register
5374        RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5375        MacReg &= 0xFF0000FF;
5376
5377        // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5378        if ((
5379                        (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5380                        (pAd->CommonCfg.bAggregationCapable == TRUE))
5381            && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5382        {
5383                        MacReg |= (0x1000 << 8);
5384        }
5385        else
5386        {
5387                        MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5388        }
5389
5390        RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5391
5392        // Initial common protection settings
5393        RTMPZeroMemory(Protect, sizeof(Protect));
5394        ProtCfg4.word = 0;
5395        ProtCfg.word = 0;
5396        ProtCfg.field.TxopAllowGF40 = 1;
5397        ProtCfg.field.TxopAllowGF20 = 1;
5398        ProtCfg.field.TxopAllowMM40 = 1;
5399        ProtCfg.field.TxopAllowMM20 = 1;
5400        ProtCfg.field.TxopAllowOfdm = 1;
5401        ProtCfg.field.TxopAllowCck = 1;
5402        ProtCfg.field.RTSThEn = 1;
5403        ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5404
5405        // update PHY mode and rate
5406        if (pAd->CommonCfg.Channel > 14)
5407                ProtCfg.field.ProtectRate = 0x4000;
5408        ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5409
5410        // Handle legacy(B/G) protection
5411        if (bDisableBGProtect)
5412        {
5413                //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5414                ProtCfg.field.ProtectCtrl = 0;
5415                Protect[0] = ProtCfg.word;
5416                Protect[1] = ProtCfg.word;
5417        }
5418        else
5419        {
5420                //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5421                ProtCfg.field.ProtectCtrl = 0;                  // CCK do not need to be protected
5422                Protect[0] = ProtCfg.word;
5423                ProtCfg.field.ProtectCtrl = ASIC_CTS;   // OFDM needs using CCK to protect
5424                Protect[1] = ProtCfg.word;
5425        }
5426
5427        // Decide HT frame protection.
5428        if ((SetMask & ALLN_SETPROTECT) != 0)
5429        {
5430                switch(OperationMode)
5431                {
5432                        case 0x0:
5433                                // NO PROTECT
5434                                // 1.All STAs in the BSS are 20/40 MHz HT
5435                                // 2. in ai 20/40MHz BSS
5436                                // 3. all STAs are 20MHz in a 20MHz BSS
5437                                // Pure HT. no protection.
5438
5439                                // MM20_PROT_CFG
5440                                //      Reserved (31:27)
5441                                //      PROT_TXOP(25:20) -- 010111
5442                                //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5443                                //  PROT_CTRL(17:16) -- 00 (None)
5444                                //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
5445                                Protect[2] = 0x01744004;
5446
5447                                // MM40_PROT_CFG
5448                                //      Reserved (31:27)
5449                                //      PROT_TXOP(25:20) -- 111111
5450                                //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5451                                //  PROT_CTRL(17:16) -- 00 (None)
5452                                //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
5453                                Protect[3] = 0x03f44084;
5454
5455                                // CF20_PROT_CFG
5456                                //      Reserved (31:27)
5457                                //      PROT_TXOP(25:20) -- 010111
5458                                //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5459                                //  PROT_CTRL(17:16) -- 00 (None)
5460                                //      PROT_RATE(15:0)  -- 0x4004 (OFDM 24M)
5461                                Protect[4] = 0x01744004;
5462
5463                                // CF40_PROT_CFG
5464                                //      Reserved (31:27)
5465                                //      PROT_TXOP(25:20) -- 111111
5466                                //      PROT_NAV(19:18)  -- 01 (Short NAV protection)
5467                                //  PROT_CTRL(17:16) -- 00 (None)
5468                                //      PROT_RATE(15:0)  -- 0x4084 (duplicate OFDM 24M)
5469                                Protect[5] = 0x03f44084;
5470
5471                                if (bNonGFExist)
5472                                {
5473                                        // PROT_NAV(19:18)  -- 01 (Short NAV protectiion)
5474                                        // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5475                                        Protect[4] = 0x01754004;
5476                                        Protect[5] = 0x03f54084;
5477                                }
5478                                pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5479                                break;
5480
5481                        case 1:
5482                                // This is "HT non-member protection mode."
5483                                // If there may be non-HT STAs my BSS
5484                                ProtCfg.word = 0x01744004;      // PROT_CTRL(17:16) : 0 (None)
5485                                ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5486                                if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5487                                {
5488                                        ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
5489                                        ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5490                                }
5491                                //Assign Protection method for 20&40 MHz packets
5492                                ProtCfg.field.ProtectCtrl = ASIC_RTS;
5493                                ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5494                                ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5495                                ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5496                                Protect[2] = ProtCfg.word;
5497                                Protect[3] = ProtCfg4.word;
5498                                Protect[4] = ProtCfg.word;
5499                                Protect[5] = ProtCfg4.word;
5500                                pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5501                                break;
5502
5503                        case 2:
5504                                // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5505                                ProtCfg.word = 0x01744004;  // PROT_CTRL(17:16) : 0 (None)
5506                                ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5507
5508                                //Assign Protection method for 40MHz packets
5509                                ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5510                                ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5511                                Protect[2] = ProtCfg.word;
5512                                Protect[3] = ProtCfg4.word;
5513                                if (bNonGFExist)
5514                                {
5515                                        ProtCfg.field.ProtectCtrl = ASIC_RTS;
5516                                        ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5517                                }
5518                                Protect[4] = ProtCfg.word;
5519                                Protect[5] = ProtCfg4.word;
5520
5521                                pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5522                                break;
5523
5524                        case 3:
5525                                // HT mixed mode.        PROTECT ALL!
5526                                // Assign Rate
5527                                ProtCfg.word = 0x01744004;      //duplicaet legacy 24M. BW set 1.
5528                                ProtCfg4.word = 0x03f44084;
5529                                // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5530                                if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5531                                {
5532                                        ProtCfg.word = 0x01740003;      //ERP use Protection bit is set, use protection rate at Clause 18..
5533                                        ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5534                                }
5535                                //Assign Protection method for 20&40 MHz packets
5536                                ProtCfg.field.ProtectCtrl = ASIC_RTS;
5537                                ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5538                                ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5539                                ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5540                                Protect[2] = ProtCfg.word;
5541                                Protect[3] = ProtCfg4.word;
5542                                Protect[4] = ProtCfg.word;
5543                                Protect[5] = ProtCfg4.word;
5544                                pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5545                                break;
5546
5547                        case 8:
5548                                // Special on for Atheros problem n chip.
5549                                Protect[2] = 0x01754004;
5550                                Protect[3] = 0x03f54084;
5551                                Protect[4] = 0x01754004;
5552                                Protect[5] = 0x03f54084;
5553                                pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5554                                break;
5555                }
5556        }
5557
5558        offset = CCK_PROT_CFG;
5559        for (i = 0;i < 6;i++)
5560        {
5561                if ((SetMask & (1<< i)))
5562                {
5563                        RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5564                }
5565        }
5566}
5567
5568#ifdef RT2870
5569/*
5570        ==========================================================================
5571        Description:
5572
5573        Load RF normal operation-mode setup
5574
5575        ==========================================================================
5576 */
5577VOID RT30xxLoadRFNormalModeSetup(
5578        IN PRTMP_ADAPTER        pAd)
5579{
5580        UCHAR RFValue;
5581
5582        // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5583        RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5584        RFValue = (RFValue & (~0x0C)) | 0x31;
5585        RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5586
5587        // TX_LO2_en, RF R15 register Bit 3 to 0
5588        RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5589        RFValue &= (~0x08);
5590        RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5591
5592        // TX_LO1_en, RF R17 register Bit 3 to 0
5593        RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5594        RFValue &= (~0x08);
5595        // to fix rx long range issue
5596        if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5597        {
5598                RFValue |= 0x20;
5599        }
5600        RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5601
5602        // RX_LO1_en, RF R20 register Bit 3 to 0
5603        RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5604        RFValue &= (~0x08);
5605        RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5606
5607        // RX_LO2_en, RF R21 register Bit 3 to 0
5608        RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5609        RFValue &= (~0x08);
5610        RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5611
5612        // LDORF_VC, RF R27 register Bit 2 to 0
5613        RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5614        if ((pAd->MACVersion & 0xffff) < 0x0211)
5615                RFValue = (RFValue & (~0x77)) | 0x3;
5616        else
5617                RFValue = (RFValue & (~0x77));
5618        RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5619        /* end johnli */
5620}
5621
5622/*
5623        ==========================================================================
5624        Description:
5625
5626        Load RF sleep-mode setup
5627
5628        ==========================================================================
5629 */
5630VOID RT30xxLoadRFSleepModeSetup(
5631        IN PRTMP_ADAPTER        pAd)
5632{
5633        UCHAR RFValue;
5634        UINT32 MACValue;
5635
5636        // RF_BLOCK_en. RF R1 register Bit 0 to 0
5637        RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5638        RFValue &= (~0x01);
5639        RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5640
5641        // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5642        RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5643        RFValue &= (~0x30);
5644        RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5645
5646        // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5647        RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5648        RFValue &= (~0x0E);
5649        RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5650
5651        // RX_CTB_en, RF R21 register Bit 7 to 0
5652        RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5653        RFValue &= (~0x80);
5654        RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5655
5656        // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5657        RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5658        RFValue |= 0x77;
5659        RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5660
5661        RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5662        MACValue |= 0x1D000000;
5663        RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5664}
5665
5666/*
5667        ==========================================================================
5668        Description:
5669
5670        Reverse RF sleep-mode setup
5671
5672        ==========================================================================
5673 */
5674VOID RT30xxReverseRFSleepModeSetup(
5675        IN PRTMP_ADAPTER        pAd)
5676{
5677        UCHAR RFValue;
5678        UINT32 MACValue;
5679
5680        // RF_BLOCK_en, RF R1 register Bit 0 to 1
5681        RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5682        RFValue |= 0x01;
5683        RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5684
5685        // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5686        RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5687        RFValue |= 0x30;
5688        RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5689
5690        // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5691        RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5692        RFValue |= 0x0E;
5693        RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5694
5695        // RX_CTB_en, RF R21 register Bit 7 to 1
5696        RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5697        RFValue |= 0x80;
5698        RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5699
5700        // LDORF_VC, RF R27 register Bit 2 to 0
5701        RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5702        if ((pAd->MACVersion & 0xffff) < 0x0211)
5703                RFValue = (RFValue & (~0x77)) | 0x3;
5704        else
5705                RFValue = (RFValue & (~0x77));
5706        RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5707
5708        // RT3071 version E has fixed this issue
5709        if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5710        {
5711                // patch tx EVM issue temporarily
5712                RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5713                MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5714                RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5715        }
5716        else
5717        {
5718                RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5719                MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5720                RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5721        }
5722}
5723#endif
5724
5725/*
5726        ==========================================================================
5727        Description:
5728
5729        IRQL = PASSIVE_LEVEL
5730        IRQL = DISPATCH_LEVEL
5731
5732        ==========================================================================
5733 */
5734VOID AsicSwitchChannel(
5735                                          IN PRTMP_ADAPTER pAd,
5736        IN      UCHAR                   Channel,
5737        IN      BOOLEAN                 bScan)
5738{
5739        ULONG                   R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5740        CHAR    TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5741        UCHAR   index;
5742        UINT32  Value = 0; //BbpReg, Value;
5743        RTMP_RF_REGS *RFRegTable;
5744
5745        // Search Tx power value
5746        // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5747        // in ChannelList, so use TxPower array instead.
5748        //
5749        for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5750        {
5751                if (Channel == pAd->TxPower[index].Channel)
5752        {
5753                        TxPwer = pAd->TxPower[index].Power;
5754                        TxPwer2 = pAd->TxPower[index].Power2;
5755                        break;
5756                }
5757        }
5758
5759        if (index == MAX_NUM_OF_CHANNELS)
5760                DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5761
5762#ifdef RT2870
5763        // The RF programming sequence is difference between 3xxx and 2xxx
5764        if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && (
5765             (pAd->RfIcType == RFIC_3022) || (pAd->RfIcType == RFIC_3021) ||
5766             (pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5767        {
5768                /* modify by WY for Read RF Reg. error */
5769                UCHAR RFValue;
5770
5771                for (index = 0; index < NUM_OF_3020_CHNL; index++)
5772                {
5773                        if (Channel == FreqItems3020[index].Channel)
5774                        {
5775                                // Programming channel parameters
5776                                RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5777                                RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5778
5779                                RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5780                                RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5781                                RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5782
5783                                // Set Tx0 Power
5784                                RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5785                                RFValue = (RFValue & 0xE0) | TxPwer;
5786                                RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5787
5788                                // Set Tx1 Power
5789                                RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5790                                RFValue = (RFValue & 0xE0) | TxPwer2;
5791                                RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5792
5793                                // Tx/Rx Stream setting
5794                                RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5795                                //if (IS_RT3090(pAd))
5796                                //      RFValue |= 0x01; // Enable RF block.
5797                                RFValue &= 0x03;        //clear bit[7~2]
5798                                if (pAd->Antenna.field.TxPath == 1)
5799                                        RFValue |= 0xA0;
5800                                else if (pAd->Antenna.field.TxPath == 2)
5801                                        RFValue |= 0x80;
5802                                if (pAd->Antenna.field.RxPath == 1)
5803                                        RFValue |= 0x50;
5804                                else if (pAd->Antenna.field.RxPath == 2)
5805                                        RFValue |= 0x40;
5806                                RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5807
5808                                // Set RF offset
5809                                RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5810                                RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5811                                RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5812
5813                                // Set BW
5814                                if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5815                                {
5816                                        RFValue = pAd->Mlme.CaliBW40RfR24;
5817                                        //DISABLE_11N_CHECK(pAd);
5818                                }
5819                                else
5820                                {
5821                                        RFValue = pAd->Mlme.CaliBW20RfR24;
5822                                }
5823                                RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5824                                RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5825
5826                                // Enable RF tuning
5827                                RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5828                                RFValue = RFValue | 0x1;
5829                                RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5830
5831                                // latch channel for future usage.
5832                                pAd->LatchRfRegs.Channel = Channel;
5833
5834                                DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5835                                        Channel,
5836                                        pAd->RfIcType,
5837                                        TxPwer,
5838                                        TxPwer2,
5839                                        pAd->Antenna.field.TxPath,
5840                                        FreqItems3020[index].N,
5841                                        FreqItems3020[index].K,
5842                                        FreqItems3020[index].R));
5843                                break;
5844                        }
5845                }
5846
5847                DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5848                        Channel,
5849                        pAd->RfIcType,
5850                        TxPwer,
5851                        TxPwer2,
5852                        pAd->Antenna.field.TxPath,
5853                        FreqItems3020[index].N,
5854                        FreqItems3020[index].K,
5855                        FreqItems3020[index].R));
5856        }
5857        else
5858#endif // RT2870 //
5859        {
5860                RFRegTable = RF2850RegTable;
5861
5862                switch (pAd->RfIcType)
5863                {
5864                        case RFIC_2820:
5865                        case RFIC_2850:
5866                        case RFIC_2720:
5867                        case RFIC_2750:
5868
5869                        for (index = 0; index < NUM_OF_2850_CHNL; index++)
5870                        {
5871                                if (Channel == RFRegTable[index].Channel)
5872                                {
5873                                        R2 = RFRegTable[index].R2;
5874                                        if (pAd->Antenna.field.TxPath == 1)
5875                                        {
5876                                                R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
5877                                        }
5878
5879                                        if (pAd->Antenna.field.RxPath == 2)
5880                                        {
5881                                                R2 |= 0x40;     // write 1 to off Rxpath.
5882                                        }
5883                                        else if (pAd->Antenna.field.RxPath == 1)
5884                                        {
5885                                                R2 |= 0x20040;  // write 1 to off RxPath
5886                                        }
5887
5888                                        if (Channel > 14)
5889                                        {
5890                                                // initialize R3, R4
5891                                                R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5892                                                R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5893
5894                                                // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5895                                                // R3
5896                                                if ((TxPwer >= -7) && (TxPwer < 0))
5897                                                {
5898                                                        TxPwer = (7+TxPwer);
5899                                                        TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5900                                                        R3 |= (TxPwer << 10);
5901                                                        DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5902                                                }
5903                                                else
5904                                                {
5905                                                        TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5906                                                        R3 |= (TxPwer << 10) | (1 << 9);
5907                                                }
5908
5909                                                // R4
5910                                                if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5911                                                {
5912                                                        TxPwer2 = (7+TxPwer2);
5913                                                        TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5914                                                        R4 |= (TxPwer2 << 7);
5915                                                        DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5916                                                }
5917                                                else
5918                                                {
5919                                                        TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5920                                                        R4 |= (TxPwer2 << 7) | (1 << 6);
5921                                                }
5922                                        }
5923                                        else
5924                                        {
5925                                                R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5926                                        R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5927                                        }
5928
5929                                        // Based on BBP current mode before changing RF channel.
5930                                        if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5931                                        {
5932                                                R4 |=0x200000;
5933                                        }
5934
5935                                        // Update variables
5936                                        pAd->LatchRfRegs.Channel = Channel;
5937                                        pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5938                                        pAd->LatchRfRegs.R2 = R2;
5939                                        pAd->LatchRfRegs.R3 = R3;
5940                                        pAd->LatchRfRegs.R4 = R4;
5941
5942                                        // Set RF value 1's set R3[bit2] = [0]
5943                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5944                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5945                                        RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5946                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5947
5948                                        RTMPusecDelay(200);
5949
5950                                        // Set RF value 2's set R3[bit2] = [1]
5951                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5952                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5953                                        RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5954                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5955
5956                                        RTMPusecDelay(200);
5957
5958                                        // Set RF value 3's set R3[bit2] = [0]
5959                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5960                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5961                                        RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5962                                        RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5963
5964                                        break;
5965                                }
5966                        }
5967                        break;
5968
5969                        default:
5970                        break;
5971                }
5972        }
5973
5974        // Change BBP setting during siwtch from a->g, g->a
5975        if (Channel <= 14)
5976        {
5977            ULONG       TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5978
5979                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5980                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5981                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5982                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd)));    // According the Rory's suggestion to solve the middle range issue.
5983                //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5984
5985                // Rx High power VGA offset for LNA select
5986            if (pAd->NicConfig2.field.ExternalLNAForG)
5987            {
5988                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5989                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5990            }
5991            else
5992            {
5993                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5994                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5995            }
5996
5997                // 5G band selection PIN, bit1 and bit2 are complement
5998                RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5999                Value &= (~0x6);
6000                Value |= (0x04);
6001                RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6002
6003        // Turn off unused PA or LNA when only 1T or 1R
6004                if (pAd->Antenna.field.TxPath == 1)
6005                {
6006                        TxPinCfg &= 0xFFFFFFF3;
6007                }
6008                if (pAd->Antenna.field.RxPath == 1)
6009                {
6010                        TxPinCfg &= 0xFFFFF3FF;
6011                }
6012
6013                RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6014        }
6015        else
6016        {
6017            ULONG       TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6018
6019                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6020                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6021                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6022                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd)));   // According the Rory's suggestion to solve the middle range issue.
6023                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6024
6025                // Rx High power VGA offset for LNA select
6026                if (pAd->NicConfig2.field.ExternalLNAForA)
6027                {
6028                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6029                }
6030                else
6031                {
6032                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6033                }
6034
6035                // 5G band selection PIN, bit1 and bit2 are complement
6036                RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6037                Value &= (~0x6);
6038                Value |= (0x02);
6039                RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6040
6041        // Turn off unused PA or LNA when only 1T or 1R
6042                if (pAd->Antenna.field.TxPath == 1)
6043                {
6044                        TxPinCfg &= 0xFFFFFFF3;
6045        }
6046                if (pAd->Antenna.field.RxPath == 1)
6047                {
6048                        TxPinCfg &= 0xFFFFF3FF;
6049        }
6050
6051                RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6052        }
6053
6054    // R66 should be set according to Channel and use 20MHz when scanning
6055        //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6056        if (bScan)
6057                RTMPSetAGCInitValue(pAd, BW_20);
6058        else
6059                RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6060
6061        //
6062        // On 11A, We should delay and wait RF/BBP to be stable
6063        // and the appropriate time should be 1000 micro seconds
6064        // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6065        //
6066        RTMPusecDelay(1000);
6067
6068        DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
6069                                                          Channel,
6070                                                          pAd->RfIcType,
6071                                                          (R3 & 0x00003e00) >> 9,
6072                                                          (R4 & 0x000007c0) >> 6,
6073                                                          pAd->Antenna.field.TxPath,
6074                                                          pAd->LatchRfRegs.R1,
6075                                                          pAd->LatchRfRegs.R2,
6076                                                          pAd->LatchRfRegs.R3,
6077                                                          pAd->LatchRfRegs.R4));
6078}
6079
6080/*
6081        ==========================================================================
6082        Description:
6083                This function is required for 2421 only, and should not be used during
6084                site survey. It's only required after NIC decided to stay at a channel
6085                for a longer period.
6086                When this function is called, it's always after AsicSwitchChannel().
6087
6088        IRQL = PASSIVE_LEVEL
6089        IRQL = DISPATCH_LEVEL
6090
6091        ==========================================================================
6092 */
6093VOID AsicLockChannel(
6094        IN PRTMP_ADAPTER pAd,
6095        IN UCHAR Channel)
6096{
6097}
6098
6099VOID AsicRfTuningExec(
6100        IN PVOID SystemSpecific1,
6101        IN PVOID FunctionContext,
6102        IN PVOID SystemSpecific2,
6103        IN PVOID SystemSpecific3)
6104{
6105}
6106
6107/*
6108        ==========================================================================
6109        Description:
6110                Gives CCK TX rate 2 more dB TX power.
6111                This routine works only in LINK UP in INFRASTRUCTURE mode.
6112
6113                calculate desired Tx power in RF R3.Tx0~5,      should consider -
6114                0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6115                1. TxPowerPercentage
6116                2. auto calibration based on TSSI feedback
6117                3. extra 2 db for CCK
6118                4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6119
6120        NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6121                it should be called AFTER MlmeDynamicTxRatSwitching()
6122        ==========================================================================
6123 */
6124VOID AsicAdjustTxPower(
6125        IN PRTMP_ADAPTER pAd)
6126{
6127        INT                     i, j;
6128        CHAR            DeltaPwr = 0;
6129        BOOLEAN         bAutoTxAgc = FALSE;
6130        UCHAR           TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6131        UCHAR           BbpR1 = 0, BbpR49 = 0, idx;
6132        PCHAR           pTxAgcCompensate;
6133        ULONG           TxPwr[5];
6134        CHAR            Value;
6135
6136#ifdef RT2860
6137        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6138                || (pAd->bPCIclkOff == TRUE)
6139                || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6140                || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6141                return;
6142#endif
6143
6144        if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6145        {
6146                if (pAd->CommonCfg.CentralChannel > 14)
6147                {
6148                        TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6149                        TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6150                        TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6151                        TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6152                        TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6153                }
6154                else
6155                {
6156                        TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6157                        TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6158                        TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6159                        TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6160                        TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6161                }
6162        }
6163        else
6164        {
6165                if (pAd->CommonCfg.Channel > 14)
6166                {
6167                        TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6168                        TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6169                        TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6170                        TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6171                        TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6172                }
6173                else
6174                {
6175                        TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6176                        TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6177                        TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6178                        TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6179                        TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6180                }
6181        }
6182
6183        // TX power compensation for temperature variation based on TSSI. try every 4 second
6184        if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6185        {
6186                if (pAd->CommonCfg.Channel <= 14)
6187                {
6188                        /* bg channel */
6189                        bAutoTxAgc         = pAd->bAutoTxAgcG;
6190                        TssiRef            = pAd->TssiRefG;
6191                        pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6192                        pTssiPlusBoundary  = &pAd->TssiPlusBoundaryG[0];
6193                        TxAgcStep          = pAd->TxAgcStepG;
6194                        pTxAgcCompensate   = &pAd->TxAgcCompensateG;
6195                }
6196                else
6197                {
6198                        /* a channel */
6199                        bAutoTxAgc         = pAd->bAutoTxAgcA;
6200                        TssiRef            = pAd->TssiRefA;
6201                        pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6202                        pTssiPlusBoundary  = &pAd->TssiPlusBoundaryA[0];
6203                        TxAgcStep          = pAd->TxAgcStepA;
6204                        pTxAgcCompensate   = &pAd->TxAgcCompensateA;
6205                }
6206
6207                if (bAutoTxAgc)
6208                {
6209                        /* BbpR1 is unsigned char */
6210                        RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6211
6212                        /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6213                        /* compensate: +4     +3   +2   +1    0   -1   -2   -3   -4 * steps */
6214                        /* step value is defined in pAd->TxAgcStepG for tx power value */
6215
6216                        /* [4]+1+[4]   p4     p3   p2   p1   o1   m1   m2   m3   m4 */
6217                        /* ex:         0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6218                           above value are examined in mass factory production */
6219                        /*             [4]    [3]  [2]  [1]  [0]  [1]  [2]  [3]  [4] */
6220
6221                        /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6222                        /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6223                        /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6224
6225                        if (BbpR49 > pTssiMinusBoundary[1])
6226                        {
6227                                // Reading is larger than the reference value
6228                                // check for how large we need to decrease the Tx power
6229                                for (idx = 1; idx < 5; idx++)
6230                                {
6231                                        if (BbpR49 <= pTssiMinusBoundary[idx])  // Found the range
6232                                                break;
6233                                }
6234                                // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6235                                *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6236
6237                                DeltaPwr += (*pTxAgcCompensate);
6238                                DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6239                                        BbpR49, TssiRef, TxAgcStep, idx-1));
6240                        }
6241                        else if (BbpR49 < pTssiPlusBoundary[1])
6242                        {
6243                                // Reading is smaller than the reference value
6244                                // check for how large we need to increase the Tx power
6245                                for (idx = 1; idx < 5; idx++)
6246                                {
6247                                        if (BbpR49 >= pTssiPlusBoundary[idx])   // Found the range
6248                                                break;
6249                                }
6250                                // The index is the step we should increase, idx = 0 means there is nothing to compensate
6251                                *pTxAgcCompensate = TxAgcStep * (idx-1);
6252                                DeltaPwr += (*pTxAgcCompensate);
6253                                DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6254                                        BbpR49, TssiRef, TxAgcStep, idx-1));
6255                        }
6256                        else
6257                        {
6258                                *pTxAgcCompensate = 0;
6259                                DBGPRINT(RT_DEBUG_TRACE, ("   Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6260                                        BbpR49, TssiRef, TxAgcStep, 0));
6261                        }
6262                }
6263        }
6264        else
6265        {
6266                if (pAd->CommonCfg.Channel <= 14)
6267                {
6268                        bAutoTxAgc         = pAd->bAutoTxAgcG;
6269                        pTxAgcCompensate   = &pAd->TxAgcCompensateG;
6270                }
6271                else
6272                {
6273                        bAutoTxAgc         = pAd->bAutoTxAgcA;
6274                        pTxAgcCompensate   = &pAd->TxAgcCompensateA;
6275                }
6276
6277                if (bAutoTxAgc)
6278                        DeltaPwr += (*pTxAgcCompensate);
6279        }
6280
6281        RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6282        BbpR1 &= 0xFC;
6283
6284        /* calculate delta power based on the percentage specified from UI */
6285        // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6286        // We lower TX power here according to the percentage specified from UI
6287        if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff)       // AUTO TX POWER control
6288                ;
6289        else if (pAd->CommonCfg.TxPowerPercentage > 90)  // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6290                ;
6291        else if (pAd->CommonCfg.TxPowerPercentage > 60)  // 61 ~ 90%, treat as 75% in terms of mW               // DeltaPwr -= 1;
6292        {
6293                DeltaPwr -= 1;
6294        }
6295        else if (pAd->CommonCfg.TxPowerPercentage > 30)  // 31 ~ 60%, treat as 50% in terms of mW               // DeltaPwr -= 3;
6296        {
6297                DeltaPwr -= 3;
6298        }
6299        else if (pAd->CommonCfg.TxPowerPercentage > 15)  // 16 ~ 30%, treat as 25% in terms of mW               // DeltaPwr -= 6;
6300        {
6301                BbpR1 |= 0x01;
6302        }
6303        else if (pAd->CommonCfg.TxPowerPercentage > 9)   // 10 ~ 15%, treat as 12.5% in terms of mW             // DeltaPwr -= 9;
6304        {
6305                BbpR1 |= 0x01;
6306                DeltaPwr -= 3;
6307        }
6308        else                                           // 0 ~ 9 %, treat as MIN(~3%) in terms of mW             // DeltaPwr -= 12;
6309        {
6310                BbpR1 |= 0x02;
6311        }
6312
6313        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6314
6315        /* reset different new tx power for different TX rate */
6316        for(i=0; i<5; i++)
6317        {
6318                if (TxPwr[i] != 0xffffffff)
6319                {
6320                        for (j=0; j<8; j++)
6321                        {
6322                                Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6323
6324                                if ((Value + DeltaPwr) < 0)
6325                                {
6326                                        Value = 0; /* min */
6327                                }
6328                                else if ((Value + DeltaPwr) > 0xF)
6329                                {
6330                                        Value = 0xF; /* max */
6331                                }
6332                                else
6333                                {
6334                                        Value += DeltaPwr; /* temperature compensation */
6335                                }
6336
6337                                /* fill new value to CSR offset */
6338                                TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6339                        }
6340
6341                        /* write tx power value to CSR */
6342                        /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6343                                                                                        TX power for OFDM 6M/9M
6344                                                                                        TX power for CCK5.5M/11M
6345                                                                                        TX power for CCK1M/2M */
6346                        /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6347                        RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6348                }
6349        }
6350
6351}
6352
6353/*
6354        ==========================================================================
6355        Description:
6356                put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6357                automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6358                the wakeup timer timeout. Driver has to issue a separate command to wake
6359                PHY up.
6360
6361        IRQL = DISPATCH_LEVEL
6362
6363        ==========================================================================
6364 */
6365VOID AsicSleepThenAutoWakeup(
6366        IN PRTMP_ADAPTER pAd,
6367        IN USHORT TbttNumToNextWakeUp)
6368{
6369    RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6370}
6371
6372/*
6373        ==========================================================================
6374        Description:
6375                AsicForceWakeup() is used whenever manual wakeup is required
6376                AsicForceSleep() should only be used when not in INFRA BSS. When
6377                in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6378        ==========================================================================
6379 */
6380VOID AsicForceSleep(
6381        IN PRTMP_ADAPTER pAd)
6382{
6383
6384}
6385
6386/*
6387        ==========================================================================
6388        Description:
6389                AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6390                expired.
6391
6392        IRQL = PASSIVE_LEVEL
6393        IRQL = DISPATCH_LEVEL
6394        ==========================================================================
6395 */
6396VOID AsicForceWakeup(
6397        IN PRTMP_ADAPTER pAd,
6398#ifdef RT2860
6399        IN UCHAR         Level)
6400#endif
6401#ifdef RT2870
6402        IN BOOLEAN    bFromTx)
6403#endif
6404{
6405    DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6406#ifdef RT2860
6407    RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6408#endif
6409#ifdef RT2870
6410    RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6411#endif
6412}
6413
6414/*
6415        ==========================================================================
6416        Description:
6417                Set My BSSID
6418
6419        IRQL = DISPATCH_LEVEL
6420
6421        ==========================================================================
6422 */
6423VOID AsicSetBssid(
6424        IN PRTMP_ADAPTER pAd,
6425        IN PUCHAR pBssid)
6426{
6427        ULONG             Addr4;
6428        DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6429                pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6430
6431        Addr4 = (ULONG)(pBssid[0])               |
6432                        (ULONG)(pBssid[1] << 8)  |
6433                        (ULONG)(pBssid[2] << 16) |
6434                        (ULONG)(pBssid[3] << 24);
6435        RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6436
6437        Addr4 = 0;
6438        // always one BSSID in STA mode
6439        Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6440
6441        RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6442}
6443
6444VOID AsicSetMcastWC(
6445        IN PRTMP_ADAPTER pAd)
6446{
6447        MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6448        USHORT          offset;
6449
6450        pEntry->Sst        = SST_ASSOC;
6451        pEntry->Aid        = MCAST_WCID;        // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6452        pEntry->PsMode     = PWR_ACTIVE;
6453        pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6454        offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6455}
6456
6457/*
6458        ==========================================================================
6459        Description:
6460
6461        IRQL = DISPATCH_LEVEL
6462
6463        ==========================================================================
6464 */
6465VOID AsicDelWcidTab(
6466        IN PRTMP_ADAPTER pAd,
6467        IN UCHAR        Wcid)
6468{
6469        ULONG             Addr0 = 0x0, Addr1 = 0x0;
6470        ULONG           offset;
6471
6472        DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6473        offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6474        RTMP_IO_WRITE32(pAd, offset, Addr0);
6475        offset += 4;
6476        RTMP_IO_WRITE32(pAd, offset, Addr1);
6477}
6478
6479/*
6480        ==========================================================================
6481        Description:
6482
6483        IRQL = DISPATCH_LEVEL
6484
6485        ==========================================================================
6486 */
6487VOID AsicEnableRDG(
6488        IN PRTMP_ADAPTER pAd)
6489{
6490        TX_LINK_CFG_STRUC       TxLinkCfg;
6491        UINT32                          Data = 0;
6492
6493        RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6494        TxLinkCfg.field.TxRDGEn = 1;
6495        RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6496
6497        RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6498        Data  &= 0xFFFFFF00;
6499        Data  |= 0x80;
6500        RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6501
6502        //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6503}
6504
6505/*
6506        ==========================================================================
6507        Description:
6508
6509        IRQL = DISPATCH_LEVEL
6510
6511        ==========================================================================
6512 */
6513VOID AsicDisableRDG(
6514        IN PRTMP_ADAPTER pAd)
6515{
6516        TX_LINK_CFG_STRUC       TxLinkCfg;
6517        UINT32                          Data = 0;
6518
6519
6520        RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6521        TxLinkCfg.field.TxRDGEn = 0;
6522        RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6523
6524        RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6525
6526        Data  &= 0xFFFFFF00;
6527        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6528                && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6529        )
6530        {
6531                // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6532                if (pAd->CommonCfg.bEnableTxBurst)
6533                        Data |= 0x20;
6534        }
6535        RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6536}
6537
6538/*
6539        ==========================================================================
6540        Description:
6541
6542        IRQL = PASSIVE_LEVEL
6543        IRQL = DISPATCH_LEVEL
6544
6545        ==========================================================================
6546 */
6547VOID AsicDisableSync(
6548        IN PRTMP_ADAPTER pAd)
6549{
6550        BCN_TIME_CFG_STRUC csr;
6551
6552        DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6553
6554        // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6555        //                        that NIC will never wakes up because TSF stops and no more
6556        //                        TBTT interrupts
6557        pAd->TbttTickCount = 0;
6558        RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6559        csr.field.bBeaconGen = 0;
6560        csr.field.bTBTTEnable = 0;
6561        csr.field.TsfSyncMode = 0;
6562        csr.field.bTsfTicking = 0;
6563        RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6564
6565}
6566
6567/*
6568        ==========================================================================
6569        Description:
6570
6571        IRQL = DISPATCH_LEVEL
6572
6573        ==========================================================================
6574 */
6575VOID AsicEnableBssSync(
6576        IN PRTMP_ADAPTER pAd)
6577{
6578        BCN_TIME_CFG_STRUC csr;
6579
6580        DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6581
6582        RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6583
6584        {
6585                csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6586                csr.field.bTsfTicking = 1;
6587                csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6588                csr.field.bBeaconGen  = 0; // do NOT generate BEACON
6589                csr.field.bTBTTEnable = 1;
6590        }
6591
6592        RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6593}
6594
6595/*
6596        ==========================================================================
6597        Description:
6598        Note:
6599                BEACON frame in shared memory should be built ok before this routine
6600                can be called. Otherwise, a garbage frame maybe transmitted out every
6601                Beacon period.
6602
6603        IRQL = DISPATCH_LEVEL
6604
6605        ==========================================================================
6606 */
6607VOID AsicEnableIbssSync(
6608        IN PRTMP_ADAPTER pAd)
6609{
6610        BCN_TIME_CFG_STRUC csr9;
6611        PUCHAR                  ptr;
6612        UINT i;
6613
6614        DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6615
6616        RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6617        csr9.field.bBeaconGen = 0;
6618        csr9.field.bTBTTEnable = 0;
6619        csr9.field.bTsfTicking = 0;
6620        RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6621
6622#ifdef RT2860
6623        // move BEACON TXD and frame content to on-chip memory
6624        ptr = (PUCHAR)&pAd->BeaconTxWI;
6625        for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
6626        {
6627                UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6628                RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6629                ptr += 4;
6630        }
6631
6632        // start right after the 16-byte TXWI field
6633        ptr = pAd->BeaconBuf;
6634        for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6635        {
6636                UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6637                RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6638                ptr +=4;
6639        }
6640#endif
6641#ifdef RT2870
6642        // move BEACON TXD and frame content to on-chip memory
6643        ptr = (PUCHAR)&pAd->BeaconTxWI;
6644        for (i=0; i<TXWI_SIZE; i+=2)  // 16-byte TXWI field
6645        {
6646                RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6647                ptr += 2;
6648        }
6649
6650        // start right after the 16-byte TXWI field
6651        ptr = pAd->BeaconBuf;
6652        for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6653        {
6654                RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6655                ptr +=2;
6656        }
6657#endif // RT2870 //
6658
6659        // start sending BEACON
6660        csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6661        csr9.field.bTsfTicking = 1;
6662        csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6663        csr9.field.bTBTTEnable = 1;
6664        csr9.field.bBeaconGen = 1;
6665        RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6666}
6667
6668/*
6669        ==========================================================================
6670        Description:
6671
6672        IRQL = PASSIVE_LEVEL
6673        IRQL = DISPATCH_LEVEL
6674
6675        ==========================================================================
6676 */
6677VOID AsicSetEdcaParm(
6678        IN PRTMP_ADAPTER pAd,
6679        IN PEDCA_PARM    pEdcaParm)
6680{
6681        EDCA_AC_CFG_STRUC   Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6682        AC_TXOP_CSR0_STRUC csr0;
6683        AC_TXOP_CSR1_STRUC csr1;
6684        AIFSN_CSR_STRUC    AifsnCsr;
6685        CWMIN_CSR_STRUC    CwminCsr;
6686        CWMAX_CSR_STRUC    CwmaxCsr;
6687        int i;
6688
6689        Ac0Cfg.word = 0;
6690        Ac1Cfg.word = 0;
6691        Ac2Cfg.word = 0;
6692        Ac3Cfg.word = 0;
6693        if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6694        {
6695                DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6696                OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6697                for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6698                {
6699                        if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6700                                CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6701                }
6702
6703                //========================================================
6704                //      MAC Register has a copy .
6705                //========================================================
6706                if( pAd->CommonCfg.bEnableTxBurst )
6707                {
6708                        // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6709                        Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6710                }
6711                else
6712                        Ac0Cfg.field.AcTxop = 0;        // QID_AC_BE
6713                Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6714                Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6715                Ac0Cfg.field.Aifsn = 2;
6716                RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6717
6718                Ac1Cfg.field.AcTxop = 0;        // QID_AC_BK
6719                Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6720                Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6721                Ac1Cfg.field.Aifsn = 2;
6722                RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6723
6724                if (pAd->CommonCfg.PhyMode == PHY_11B)
6725                {
6726                        Ac2Cfg.field.AcTxop = 192;      // AC_VI: 192*32us ~= 6ms
6727                        Ac3Cfg.field.AcTxop = 96;       // AC_VO: 96*32us  ~= 3ms
6728                }
6729                else
6730                {
6731                        Ac2Cfg.field.AcTxop = 96;       // AC_VI: 96*32us ~= 3ms
6732                        Ac3Cfg.field.AcTxop = 48;       // AC_VO: 48*32us ~= 1.5ms
6733                }
6734                Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6735                Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6736                Ac2Cfg.field.Aifsn = 2;
6737                RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6738                Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6739                Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6740                Ac3Cfg.field.Aifsn = 2;
6741                RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6742
6743                //========================================================
6744                //      DMA Register has a copy too.
6745                //========================================================
6746                csr0.field.Ac0Txop = 0;         // QID_AC_BE
6747                csr0.field.Ac1Txop = 0;         // QID_AC_BK
6748                RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6749                if (pAd->CommonCfg.PhyMode == PHY_11B)
6750                {
6751                        csr1.field.Ac2Txop = 192;               // AC_VI: 192*32us ~= 6ms
6752                        csr1.field.Ac3Txop = 96;                // AC_VO: 96*32us  ~= 3ms
6753                }
6754                else
6755                {
6756                        csr1.field.Ac2Txop = 96;                // AC_VI: 96*32us ~= 3ms
6757                        csr1.field.Ac3Txop = 48;                // AC_VO: 48*32us ~= 1.5ms
6758                }
6759                RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6760
6761                CwminCsr.word = 0;
6762                CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6763                CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6764                CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6765                CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6766                RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6767
6768                CwmaxCsr.word = 0;
6769                CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6770                CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6771                CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6772                CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6773                RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6774
6775                RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6776
6777                NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6778        }
6779        else
6780        {
6781                OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6782                //========================================================
6783                //      MAC Register has a copy.
6784                //========================================================
6785                //
6786                // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6787                // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6788                //
6789                //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6790
6791                Ac0Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BE];
6792                Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6793                Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6794                Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6795
6796                Ac1Cfg.field.AcTxop =  pEdcaParm->Txop[QID_AC_BK];
6797                Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6798                Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6799                Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6800
6801                Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6802                Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6803                Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6804                Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6805
6806                {
6807                        // Tuning for Wi-Fi WMM S06
6808                        if (pAd->CommonCfg.bWiFiTest &&
6809                                pEdcaParm->Aifsn[QID_AC_VI] == 10)
6810                                Ac2Cfg.field.Aifsn -= 1;
6811
6812                        // Tuning for TGn Wi-Fi 5.2.32
6813                        // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6814                        if (STA_TGN_WIFI_ON(pAd) &&
6815                                pEdcaParm->Aifsn[QID_AC_VI] == 10)
6816                        {
6817                                Ac0Cfg.field.Aifsn = 3;
6818                                Ac2Cfg.field.AcTxop = 5;
6819                        }
6820
6821#ifdef RT2870
6822                        if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6823                        {
6824                                // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6825                                Ac2Cfg.field.Aifsn = 5;
6826                        }
6827#endif
6828                }
6829
6830                Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6831                Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6832                Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6833                Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6834
6835//#ifdef WIFI_TEST
6836                if (pAd->CommonCfg.bWiFiTest)
6837                {
6838                        if (Ac3Cfg.field.AcTxop == 102)
6839                        {
6840                        Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6841                                Ac0Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6842                        Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6843                                Ac1Cfg.field.Aifsn  = pEdcaParm->Aifsn[QID_AC_BK];
6844                        Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6845                        } /* End of if */
6846                }
6847//#endif // WIFI_TEST //
6848
6849                RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6850                RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6851                RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6852                RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6853
6854
6855                //========================================================
6856                //      DMA Register has a copy too.
6857                //========================================================
6858                csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6859                csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6860                RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6861
6862                csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6863                csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6864                RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6865
6866                CwminCsr.word = 0;
6867                CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6868                CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6869                CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6870
6871                CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6872
6873                RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6874
6875                CwmaxCsr.word = 0;
6876                CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6877                CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6878                CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6879                CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6880                RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6881
6882                AifsnCsr.word = 0;
6883                AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6884                AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6885                AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6886
6887                {
6888                        // Tuning for Wi-Fi WMM S06
6889                        if (pAd->CommonCfg.bWiFiTest &&
6890                                pEdcaParm->Aifsn[QID_AC_VI] == 10)
6891                                AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6892
6893                        // Tuning for TGn Wi-Fi 5.2.32
6894                        // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
6895                        if (STA_TGN_WIFI_ON(pAd) &&
6896                                pEdcaParm->Aifsn[QID_AC_VI] == 10)
6897                        {
6898                                AifsnCsr.field.Aifsn0 = 3;
6899                                AifsnCsr.field.Aifsn2 = 7;
6900                        }
6901#ifdef RT2870
6902                        if (INFRA_ON(pAd))
6903                                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6904#endif
6905                }
6906
6907                AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6908#ifdef RT2870
6909                if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6910                        AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
6911#endif
6912                RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6913
6914                NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6915                if (!ADHOC_ON(pAd))
6916                {
6917                        DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax  TXOP(us)  ACM\n", pEdcaParm->EdcaUpdateCount));
6918                        DBGPRINT(RT_DEBUG_TRACE,("     AC_BE      %2d     %2d     %2d      %4d     %d\n",
6919                                                                         pEdcaParm->Aifsn[0],
6920                                                                         pEdcaParm->Cwmin[0],
6921                                                                         pEdcaParm->Cwmax[0],
6922                                                                         pEdcaParm->Txop[0]<<5,
6923                                                                         pEdcaParm->bACM[0]));
6924                        DBGPRINT(RT_DEBUG_TRACE,("     AC_BK      %2d     %2d     %2d      %4d     %d\n",
6925                                                                         pEdcaParm->Aifsn[1],
6926                                                                         pEdcaParm->Cwmin[1],
6927                                                                         pEdcaParm->Cwmax[1],
6928                                                                         pEdcaParm->Txop[1]<<5,
6929                                                                         pEdcaParm->bACM[1]));
6930                        DBGPRINT(RT_DEBUG_TRACE,("     AC_VI      %2d     %2d     %2d      %4d     %d\n",
6931                                                                         pEdcaParm->Aifsn[2],
6932                                                                         pEdcaParm->Cwmin[2],
6933                                                                         pEdcaParm->Cwmax[2],
6934                                                                         pEdcaParm->Txop[2]<<5,
6935                                                                         pEdcaParm->bACM[2]));
6936                        DBGPRINT(RT_DEBUG_TRACE,("     AC_VO      %2d     %2d     %2d      %4d     %d\n",
6937                                                                         pEdcaParm->Aifsn[3],
6938                                                                         pEdcaParm->Cwmin[3],
6939                                                                         pEdcaParm->Cwmax[3],
6940                                                                         pEdcaParm->Txop[3]<<5,
6941                                                                         pEdcaParm->bACM[3]));
6942                }
6943        }
6944}
6945
6946/*
6947        ==========================================================================
6948        Description:
6949
6950        IRQL = PASSIVE_LEVEL
6951        IRQL = DISPATCH_LEVEL
6952
6953        ==========================================================================
6954 */
6955VOID    AsicSetSlotTime(
6956        IN PRTMP_ADAPTER pAd,
6957        IN BOOLEAN bUseShortSlotTime)
6958{
6959        ULONG   SlotTime;
6960        UINT32  RegValue = 0;
6961
6962        if (pAd->CommonCfg.Channel > 14)
6963                bUseShortSlotTime = TRUE;
6964
6965        if (bUseShortSlotTime)
6966                OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6967        else
6968                OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6969
6970        SlotTime = (bUseShortSlotTime)? 9 : 20;
6971
6972        {
6973                // force using short SLOT time for FAE to demo performance when TxBurst is ON
6974                if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6975                        || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6976                        )
6977                {
6978                        // In this case, we will think it is doing Wi-Fi test
6979                        // And we will not set to short slot when bEnableTxBurst is TRUE.
6980                }
6981                else if (pAd->CommonCfg.bEnableTxBurst)
6982                        SlotTime = 9;
6983        }
6984
6985        //
6986        // For some reasons, always set it to short slot time.
6987        //
6988        // ToDo: Should consider capability with 11B
6989        //
6990        if (pAd->StaCfg.BssType == BSS_ADHOC)
6991                SlotTime = 20;
6992
6993        RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6994        RegValue = RegValue & 0xFFFFFF00;
6995
6996        RegValue |= SlotTime;
6997
6998        RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6999}
7000
7001/*
7002        ========================================================================
7003        Description:
7004                Add Shared key information into ASIC.
7005                Update shared key, TxMic and RxMic to Asic Shared key table
7006                Update its cipherAlg to Asic Shared key Mode.
7007
7008    Return:
7009        ========================================================================
7010*/
7011VOID AsicAddSharedKeyEntry(
7012        IN PRTMP_ADAPTER pAd,
7013        IN UCHAR                 BssIndex,
7014        IN UCHAR                 KeyIdx,
7015        IN UCHAR                 CipherAlg,
7016        IN PUCHAR                pKey,
7017        IN PUCHAR                pTxMic,
7018        IN PUCHAR                pRxMic)
7019{
7020        ULONG offset; //, csr0;
7021        SHAREDKEY_MODE_STRUC csr1;
7022#ifdef RT2860
7023        INT   i;
7024#endif
7025
7026        DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7027//============================================================================================
7028
7029        DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7030        DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7031                pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7032        if (pRxMic)
7033        {
7034                DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7035                        pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7036        }
7037        if (pTxMic)
7038        {
7039                DBGPRINT_RAW(RT_DEBUG_TRACE, ("         Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7040                        pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7041        }
7042//============================================================================================
7043        //
7044        // fill key material - key + TX MIC + RX MIC
7045        //
7046
7047        offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7048#ifdef RT2860
7049        for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7050        {
7051                RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7052        }
7053#endif
7054#ifdef RT2870
7055        RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7056#endif
7057        offset += MAX_LEN_OF_SHARE_KEY;
7058        if (pTxMic)
7059        {
7060#ifdef RT2860
7061                for (i=0; i<8; i++)
7062                {
7063                        RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7064                }
7065#endif
7066#ifdef RT2870
7067                RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7068#endif
7069        }
7070
7071        offset += 8;
7072        if (pRxMic)
7073        {
7074#ifdef RT2860
7075                for (i=0; i<8; i++)
7076                {
7077                        RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7078                }
7079#endif
7080#ifdef RT2870
7081                RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7082#endif
7083        }
7084
7085
7086        //
7087        // Update cipher algorithm. WSTA always use BSS0
7088        //
7089        RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7090        DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7091        if ((BssIndex%2) == 0)
7092        {
7093                if (KeyIdx == 0)
7094                        csr1.field.Bss0Key0CipherAlg = CipherAlg;
7095                else if (KeyIdx == 1)
7096                        csr1.field.Bss0Key1CipherAlg = CipherAlg;
7097                else if (KeyIdx == 2)
7098                        csr1.field.Bss0Key2CipherAlg = CipherAlg;
7099                else
7100                        csr1.field.Bss0Key3CipherAlg = CipherAlg;
7101        }
7102        else
7103        {
7104                if (KeyIdx == 0)
7105                        csr1.field.Bss1Key0CipherAlg = CipherAlg;
7106                else if (KeyIdx == 1)
7107                        csr1.field.Bss1Key1CipherAlg = CipherAlg;
7108                else if (KeyIdx == 2)
7109                        csr1.field.Bss1Key2CipherAlg = CipherAlg;
7110                else
7111                        csr1.field.Bss1Key3CipherAlg = CipherAlg;
7112        }
7113        DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7114        RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7115
7116}
7117
7118//      IRQL = DISPATCH_LEVEL
7119VOID AsicRemoveSharedKeyEntry(
7120        IN PRTMP_ADAPTER pAd,
7121        IN UCHAR                 BssIndex,
7122        IN UCHAR                 KeyIdx)
7123{
7124        //ULONG SecCsr0;
7125        SHAREDKEY_MODE_STRUC csr1;
7126
7127        DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7128
7129        RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7130        if ((BssIndex%2) == 0)
7131        {
7132                if (KeyIdx == 0)
7133                        csr1.field.Bss0Key0CipherAlg = 0;
7134                else if (KeyIdx == 1)
7135                        csr1.field.Bss0Key1CipherAlg = 0;
7136                else if (KeyIdx == 2)
7137                        csr1.field.Bss0Key2CipherAlg = 0;
7138                else
7139                        csr1.field.Bss0Key3CipherAlg = 0;
7140        }
7141        else
7142        {
7143                if (KeyIdx == 0)
7144                        csr1.field.Bss1Key0CipherAlg = 0;
7145                else if (KeyIdx == 1)
7146                        csr1.field.Bss1Key1CipherAlg = 0;
7147                else if (KeyIdx == 2)
7148                        csr1.field.Bss1Key2CipherAlg = 0;
7149                else
7150                        csr1.field.Bss1Key3CipherAlg = 0;
7151        }
7152        DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7153        RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7154        ASSERT(BssIndex < 4);
7155        ASSERT(KeyIdx < 4);
7156
7157}
7158
7159
7160VOID AsicUpdateWCIDAttribute(
7161        IN PRTMP_ADAPTER pAd,
7162        IN USHORT               WCID,
7163        IN UCHAR                BssIndex,
7164        IN UCHAR        CipherAlg,
7165        IN BOOLEAN              bUsePairewiseKeyTable)
7166{
7167        ULONG   WCIDAttri = 0, offset;
7168
7169        //
7170        // Update WCID attribute.
7171        // Only TxKey could update WCID attribute.
7172        //
7173        offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7174        WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7175        RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7176}
7177
7178VOID AsicUpdateWCIDIVEIV(
7179        IN PRTMP_ADAPTER pAd,
7180        IN USHORT               WCID,
7181        IN ULONG        uIV,
7182        IN ULONG        uEIV)
7183{
7184        ULONG   offset;
7185
7186        offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7187
7188        RTMP_IO_WRITE32(pAd, offset, uIV);
7189        RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7190}
7191
7192VOID AsicUpdateRxWCIDTable(
7193        IN PRTMP_ADAPTER pAd,
7194        IN USHORT               WCID,
7195        IN PUCHAR        pAddr)
7196{
7197        ULONG offset;
7198        ULONG Addr;
7199
7200        offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7201        Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7202        RTMP_IO_WRITE32(pAd, offset, Addr);
7203        Addr = pAddr[4] + (pAddr[5] << 8);
7204        RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7205}
7206
7207
7208/*
7209    ========================================================================
7210
7211    Routine Description:
7212        Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7213
7214    Arguments:
7215        pAd                     Pointer to our adapter
7216        WCID                    WCID Entry number.
7217        BssIndex                BSSID index, station or none multiple BSSID support
7218                                this value should be 0.
7219        KeyIdx                  This KeyIdx will set to IV's KeyID if bTxKey enabled
7220        pCipherKey              Pointer to Cipher Key.
7221        bUsePairewiseKeyTable   TRUE means saved the key in SharedKey table,
7222                                otherwise PairewiseKey table
7223        bTxKey                  This is the transmit key if enabled.
7224
7225    Return Value:
7226        None
7227
7228    Note:
7229        This routine will set the relative key stuff to Asic including WCID attribute,
7230        Cipher Key, Cipher algorithm and IV/EIV.
7231
7232        IV/EIV will be update if this CipherKey is the transmission key because
7233        ASIC will base on IV's KeyID value to select Cipher Key.
7234
7235        If bTxKey sets to FALSE, this is not the TX key, but it could be
7236        RX key
7237
7238        For AP mode bTxKey must be always set to TRUE.
7239    ========================================================================
7240*/
7241VOID AsicAddKeyEntry(
7242        IN PRTMP_ADAPTER pAd,
7243        IN USHORT               WCID,
7244        IN UCHAR                BssIndex,
7245        IN UCHAR                KeyIdx,
7246        IN PCIPHER_KEY  pCipherKey,
7247        IN BOOLEAN              bUsePairewiseKeyTable,
7248        IN BOOLEAN              bTxKey)
7249{
7250        ULONG   offset;
7251        UCHAR   IV4 = 0;
7252        PUCHAR          pKey = pCipherKey->Key;
7253        PUCHAR          pTxMic = pCipherKey->TxMic;
7254        PUCHAR          pRxMic = pCipherKey->RxMic;
7255        PUCHAR          pTxtsc = pCipherKey->TxTsc;
7256        UCHAR           CipherAlg = pCipherKey->CipherAlg;
7257        SHAREDKEY_MODE_STRUC csr1;
7258#ifdef RT2860
7259        UCHAR           i;
7260#endif
7261
7262        DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7263        //
7264        // 1.) decide key table offset
7265        //
7266        if (bUsePairewiseKeyTable)
7267                offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7268        else
7269                offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7270
7271        //
7272        // 2.) Set Key to Asic
7273        //
7274        //for (i = 0; i < KeyLen; i++)
7275#ifdef RT2860
7276        for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7277        {
7278                RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7279        }
7280#endif
7281#ifdef RT2870
7282        RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7283#endif
7284        offset += MAX_LEN_OF_PEER_KEY;
7285
7286        //
7287        // 3.) Set MIC key if available
7288        //
7289        if (pTxMic)
7290        {
7291#ifdef RT2860
7292                for (i = 0; i < 8; i++)
7293                {
7294                        RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7295                }
7296#endif
7297#ifdef RT2870
7298                RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7299#endif
7300        }
7301        offset += LEN_TKIP_TXMICK;
7302
7303        if (pRxMic)
7304        {
7305#ifdef RT2860
7306                for (i = 0; i < 8; i++)
7307                {
7308                        RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7309                }
7310#endif
7311#ifdef RT2870
7312                RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7313#endif
7314        }
7315
7316
7317        //
7318        // 4.) Modify IV/EIV if needs
7319        //     This will force Asic to use this key ID by setting IV.
7320        //
7321        if (bTxKey)
7322        {
7323#ifdef RT2860
7324                offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7325                //
7326                // Write IV
7327                //
7328                RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7329                RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7330                RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7331
7332                IV4 = (KeyIdx << 6);
7333                if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7334                        IV4 |= 0x20;  // turn on extension bit means EIV existence
7335
7336                RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7337
7338                //
7339                // Write EIV
7340                //
7341                offset += 4;
7342                for (i = 0; i < 4; i++)
7343                {
7344                        RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7345                }
7346
7347#endif
7348#ifdef RT2870
7349                UINT32 tmpVal;
7350
7351                //
7352                // Write IV
7353                //
7354                IV4 = (KeyIdx << 6);
7355                if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7356                        IV4 |= 0x20;  // turn on extension bit means EIV existence
7357
7358                tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7359                RTMP_IO_WRITE32(pAd, offset, tmpVal);
7360
7361                //
7362                // Write EIV
7363                //
7364                offset += 4;
7365                RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7366#endif // RT2870 //
7367                AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7368        }
7369
7370        if (!bUsePairewiseKeyTable)
7371        {
7372                //
7373                // Only update the shared key security mode
7374                //
7375                RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7376                if ((BssIndex % 2) == 0)
7377                {
7378                        if (KeyIdx == 0)
7379                                csr1.field.Bss0Key0CipherAlg = CipherAlg;
7380                        else if (KeyIdx == 1)
7381                                csr1.field.Bss0Key1CipherAlg = CipherAlg;
7382                        else if (KeyIdx == 2)
7383                                csr1.field.Bss0Key2CipherAlg = CipherAlg;
7384                        else
7385                                csr1.field.Bss0Key3CipherAlg = CipherAlg;
7386                }
7387                else
7388                {
7389                        if (KeyIdx == 0)
7390                                csr1.field.Bss1Key0CipherAlg = CipherAlg;
7391                        else if (KeyIdx == 1)
7392                                csr1.field.Bss1Key1CipherAlg = CipherAlg;
7393                        else if (KeyIdx == 2)
7394                                csr1.field.Bss1Key2CipherAlg = CipherAlg;
7395                        else
7396                                csr1.field.Bss1Key3CipherAlg = CipherAlg;
7397                }
7398                RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7399        }
7400
7401        DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7402}
7403
7404
7405/*
7406        ========================================================================
7407        Description:
7408                Add Pair-wise key material into ASIC.
7409                Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7410
7411    Return:
7412        ========================================================================
7413*/
7414VOID AsicAddPairwiseKeyEntry(
7415        IN PRTMP_ADAPTER pAd,
7416        IN PUCHAR        pAddr,
7417        IN UCHAR                WCID,
7418        IN CIPHER_KEY            *pCipherKey)
7419{
7420        INT i;
7421        ULONG           offset;
7422        PUCHAR           pKey = pCipherKey->Key;
7423        PUCHAR           pTxMic = pCipherKey->TxMic;
7424        PUCHAR           pRxMic = pCipherKey->RxMic;
7425#ifdef DBG
7426        UCHAR           CipherAlg = pCipherKey->CipherAlg;
7427#endif // DBG //
7428
7429        // EKEY
7430        offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7431#ifdef RT2860
7432        for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7433        {
7434                RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7435        }
7436#endif
7437#ifdef RT2870
7438        RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7439#endif // RT2870 //
7440        for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7441        {
7442                UINT32 Value;
7443                RTMP_IO_READ32(pAd, offset + i, &Value);
7444        }
7445
7446        offset += MAX_LEN_OF_PEER_KEY;
7447
7448        //  MIC KEY
7449        if (pTxMic)
7450        {
7451#ifdef RT2860
7452                for (i=0; i<8; i++)
7453                {
7454                        RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7455                }
7456#endif
7457#ifdef RT2870
7458                RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7459#endif // RT2870 //
7460        }
7461        offset += 8;
7462        if (pRxMic)
7463        {
7464#ifdef RT2860
7465                for (i=0; i<8; i++)
7466                {
7467                        RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7468                }
7469#endif
7470#ifdef RT2870
7471                RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7472#endif // RT2870 //
7473        }
7474
7475        DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7476        DBGPRINT(RT_DEBUG_TRACE,("      Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7477                pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7478        if (pRxMic)
7479        {
7480                DBGPRINT(RT_DEBUG_TRACE, ("     Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7481                        pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7482        }
7483        if (pTxMic)
7484        {
7485                DBGPRINT(RT_DEBUG_TRACE, ("     Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7486                        pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7487        }
7488}
7489/*
7490        ========================================================================
7491        Description:
7492                Remove Pair-wise key material from ASIC.
7493
7494    Return:
7495        ========================================================================
7496*/
7497VOID AsicRemovePairwiseKeyEntry(
7498        IN PRTMP_ADAPTER pAd,
7499        IN UCHAR                 BssIdx,
7500        IN UCHAR                 Wcid)
7501{
7502        ULONG           WCIDAttri;
7503        USHORT          offset;
7504
7505        // re-set the entry's WCID attribute as OPEN-NONE.
7506        offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7507        WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7508        RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7509}
7510
7511BOOLEAN AsicSendCommandToMcu(
7512        IN PRTMP_ADAPTER pAd,
7513        IN UCHAR                 Command,
7514        IN UCHAR                 Token,
7515        IN UCHAR                 Arg0,
7516        IN UCHAR                 Arg1)
7517{
7518        HOST_CMD_CSR_STRUC      H2MCmd;
7519        H2M_MAILBOX_STRUC       H2MMailbox;
7520        ULONG                           i = 0;
7521
7522        do
7523        {
7524                RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7525                if (H2MMailbox.field.Owner == 0)
7526                        break;
7527
7528                RTMPusecDelay(2);
7529        } while(i++ < 100);
7530
7531        if (i > 100)
7532        {
7533                {
7534#ifdef RT2860
7535                        UINT32 Data;
7536
7537                        // Reset DMA
7538                        RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7539                        Data |= 0x2;
7540                        RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7541
7542                        // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7543                        // Reset DMA/CPU ring index
7544                        RTMPRingCleanUp(pAd, QID_AC_BK);
7545                        RTMPRingCleanUp(pAd, QID_AC_BE);
7546                        RTMPRingCleanUp(pAd, QID_AC_VI);
7547                        RTMPRingCleanUp(pAd, QID_AC_VO);
7548                        RTMPRingCleanUp(pAd, QID_HCCA);
7549                        RTMPRingCleanUp(pAd, QID_MGMT);
7550                        RTMPRingCleanUp(pAd, QID_RX);
7551
7552                        // Clear Reset
7553                        RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7554                        Data &= 0xfffffffd;
7555                        RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7556#endif /* RT2860 */
7557                DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7558                }
7559                //return FALSE;
7560#ifdef RT2870
7561                return FALSE;
7562#endif
7563        }
7564
7565        H2MMailbox.field.Owner    = 1;     // pass ownership to MCU
7566        H2MMailbox.field.CmdToken = Token;
7567        H2MMailbox.field.HighByte = Arg1;
7568        H2MMailbox.field.LowByte  = Arg0;
7569        RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7570
7571        H2MCmd.word                       = 0;
7572        H2MCmd.field.HostCommand  = Command;
7573        RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7574
7575        if (Command != 0x80)
7576        {
7577        }
7578
7579        return TRUE;
7580}
7581
7582#ifdef RT2860
7583BOOLEAN AsicCheckCommanOk(
7584        IN PRTMP_ADAPTER pAd,
7585        IN UCHAR                 Command)
7586{
7587        UINT32  CmdStatus = 0, CID = 0, i;
7588        UINT32  ThisCIDMask = 0;
7589
7590        i = 0;
7591        do
7592        {
7593                RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7594                // Find where the command is. Because this is randomly specified by firmware.
7595                if ((CID & CID0MASK) == Command)
7596                {
7597                        ThisCIDMask = CID0MASK;
7598                        break;
7599                }
7600                else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7601                {
7602                        ThisCIDMask = CID1MASK;
7603                        break;
7604                }
7605                else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7606                {
7607                        ThisCIDMask = CID2MASK;
7608                        break;
7609                }
7610                else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7611                {
7612                        ThisCIDMask = CID3MASK;
7613                        break;
7614                }
7615
7616                RTMPusecDelay(100);
7617                i++;
7618        }while (i < 200);
7619
7620        // Get CommandStatus Value
7621        RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7622
7623        // This command's status is at the same position as command. So AND command position's bitmask to read status.
7624        if (i < 200)
7625        {
7626                // If Status is 1, the comamnd is success.
7627                if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7628                        || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7629                {
7630                        DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7631                        RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7632                        RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7633                        return TRUE;
7634                }
7635                DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7636        }
7637        else
7638        {
7639                DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7640        }
7641        // Clear Command and Status.
7642        RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7643        RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7644
7645        return FALSE;
7646}
7647#endif /* RT8260 */
7648
7649/*
7650        ========================================================================
7651
7652        Routine Description:
7653                Verify the support rate for different PHY type
7654
7655        Arguments:
7656                pAd                             Pointer to our adapter
7657
7658        Return Value:
7659                None
7660
7661        IRQL = PASSIVE_LEVEL
7662
7663        ========================================================================
7664*/
7665VOID    RTMPCheckRates(
7666        IN              PRTMP_ADAPTER   pAd,
7667        IN OUT  UCHAR                   SupRate[],
7668        IN OUT  UCHAR                   *SupRateLen)
7669{
7670        UCHAR   RateIdx, i, j;
7671        UCHAR   NewRate[12], NewRateLen;
7672
7673        NewRateLen = 0;
7674
7675        if (pAd->CommonCfg.PhyMode == PHY_11B)
7676                RateIdx = 4;
7677        else
7678                RateIdx = 12;
7679
7680        // Check for support rates exclude basic rate bit
7681        for (i = 0; i < *SupRateLen; i++)
7682                for (j = 0; j < RateIdx; j++)
7683                        if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7684                                NewRate[NewRateLen++] = SupRate[i];
7685
7686        *SupRateLen = NewRateLen;
7687        NdisMoveMemory(SupRate, NewRate, NewRateLen);
7688}
7689
7690BOOLEAN RTMPCheckChannel(
7691        IN PRTMP_ADAPTER pAd,
7692        IN UCHAR                CentralChannel,
7693        IN UCHAR                Channel)
7694{
7695        UCHAR           k;
7696        UCHAR           UpperChannel = 0, LowerChannel = 0;
7697        UCHAR           NoEffectChannelinList = 0;
7698
7699        // Find upper and lower channel according to 40MHz current operation.
7700        if (CentralChannel < Channel)
7701        {
7702                UpperChannel = Channel;
7703                if (CentralChannel > 2)
7704                        LowerChannel = CentralChannel - 2;
7705                else
7706                        return FALSE;
7707        }
7708        else if (CentralChannel > Channel)
7709        {
7710                UpperChannel = CentralChannel + 2;
7711                LowerChannel = Channel;
7712        }
7713
7714        for (k = 0;k < pAd->ChannelListNum;k++)
7715        {
7716                if (pAd->ChannelList[k].Channel == UpperChannel)
7717                {
7718                        NoEffectChannelinList ++;
7719                }
7720                if (pAd->ChannelList[k].Channel == LowerChannel)
7721                {
7722                        NoEffectChannelinList ++;
7723                }
7724        }
7725
7726        DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7727        if (NoEffectChannelinList == 2)
7728                return TRUE;
7729        else
7730                return FALSE;
7731}
7732
7733/*
7734        ========================================================================
7735
7736        Routine Description:
7737                Verify the support rate for HT phy type
7738
7739        Arguments:
7740                pAd                             Pointer to our adapter
7741
7742        Return Value:
7743                FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability.  (AP Mode)
7744
7745        IRQL = PASSIVE_LEVEL
7746
7747        ========================================================================
7748*/
7749BOOLEAN         RTMPCheckHt(
7750        IN      PRTMP_ADAPTER                   pAd,
7751        IN      UCHAR                                   Wcid,
7752        IN      HT_CAPABILITY_IE                *pHtCapability,
7753        IN      ADD_HT_INFO_IE                  *pAddHtInfo)
7754{
7755        if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7756                return FALSE;
7757
7758        // If use AMSDU, set flag.
7759        if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7760                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7761        // Save Peer Capability
7762        if (pHtCapability->HtCapInfo.ShortGIfor20)
7763                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7764        if (pHtCapability->HtCapInfo.ShortGIfor40)
7765                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7766        if (pHtCapability->HtCapInfo.TxSTBC)
7767                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7768        if (pHtCapability->HtCapInfo.RxSTBC)
7769                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7770        if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7771        {
7772                CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7773        }
7774
7775        if (Wcid < MAX_LEN_OF_MAC_TABLE)
7776        {
7777                pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7778        }
7779
7780        // Will check ChannelWidth for MCSSet[4] below
7781        pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7782    switch (pAd->CommonCfg.RxStream)
7783        {
7784                case 1:
7785                        pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7786                        pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7787            pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7788            pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7789                        break;
7790                case 2:
7791                        pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7792                        pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7793            pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7794            pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7795                        break;
7796                case 3:
7797                        pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7798                        pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7799            pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7800            pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7801                        break;
7802        }
7803
7804        pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7805
7806    DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7807                pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7808                pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7809
7810        pAd->MlmeAux.HtCapability.HtCapInfo.GF =  pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7811
7812        // Send Assoc Req with my HT capability.
7813        pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =  pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7814        pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =  pAd->CommonCfg.DesiredHtPhy.MimoPs;
7815        pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7816        pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =  (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7817        pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =  (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7818        pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =  (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7819        pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7820    pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7821        pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7822        pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7823        if (pAd->CommonCfg.bRdg)
7824        {
7825                pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7826        pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7827        }
7828
7829    if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7830        pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0;  // BW20 can't transmit MCS32
7831
7832        COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7833        return TRUE;
7834}
7835
7836/*
7837        ========================================================================
7838
7839        Routine Description:
7840                Verify the support rate for different PHY type
7841
7842        Arguments:
7843                pAd                             Pointer to our adapter
7844
7845        Return Value:
7846                None
7847
7848        IRQL = PASSIVE_LEVEL
7849
7850        ========================================================================
7851*/
7852VOID RTMPUpdateMlmeRate(
7853        IN PRTMP_ADAPTER        pAd)
7854{
7855        UCHAR   MinimumRate;
7856        UCHAR   ProperMlmeRate; //= RATE_54;
7857        UCHAR   i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7858        BOOLEAN bMatch = FALSE;
7859
7860        switch (pAd->CommonCfg.PhyMode)
7861        {
7862                case PHY_11B:
7863                        ProperMlmeRate = RATE_11;
7864                        MinimumRate = RATE_1;
7865                        break;
7866                case PHY_11BG_MIXED:
7867                case PHY_11ABGN_MIXED:
7868                case PHY_11BGN_MIXED:
7869                        if ((pAd->MlmeAux.SupRateLen == 4) &&
7870                                (pAd->MlmeAux.ExtRateLen == 0))
7871                                // B only AP
7872                                ProperMlmeRate = RATE_11;
7873                        else
7874                                ProperMlmeRate = RATE_24;
7875
7876                        if (pAd->MlmeAux.Channel <= 14)
7877                                MinimumRate = RATE_1;
7878                        else
7879                                MinimumRate = RATE_6;
7880                        break;
7881                case PHY_11A:
7882                case PHY_11N_2_4G:      // rt2860 need to check mlmerate for 802.11n
7883                case PHY_11GN_MIXED:
7884                case PHY_11AGN_MIXED:
7885                case PHY_11AN_MIXED:
7886                case PHY_11N_5G:
7887                        ProperMlmeRate = RATE_24;
7888                        MinimumRate = RATE_6;
7889                        break;
7890                case PHY_11ABG_MIXED:
7891                        ProperMlmeRate = RATE_24;
7892                        if (pAd->MlmeAux.Channel <= 14)
7893                           MinimumRate = RATE_1;
7894                        else
7895                                MinimumRate = RATE_6;
7896                        break;
7897                default: // error
7898                        ProperMlmeRate = RATE_1;
7899                        MinimumRate = RATE_1;
7900                        break;
7901        }
7902
7903        for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7904        {
7905                for (j = 0; j < RateIdx; j++)
7906                {
7907                        if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7908                        {
7909                                if (j == ProperMlmeRate)
7910                                {
7911                                        bMatch = TRUE;
7912                                        break;
7913                                }
7914                        }
7915                }
7916
7917                if (bMatch)
7918                        break;
7919        }
7920
7921        if (bMatch == FALSE)
7922        {
7923                for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7924                {
7925                        for (j = 0; j < RateIdx; j++)
7926                        {
7927                                if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7928                                {
7929                                        if (j == ProperMlmeRate)
7930                                        {
7931                                                bMatch = TRUE;
7932                                                break;
7933                                        }
7934                                }
7935                        }
7936
7937                        if (bMatch)
7938                                break;
7939                }
7940        }
7941
7942        if (bMatch == FALSE)
7943        {
7944                ProperMlmeRate = MinimumRate;
7945        }
7946
7947        pAd->CommonCfg.MlmeRate = MinimumRate;
7948        pAd->CommonCfg.RtsRate = ProperMlmeRate;
7949        if (pAd->CommonCfg.MlmeRate >= RATE_6)
7950        {
7951                pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7952                pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7953                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7954                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7955        }
7956        else
7957        {
7958                pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7959                pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7960                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7961                pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7962        }
7963
7964        DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==>   MlmeTransmit = 0x%x  \n" , pAd->CommonCfg.MlmeTransmit.word));
7965}
7966
7967CHAR RTMPMaxRssi(
7968        IN PRTMP_ADAPTER        pAd,
7969        IN CHAR                         Rssi0,
7970        IN CHAR                         Rssi1,
7971        IN CHAR                         Rssi2)
7972{
7973        CHAR    larger = -127;
7974
7975        if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7976        {
7977                larger = Rssi0;
7978        }
7979
7980        if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7981        {
7982                larger = max(Rssi0, Rssi1);
7983        }
7984
7985        if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7986        {
7987                larger = max(larger, Rssi2);
7988        }
7989
7990        if (larger == -127)
7991                larger = 0;
7992
7993        return larger;
7994}
7995
7996#ifdef RT2870
7997// Antenna divesity use GPIO3 and EESK pin for control
7998// Antenna and EEPROM access are both using EESK pin,
7999// Therefor we should avoid accessing EESK at the same time
8000// Then restore antenna after EEPROM access
8001VOID AsicSetRxAnt(
8002        IN PRTMP_ADAPTER        pAd,
8003        IN UCHAR                        Ant)
8004{
8005        UINT32  Value;
8006        UINT32  x;
8007
8008        if ((pAd->EepromAccess)                                                                         ||
8009                (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))  ||
8010                (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))   ||
8011                (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))                  ||
8012                (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8013        {
8014                return;
8015        }
8016
8017        // the antenna selection is through firmware and MAC register(GPIO3)
8018        if (Ant == 0)
8019        {
8020                // Main antenna
8021                RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8022                x |= (EESK);
8023                RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8024
8025                RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8026                Value &= ~(0x0808);
8027                RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8028                DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8029        }
8030        else
8031        {
8032                // Aux antenna
8033                RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8034                x &= ~(EESK);
8035                RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8036
8037                RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8038                Value &= ~(0x0808);
8039                Value |= 0x08;
8040                RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8041                DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8042        }
8043}
8044#endif
8045
8046/*
8047    ========================================================================
8048    Routine Description:
8049        Periodic evaluate antenna link status
8050
8051    Arguments:
8052        pAd         - Adapter pointer
8053
8054    Return Value:
8055        None
8056
8057    ========================================================================
8058*/
8059VOID AsicEvaluateRxAnt(
8060        IN PRTMP_ADAPTER        pAd)
8061{
8062        UCHAR   BBPR3 = 0;
8063
8064        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8065                                fRTMP_ADAPTER_HALT_IN_PROGRESS |
8066                                fRTMP_ADAPTER_RADIO_OFF |
8067                                fRTMP_ADAPTER_NIC_NOT_EXIST |
8068                                fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
8069                                || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8070#ifdef RT2870
8071                                || (pAd->EepromAccess)
8072#endif
8073                                )
8074                        return;
8075
8076#ifdef RT30xx
8077        // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8078        // one is antenna diversity:there is only one antenna can rx and tx
8079        // the other is failed antenna remove:two physical antenna can rx and tx
8080        if (pAd->NicConfig2.field.AntDiversity)
8081        {
8082                DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8083                        pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8084
8085                AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8086
8087                pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8088                pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8089                pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8090
8091                // a one-shot timer to end the evalution
8092                // dynamic adjust antenna evaluation period according to the traffic
8093                if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8094                        RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8095                else
8096                        RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8097        }
8098        else
8099#endif
8100        {
8101                if (pAd->StaCfg.Psm == PWR_SAVE)
8102                        return;
8103
8104                RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8105                BBPR3 &= (~0x18);
8106                if(pAd->Antenna.field.RxPath == 3)
8107                {
8108                        BBPR3 |= (0x10);
8109                }
8110                else if(pAd->Antenna.field.RxPath == 2)
8111                {
8112                        BBPR3 |= (0x8);
8113                }
8114                else if(pAd->Antenna.field.RxPath == 1)
8115                {
8116                        BBPR3 |= (0x0);
8117                }
8118                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8119
8120#ifdef RT2860
8121                pAd->StaCfg.BBPR3 = BBPR3;
8122#endif
8123        }
8124
8125        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8126                )
8127        {
8128                ULONG   TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8129                                                                pAd->RalinkCounters.OneSecTxRetryOkCount +
8130                                                                pAd->RalinkCounters.OneSecTxFailCount;
8131
8132                        // dynamic adjust antenna evaluation period according to the traffic
8133                if (TxTotalCnt > 50)
8134                {
8135                        RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8136                        pAd->Mlme.bLowThroughput = FALSE;
8137                }
8138                else
8139                {
8140                        RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8141                        pAd->Mlme.bLowThroughput = TRUE;
8142                }
8143        }
8144}
8145
8146/*
8147    ========================================================================
8148    Routine Description:
8149        After evaluation, check antenna link status
8150
8151    Arguments:
8152        pAd         - Adapter pointer
8153
8154    Return Value:
8155        None
8156
8157    ========================================================================
8158*/
8159VOID AsicRxAntEvalTimeout(
8160        IN PVOID SystemSpecific1,
8161        IN PVOID FunctionContext,
8162        IN PVOID SystemSpecific2,
8163        IN PVOID SystemSpecific3)
8164{
8165        RTMP_ADAPTER    *pAd = (RTMP_ADAPTER *)FunctionContext;
8166        UCHAR                   BBPR3 = 0;
8167        CHAR                    larger = -127, rssi0, rssi1, rssi2;
8168
8169        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8170                                                        fRTMP_ADAPTER_HALT_IN_PROGRESS  |
8171                                                        fRTMP_ADAPTER_RADIO_OFF                 |
8172                                                        fRTMP_ADAPTER_NIC_NOT_EXIST)
8173                                                        || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8174#ifdef RT2870
8175                                                        || (pAd->EepromAccess)
8176#endif
8177                                                        )
8178                return;
8179
8180        {
8181#ifdef RT30xx
8182                if (pAd->NicConfig2.field.AntDiversity)
8183                {
8184                        if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8185                        {
8186                                UCHAR                   temp;
8187
8188                                //
8189                                // select PrimaryRxAntPair
8190                                //    Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8191                                //    Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8192                                //
8193                                temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8194                                pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8195                                pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8196
8197                                pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8198                                pAd->RxAnt.EvaluateStableCnt = 0;
8199                        }
8200                        else
8201                        {
8202                                // if the evaluated antenna is not better than original, switch back to original antenna
8203                                AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8204                                pAd->RxAnt.EvaluateStableCnt ++;
8205                        }
8206
8207                        pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8208
8209                        DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8210                                        pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8211                }
8212                else
8213#endif
8214                {
8215                        if (pAd->StaCfg.Psm == PWR_SAVE)
8216                                return;
8217
8218                        // if the traffic is low, use average rssi as the criteria
8219                        if (pAd->Mlme.bLowThroughput == TRUE)
8220                        {
8221                                rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8222                                rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8223                                rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8224                        }
8225                        else
8226                        {
8227                                rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8228                                rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8229                                rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8230                        }
8231
8232                        if(pAd->Antenna.field.RxPath == 3)
8233                        {
8234                                larger = max(rssi0, rssi1);
8235
8236                                if (larger > (rssi2 + 20))
8237                                        pAd->Mlme.RealRxPath = 2;
8238                                else
8239                                        pAd->Mlme.RealRxPath = 3;
8240                        }
8241                        else if(pAd->Antenna.field.RxPath == 2)
8242                        {
8243                                if (rssi0 > (rssi1 + 20))
8244                                        pAd->Mlme.RealRxPath = 1;
8245                                else
8246                                        pAd->Mlme.RealRxPath = 2;
8247                        }
8248
8249                        RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8250                        BBPR3 &= (~0x18);
8251                        if(pAd->Mlme.RealRxPath == 3)
8252                        {
8253                                BBPR3 |= (0x10);
8254                        }
8255                        else if(pAd->Mlme.RealRxPath == 2)
8256                        {
8257                                BBPR3 |= (0x8);
8258                        }
8259                        else if(pAd->Mlme.RealRxPath == 1)
8260                        {
8261                                BBPR3 |= (0x0);
8262                        }
8263                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8264#ifdef RT2860
8265                        pAd->StaCfg.BBPR3 = BBPR3;
8266#endif
8267                }
8268        }
8269}
8270
8271VOID APSDPeriodicExec(
8272        IN PVOID SystemSpecific1,
8273        IN PVOID FunctionContext,
8274        IN PVOID SystemSpecific2,
8275        IN PVOID SystemSpecific3)
8276{
8277        RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8278
8279        if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8280                return;
8281
8282        pAd->CommonCfg.TriggerTimerCount++;
8283
8284}
8285
8286/*
8287    ========================================================================
8288    Routine Description:
8289        Set/reset MAC registers according to bPiggyBack parameter
8290
8291    Arguments:
8292        pAd         - Adapter pointer
8293        bPiggyBack  - Enable / Disable Piggy-Back
8294
8295    Return Value:
8296        None
8297
8298    ========================================================================
8299*/
8300VOID RTMPSetPiggyBack(
8301    IN PRTMP_ADAPTER    pAd,
8302    IN BOOLEAN          bPiggyBack)
8303{
8304        TX_LINK_CFG_STRUC  TxLinkCfg;
8305
8306        RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8307
8308        TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8309        RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8310}
8311
8312/*
8313    ========================================================================
8314    Routine Description:
8315        check if this entry need to switch rate automatically
8316
8317    Arguments:
8318        pAd
8319        pEntry
8320
8321    Return Value:
8322        TURE
8323        FALSE
8324
8325    ========================================================================
8326*/
8327BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8328        IN PRTMP_ADAPTER    pAd,
8329        IN PMAC_TABLE_ENTRY     pEntry)
8330{
8331        BOOLEAN         result = TRUE;
8332
8333        {
8334                // only associated STA counts
8335                if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8336                {
8337                        result = pAd->StaCfg.bAutoTxRateSwitch;
8338                }
8339                else
8340                        result = FALSE;
8341        }
8342
8343        return result;
8344}
8345
8346
8347BOOLEAN RTMPAutoRateSwitchCheck(
8348        IN PRTMP_ADAPTER    pAd)
8349{
8350        if (pAd->StaCfg.bAutoTxRateSwitch)
8351                return TRUE;
8352
8353        return FALSE;
8354}
8355
8356
8357/*
8358    ========================================================================
8359    Routine Description:
8360        check if this entry need to fix tx legacy rate
8361
8362    Arguments:
8363        pAd
8364        pEntry
8365
8366    Return Value:
8367        TURE
8368        FALSE
8369
8370    ========================================================================
8371*/
8372UCHAR RTMPStaFixedTxMode(
8373        IN PRTMP_ADAPTER    pAd,
8374        IN PMAC_TABLE_ENTRY     pEntry)
8375{
8376        UCHAR   tx_mode = FIXED_TXMODE_HT;
8377
8378        tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8379
8380        return tx_mode;
8381}
8382
8383/*
8384    ========================================================================
8385    Routine Description:
8386        Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8387
8388    Arguments:
8389        pAd
8390        pEntry
8391
8392    Return Value:
8393        TURE
8394        FALSE
8395
8396    ========================================================================
8397*/
8398VOID RTMPUpdateLegacyTxSetting(
8399                UCHAR                           fixed_tx_mode,
8400                PMAC_TABLE_ENTRY        pEntry)
8401{
8402        HTTRANSMIT_SETTING TransmitSetting;
8403
8404        if (fixed_tx_mode == FIXED_TXMODE_HT)
8405                return;
8406
8407        TransmitSetting.word = 0;
8408
8409        TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8410        TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8411
8412        if (fixed_tx_mode == FIXED_TXMODE_CCK)
8413        {
8414                TransmitSetting.field.MODE = MODE_CCK;
8415                // CCK mode allow MCS 0~3
8416                if (TransmitSetting.field.MCS > MCS_3)
8417                        TransmitSetting.field.MCS = MCS_3;
8418        }
8419        else
8420        {
8421                TransmitSetting.field.MODE = MODE_OFDM;
8422                // OFDM mode allow MCS 0~7
8423                if (TransmitSetting.field.MCS > MCS_7)
8424                        TransmitSetting.field.MCS = MCS_7;
8425        }
8426
8427        if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8428        {
8429                pEntry->HTPhyMode.word = TransmitSetting.word;
8430                DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8431                                pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8432        }
8433}
8434
8435/*
8436        ==========================================================================
8437        Description:
8438                dynamic tune BBP R66 to find a balance between sensibility and
8439                noise isolation
8440
8441        IRQL = DISPATCH_LEVEL
8442
8443        ==========================================================================
8444 */
8445VOID AsicStaBbpTuning(
8446        IN PRTMP_ADAPTER pAd)
8447{
8448        UCHAR   OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8449        CHAR    Rssi;
8450
8451        // 2860C did not support Fase CCA, therefore can't tune
8452        if (pAd->MACVersion == 0x28600100)
8453                return;
8454
8455        //
8456        // work as a STA
8457        //
8458        if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)  // no R66 tuning when SCANNING
8459                return;
8460
8461        if ((pAd->OpMode == OPMODE_STA)
8462                && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8463                        )
8464                && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8465#ifdef RT2860
8466                && (pAd->bPCIclkOff == FALSE))
8467#endif
8468#ifdef RT2870
8469                )
8470#endif
8471        {
8472                RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8473                R66 = OrigR66Value;
8474
8475                if (pAd->Antenna.field.RxPath > 1)
8476                        Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8477                else
8478                        Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8479
8480                if (pAd->LatchRfRegs.Channel <= 14)
8481                {       //BG band
8482#ifdef RT2870
8483                        // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8484                        // Otherwise, it will have some throughput side effect when low RSSI
8485                        if (IS_RT30xx(pAd))
8486                        {
8487                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8488                                {
8489                                        R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8490                                        if (OrigR66Value != R66)
8491                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8492                                }
8493                                else
8494                                {
8495                                        R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8496                                        if (OrigR66Value != R66)
8497                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8498                                }
8499                        }
8500                        else
8501#endif // RT2870 //
8502                        {
8503                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8504                                {
8505                                        R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8506                                        if (OrigR66Value != R66)
8507                                        {
8508                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8509                                        }
8510                                }
8511                                else
8512                                {
8513                                        R66 = 0x2E + GET_LNA_GAIN(pAd);
8514                                        if (OrigR66Value != R66)
8515                                        {
8516                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8517                                        }
8518                                }
8519                        }
8520                }
8521                else
8522                {       //A band
8523                        if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8524                        {
8525                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8526                                {
8527                                        R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8528                                        if (OrigR66Value != R66)
8529                                        {
8530                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8531                                        }
8532                                }
8533                                else
8534                                {
8535                                        R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8536                                        if (OrigR66Value != R66)
8537                                        {
8538                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8539                                        }
8540                                }
8541                        }
8542                        else
8543                        {
8544                                if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8545                                {
8546                                        R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8547                                        if (OrigR66Value != R66)
8548                                        {
8549                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8550                                        }
8551                                }
8552                                else
8553                                {
8554                                        R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8555                                        if (OrigR66Value != R66)
8556                                        {
8557                                                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8558                                        }
8559                                }
8560                        }
8561                }
8562
8563
8564        }
8565}
8566
8567#ifdef RT2860
8568VOID AsicResetFromDMABusy(
8569        IN PRTMP_ADAPTER pAd)
8570{
8571        UINT32          Data;
8572        BOOLEAN         bCtrl = FALSE;
8573
8574        DBGPRINT(RT_DEBUG_TRACE, ("--->  AsicResetFromDMABusy  !!!!!!!!!!!!!!!!!!!!!!! \n"));
8575
8576        // Be sure restore link control value so we can write register.
8577        RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8578        if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8579        {
8580                DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8581                RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8582                RTMPusecDelay(6000);
8583                pAd->bPCIclkOff = FALSE;
8584                bCtrl = TRUE;
8585        }
8586        // Reset DMA
8587        RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8588        Data |= 0x2;
8589        RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8590
8591        // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8592        // Reset DMA/CPU ring index
8593        RTMPRingCleanUp(pAd, QID_AC_BK);
8594        RTMPRingCleanUp(pAd, QID_AC_BE);
8595        RTMPRingCleanUp(pAd, QID_AC_VI);
8596        RTMPRingCleanUp(pAd, QID_AC_VO);
8597        RTMPRingCleanUp(pAd, QID_HCCA);
8598        RTMPRingCleanUp(pAd, QID_MGMT);
8599        RTMPRingCleanUp(pAd, QID_RX);
8600
8601        // Clear Reset
8602        RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8603        Data &= 0xfffffffd;
8604        RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8605
8606        // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8607        if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8608                RTMPPCIeLinkCtrlSetting(pAd, 3);
8609
8610        RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8611        RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8612        DBGPRINT(RT_DEBUG_TRACE, ("<---  AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!!  \n"));
8613}
8614
8615VOID AsicResetBBP(
8616        IN PRTMP_ADAPTER pAd)
8617{
8618        DBGPRINT(RT_DEBUG_TRACE, ("--->  Asic HardReset BBP  !!!!!!!!!!!!!!!!!!!!!!! \n"));
8619
8620        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8621        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8622        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8623
8624        // After hard-reset BBP, initialize all BBP values.
8625        NICRestoreBBPValue(pAd);
8626        DBGPRINT(RT_DEBUG_TRACE, ("<---  Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!!  \n"));
8627}
8628
8629VOID AsicResetMAC(
8630        IN PRTMP_ADAPTER pAd)
8631{
8632        ULONG           Data;
8633
8634        DBGPRINT(RT_DEBUG_TRACE, ("--->  AsicResetMAC   !!!! \n"));
8635        RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8636        Data |= 0x4;
8637        RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8638        Data &= 0xfffffffb;
8639        RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8640
8641        DBGPRINT(RT_DEBUG_TRACE, ("<---  AsicResetMAC   !!!! \n"));
8642}
8643
8644VOID AsicResetPBF(
8645        IN PRTMP_ADAPTER pAd)
8646{
8647        ULONG           Value1, Value2;
8648        ULONG           Data;
8649
8650        RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8651        RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8652
8653        Value2 &= 0xff;
8654        // sum should be equals to 0xff, which is the total buffer size.
8655        if ((Value1 + Value2) < 0xff)
8656        {
8657                DBGPRINT(RT_DEBUG_TRACE, ("--->  Asic HardReset PBF !!!! \n"));
8658                RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8659                Data |= 0x8;
8660                RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8661                Data &= 0xfffffff7;
8662                RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8663
8664                DBGPRINT(RT_DEBUG_TRACE, ("<---  Asic HardReset PBF !!!! \n"));
8665        }
8666}
8667#endif /* RT2860 */
8668
8669VOID RTMPSetAGCInitValue(
8670        IN PRTMP_ADAPTER        pAd,
8671        IN UCHAR                        BandWidth)
8672{
8673        UCHAR   R66 = 0x30;
8674
8675        if (pAd->LatchRfRegs.Channel <= 14)
8676        {       // BG band
8677                R66 = 0x2E + GET_LNA_GAIN(pAd);
8678                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8679        }
8680        else
8681        {       //A band
8682                if (BandWidth == BW_20)
8683                {
8684                        R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8685                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8686                }
8687                else
8688                {
8689                        R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8690                        RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8691                }
8692        }
8693
8694}
8695
8696VOID AsicTurnOffRFClk(
8697        IN PRTMP_ADAPTER pAd,
8698        IN      UCHAR           Channel)
8699{
8700
8701        // RF R2 bit 18 = 0
8702        UINT32                  R1 = 0, R2 = 0, R3 = 0;
8703        UCHAR                   index;
8704        RTMP_RF_REGS    *RFRegTable;
8705
8706        // The RF programming sequence is difference between 3xxx and 2xxx
8707        if (IS_RT3090(pAd))
8708        {
8709                RT30xxLoadRFSleepModeSetup(pAd);  // add by johnli,  RF power sequence setup, load RF sleep-mode setup
8710                return;
8711        }
8712
8713        RFRegTable = RF2850RegTable;
8714
8715        switch (pAd->RfIcType)
8716        {
8717                case RFIC_2820:
8718                case RFIC_2850:
8719                case RFIC_2720:
8720                case RFIC_2750:
8721
8722                        for (index = 0; index < NUM_OF_2850_CHNL; index++)
8723                        {
8724                                if (Channel == RFRegTable[index].Channel)
8725                                {
8726                                        R1 = RFRegTable[index].R1 & 0xffffdfff;
8727                                        R2 = RFRegTable[index].R2 & 0xfffbffff;
8728                                        R3 = RFRegTable[index].R3 & 0xfff3ffff;
8729
8730                                        RTMP_RF_IO_WRITE32(pAd, R1);
8731                                        RTMP_RF_IO_WRITE32(pAd, R2);
8732
8733                                        // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8734                                        // Set RF R2 bit18=0, R3 bit[18:19]=0
8735                                        //if (pAd->StaCfg.bRadio == FALSE)
8736                                        if (1)
8737                                        {
8738                                                RTMP_RF_IO_WRITE32(pAd, R3);
8739
8740                                                DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x,  R3 = 0x%08x \n",
8741                                                        Channel, pAd->RfIcType, R2, R3));
8742                                        }
8743                                        else
8744                                                DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8745                                                        Channel, pAd->RfIcType, R2));
8746                                        break;
8747                                }
8748                        }
8749                        break;
8750
8751                default:
8752                        break;
8753        }
8754}
8755
8756
8757VOID AsicTurnOnRFClk(
8758        IN PRTMP_ADAPTER pAd,
8759        IN      UCHAR                   Channel)
8760{
8761
8762        // RF R2 bit 18 = 0
8763        UINT32                  R1 = 0, R2 = 0, R3 = 0;
8764        UCHAR                   index;
8765        RTMP_RF_REGS    *RFRegTable;
8766
8767        // The RF programming sequence is difference between 3xxx and 2xxx
8768        if (IS_RT3090(pAd))
8769                return;
8770
8771        RFRegTable = RF2850RegTable;
8772
8773        switch (pAd->RfIcType)
8774        {
8775                case RFIC_2820:
8776                case RFIC_2850:
8777                case RFIC_2720:
8778                case RFIC_2750:
8779
8780                        for (index = 0; index < NUM_OF_2850_CHNL; index++)
8781                        {
8782                                if (Channel == RFRegTable[index].Channel)
8783                                {
8784                                        R3 = pAd->LatchRfRegs.R3;
8785                                        R3 &= 0xfff3ffff;
8786                                        R3 |= 0x00080000;
8787                                        RTMP_RF_IO_WRITE32(pAd, R3);
8788
8789                                        R1 = RFRegTable[index].R1;
8790                                        RTMP_RF_IO_WRITE32(pAd, R1);
8791
8792                                        R2 = RFRegTable[index].R2;
8793                                        if (pAd->Antenna.field.TxPath == 1)
8794                                        {
8795                                                R2 |= 0x4000;   // If TXpath is 1, bit 14 = 1;
8796                                        }
8797
8798                                        if (pAd->Antenna.field.RxPath == 2)
8799                                        {
8800                                                R2 |= 0x40;     // write 1 to off Rxpath.
8801                                        }
8802                                        else if (pAd->Antenna.field.RxPath == 1)
8803                                        {
8804                                                R2 |= 0x20040;  // write 1 to off RxPath
8805                                        }
8806                                        RTMP_RF_IO_WRITE32(pAd, R2);
8807
8808                                        break;
8809                                }
8810                        }
8811                        break;
8812
8813                default:
8814                        break;
8815        }
8816
8817        DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8818                Channel,
8819                pAd->RfIcType,
8820                R2));
8821}
8822
8823