linux/drivers/staging/rtl8188eu/core/rtw_mp.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 *published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 *
  19 ******************************************************************************/
  20#define _RTW_MP_C_
  21
  22#include <drv_types.h>
  23
  24#include "odm_precomp.h"
  25#include "rtl8188e_hal.h"
  26#include <linux/vmalloc.h>
  27
  28u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
  29{
  30        u32 val = 0;
  31
  32        switch (sz) {
  33        case 1:
  34                val = rtw_read8(padapter, addr);
  35                break;
  36        case 2:
  37                val = rtw_read16(padapter, addr);
  38                break;
  39        case 4:
  40                val = rtw_read32(padapter, addr);
  41                break;
  42        default:
  43                val = 0xffffffff;
  44                break;
  45        }
  46
  47        return val;
  48}
  49
  50void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz)
  51{
  52        switch (sz) {
  53        case 1:
  54                rtw_write8(padapter, addr, (u8)val);
  55                break;
  56        case 2:
  57                rtw_write16(padapter, addr, (u16)val);
  58                break;
  59        case 4:
  60                rtw_write32(padapter, addr, val);
  61                break;
  62        default:
  63                break;
  64        }
  65}
  66
  67u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask)
  68{
  69        return rtw_hal_read_bbreg(padapter, addr, bitmask);
  70}
  71
  72void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val)
  73{
  74        rtw_hal_write_bbreg(padapter, addr, bitmask, val);
  75}
  76
  77u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask)
  78{
  79        return rtw_hal_read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask);
  80}
  81
  82void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val)
  83{
  84        rtw_hal_write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask, val);
  85}
  86
  87u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr)
  88{
  89        return _read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask);
  90}
  91
  92void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val)
  93{
  94        _write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask, val);
  95}
  96
  97static void _init_mp_priv_(struct mp_priv *pmp_priv)
  98{
  99        struct wlan_bssid_ex *pnetwork;
 100
 101        _rtw_memset(pmp_priv, 0, sizeof(struct mp_priv));
 102
 103        pmp_priv->mode = MP_OFF;
 104
 105        pmp_priv->channel = 1;
 106        pmp_priv->bandwidth = HT_CHANNEL_WIDTH_20;
 107        pmp_priv->prime_channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 108        pmp_priv->rateidx = MPT_RATE_1M;
 109        pmp_priv->txpoweridx = 0x2A;
 110
 111        pmp_priv->antenna_tx = ANTENNA_A;
 112        pmp_priv->antenna_rx = ANTENNA_AB;
 113
 114        pmp_priv->check_mp_pkt = 0;
 115
 116        pmp_priv->tx_pktcount = 0;
 117
 118        pmp_priv->rx_pktcount = 0;
 119        pmp_priv->rx_crcerrpktcount = 0;
 120
 121        pmp_priv->network_macaddr[0] = 0x00;
 122        pmp_priv->network_macaddr[1] = 0xE0;
 123        pmp_priv->network_macaddr[2] = 0x4C;
 124        pmp_priv->network_macaddr[3] = 0x87;
 125        pmp_priv->network_macaddr[4] = 0x66;
 126        pmp_priv->network_macaddr[5] = 0x55;
 127
 128        pnetwork = &pmp_priv->mp_network.network;
 129        memcpy(pnetwork->MacAddress, pmp_priv->network_macaddr, ETH_ALEN);
 130
 131        pnetwork->Ssid.SsidLength = 8;
 132        memcpy(pnetwork->Ssid.Ssid, "mp_871x", pnetwork->Ssid.SsidLength);
 133}
 134
 135static void mp_init_xmit_attrib(struct mp_tx *pmptx, struct adapter *padapter)
 136{
 137        struct pkt_attrib *pattrib;
 138        struct tx_desc *desc;
 139
 140        /*  init xmitframe attribute */
 141        pattrib = &pmptx->attrib;
 142        _rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
 143        desc = &pmptx->desc;
 144        _rtw_memset(desc, 0, TXDESC_SIZE);
 145
 146        pattrib->ether_type = 0x8712;
 147        _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
 148        pattrib->ack_policy = 0;
 149        pattrib->hdrlen = WLAN_HDR_A3_LEN;
 150        pattrib->subtype = WIFI_DATA;
 151        pattrib->priority = 0;
 152        pattrib->qsel = pattrib->priority;
 153        pattrib->nr_frags = 1;
 154        pattrib->encrypt = 0;
 155        pattrib->bswenc = false;
 156        pattrib->qos_en = false;
 157}
 158
 159s32 init_mp_priv(struct adapter *padapter)
 160{
 161        struct mp_priv *pmppriv = &padapter->mppriv;
 162
 163        _init_mp_priv_(pmppriv);
 164        pmppriv->papdater = padapter;
 165
 166        pmppriv->tx.stop = 1;
 167        mp_init_xmit_attrib(&pmppriv->tx, padapter);
 168
 169        switch (padapter->registrypriv.rf_config) {
 170        case RF_1T1R:
 171                pmppriv->antenna_tx = ANTENNA_A;
 172                pmppriv->antenna_rx = ANTENNA_A;
 173                break;
 174        case RF_1T2R:
 175        default:
 176                pmppriv->antenna_tx = ANTENNA_A;
 177                pmppriv->antenna_rx = ANTENNA_AB;
 178                break;
 179        case RF_2T2R:
 180        case RF_2T2R_GREEN:
 181                pmppriv->antenna_tx = ANTENNA_AB;
 182                pmppriv->antenna_rx = ANTENNA_AB;
 183                break;
 184        case RF_2T4R:
 185                pmppriv->antenna_tx = ANTENNA_AB;
 186                pmppriv->antenna_rx = ANTENNA_ABCD;
 187                break;
 188        }
 189
 190        return _SUCCESS;
 191}
 192
 193void free_mp_priv(struct mp_priv *pmp_priv)
 194{
 195        kfree(pmp_priv->pallocated_mp_xmitframe_buf);
 196        pmp_priv->pallocated_mp_xmitframe_buf = NULL;
 197        pmp_priv->pmp_xmtframe_buf = NULL;
 198}
 199
 200#define PHY_IQCalibrate(a, b)   PHY_IQCalibrate_8188E(a, b)
 201#define PHY_LCCalibrate(a)      PHY_LCCalibrate_8188E(a)
 202#define PHY_SetRFPathSwitch(a, b) PHY_SetRFPathSwitch_8188E(a, b)
 203
 204s32 MPT_InitializeAdapter(struct adapter *pAdapter, u8 Channel)
 205{
 206        struct hal_data_8188e   *pHalData = GET_HAL_DATA(pAdapter);
 207        s32             rtStatus = _SUCCESS;
 208        struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
 209        struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv;
 210
 211        /*  HW Initialization for 8190 MPT. */
 212        /*  SW Initialization for 8190 MP. */
 213        pMptCtx->bMptDrvUnload = false;
 214        pMptCtx->bMassProdTest = false;
 215        pMptCtx->bMptIndexEven = true;  /* default gain index is -6.0db */
 216        pMptCtx->h2cReqNum = 0x0;
 217        /* Init mpt event. */
 218        /* init for BT MP */
 219
 220        pMptCtx->bMptWorkItemInProgress = false;
 221        pMptCtx->CurrMptAct = NULL;
 222        /*  */
 223
 224        /*  Don't accept any packets */
 225        rtw_write32(pAdapter, REG_RCR, 0);
 226
 227        PHY_IQCalibrate(pAdapter, false);
 228        dm_CheckTXPowerTracking(&pHalData->odmpriv);    /* trigger thermal meter */
 229        PHY_LCCalibrate(pAdapter);
 230
 231        pMptCtx->backup0xc50 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XAAGCCore1, bMaskByte0);
 232        pMptCtx->backup0xc58 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XBAGCCore1, bMaskByte0);
 233        pMptCtx->backup0xc30 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_RxDetector1, bMaskByte0);
 234        pMptCtx->backup0x52_RF_A = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
 235        pMptCtx->backup0x52_RF_B = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
 236
 237        /* set ant to wifi side in mp mode */
 238        rtw_write16(pAdapter, 0x870, 0x300);
 239        rtw_write16(pAdapter, 0x860, 0x110);
 240
 241        if (pAdapter->registrypriv.mp_mode == 1)
 242                pmlmepriv->fw_state = WIFI_MP_STATE;
 243
 244        return  rtStatus;
 245}
 246
 247/*-----------------------------------------------------------------------------
 248 * Function:    MPT_DeInitAdapter()
 249 *
 250 * Overview:    Extra DeInitialization for Mass Production Test.
 251 *
 252 * Input:               struct adapter *        pAdapter
 253 *
 254 * Output:              NONE
 255 *
 256 * Return:              NONE
 257 *
 258 * Revised History:
 259 *      When            Who             Remark
 260 *      05/08/2007      MHC             Create Version 0.
 261 *      05/18/2007      MHC             Add normal driver MPHalt code.
 262 *
 263 *---------------------------------------------------------------------------*/
 264void MPT_DeInitAdapter(struct adapter *pAdapter)
 265{
 266        struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
 267
 268        pMptCtx->bMptDrvUnload = true;
 269}
 270
 271static u8 mpt_ProStartTest(struct adapter *padapter)
 272{
 273        struct mpt_context *pMptCtx = &padapter->mppriv.MptCtx;
 274
 275        pMptCtx->bMassProdTest = true;
 276        pMptCtx->bStartContTx = false;
 277        pMptCtx->bCckContTx = false;
 278        pMptCtx->bOfdmContTx = false;
 279        pMptCtx->bSingleCarrier = false;
 280        pMptCtx->bCarrierSuppression = false;
 281        pMptCtx->bSingleTone = false;
 282
 283        return _SUCCESS;
 284}
 285
 286/*
 287 * General use
 288 */
 289s32 SetPowerTracking(struct adapter *padapter, u8 enable)
 290{
 291        Hal_SetPowerTracking(padapter, enable);
 292        return 0;
 293}
 294
 295void GetPowerTracking(struct adapter *padapter, u8 *enable)
 296{
 297        Hal_GetPowerTracking(padapter, enable);
 298}
 299
 300static void disable_dm(struct adapter *padapter)
 301{
 302        u8 v8;
 303
 304        /* 3 1. disable firmware dynamic mechanism */
 305        /*  disable Power Training, Rate Adaptive */
 306        v8 = rtw_read8(padapter, REG_BCN_CTRL);
 307        v8 &= ~EN_BCN_FUNCTION;
 308        rtw_write8(padapter, REG_BCN_CTRL, v8);
 309
 310        /* 3 2. disable driver dynamic mechanism */
 311        /*  disable Dynamic Initial Gain */
 312        /*  disable High Power */
 313        /*  disable Power Tracking */
 314        Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
 315
 316        /*  enable APK, LCK and IQK but disable power tracking */
 317        Switch_DM_Func(padapter, DYNAMIC_RF_CALIBRATION, true);
 318}
 319
 320/* This function initializes the DUT to the MP test mode */
 321s32 mp_start_test(struct adapter *padapter)
 322{
 323        struct wlan_bssid_ex bssid;
 324        struct sta_info *psta;
 325        u32 length;
 326        u8 val8;
 327        s32 res = _SUCCESS;
 328        struct mp_priv *pmppriv = &padapter->mppriv;
 329        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 330        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 331
 332        padapter->registrypriv.mp_mode = 1;
 333        pmppriv->bSetTxPower = 0;               /* for  manually set tx power */
 334
 335        /* 3 disable dynamic mechanism */
 336        disable_dm(padapter);
 337
 338        /* 3 0. update mp_priv */
 339
 340        if (padapter->registrypriv.rf_config == RF_819X_MAX_TYPE) {
 341                switch (GET_RF_TYPE(padapter)) {
 342                case RF_1T1R:
 343                        pmppriv->antenna_tx = ANTENNA_A;
 344                        pmppriv->antenna_rx = ANTENNA_A;
 345                        break;
 346                case RF_1T2R:
 347                default:
 348                        pmppriv->antenna_tx = ANTENNA_A;
 349                        pmppriv->antenna_rx = ANTENNA_AB;
 350                        break;
 351                case RF_2T2R:
 352                case RF_2T2R_GREEN:
 353                        pmppriv->antenna_tx = ANTENNA_AB;
 354                        pmppriv->antenna_rx = ANTENNA_AB;
 355                        break;
 356                case RF_2T4R:
 357                        pmppriv->antenna_tx = ANTENNA_AB;
 358                        pmppriv->antenna_rx = ANTENNA_ABCD;
 359                        break;
 360                }
 361        }
 362
 363        mpt_ProStartTest(padapter);
 364
 365        /* 3 1. initialize a new struct wlan_bssid_ex */
 366/*      _rtw_memset(&bssid, 0, sizeof(struct wlan_bssid_ex)); */
 367        memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
 368        bssid.Ssid.SsidLength = strlen("mp_pseudo_adhoc");
 369        memcpy(bssid.Ssid.Ssid, (u8 *)"mp_pseudo_adhoc", bssid.Ssid.SsidLength);
 370        bssid.InfrastructureMode = Ndis802_11IBSS;
 371        bssid.NetworkTypeInUse = Ndis802_11DS;
 372        bssid.IELength = 0;
 373
 374        length = get_wlan_bssid_ex_sz(&bssid);
 375        if (length % 4)
 376                bssid.Length = ((length >> 2) + 1) << 2; /* round up to multiple of 4 bytes. */
 377        else
 378                bssid.Length = length;
 379
 380        spin_lock_bh(&pmlmepriv->lock);
 381
 382        if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)
 383                goto end_of_mp_start_test;
 384
 385        /* init mp_start_test status */
 386        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
 387                rtw_disassoc_cmd(padapter, 500, true);
 388                rtw_indicate_disconnect(padapter);
 389                rtw_free_assoc_resources(padapter, 1);
 390        }
 391        pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
 392        if (padapter->registrypriv.mp_mode == 1)
 393                pmlmepriv->fw_state = WIFI_MP_STATE;
 394        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 395
 396        /* 3 2. create a new psta for mp driver */
 397        /* clear psta in the cur_network, if any */
 398        psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
 399        if (psta)
 400                rtw_free_stainfo(padapter, psta);
 401
 402        psta = rtw_alloc_stainfo(&padapter->stapriv, bssid.MacAddress);
 403        if (psta == NULL) {
 404                RT_TRACE(_module_mp_, _drv_err_, ("mp_start_test: Can't alloc sta_info!\n"));
 405                pmlmepriv->fw_state = pmppriv->prev_fw_state;
 406                res = _FAIL;
 407                goto end_of_mp_start_test;
 408        }
 409
 410        /* 3 3. join pseudo AdHoc */
 411        tgt_network->join_res = 1;
 412        tgt_network->aid = 1;
 413        psta->aid = 1;
 414        memcpy(&tgt_network->network, &bssid, length);
 415
 416        rtw_indicate_connect(padapter);
 417        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 418
 419end_of_mp_start_test:
 420
 421        spin_unlock_bh(&pmlmepriv->lock);
 422
 423        if (res == _SUCCESS) {
 424                /*  set MSR to WIFI_FW_ADHOC_STATE */
 425                val8 = rtw_read8(padapter, MSR) & 0xFC; /*  0x0102 */
 426                val8 |= WIFI_FW_ADHOC_STATE;
 427                rtw_write8(padapter, MSR, val8); /*  Link in ad hoc network */
 428        }
 429        return res;
 430}
 431/*  */
 432/* This function change the DUT from the MP test mode into normal mode */
 433void mp_stop_test(struct adapter *padapter)
 434{
 435        struct mp_priv *pmppriv = &padapter->mppriv;
 436        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 437        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 438        struct sta_info *psta;
 439
 440        if (pmppriv->mode == MP_ON) {
 441                pmppriv->bSetTxPower = 0;
 442                spin_lock_bh(&pmlmepriv->lock);
 443                if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)
 444                        goto end_of_mp_stop_test;
 445
 446                /* 3 1. disconnect pseudo AdHoc */
 447                rtw_indicate_disconnect(padapter);
 448
 449                /* 3 2. clear psta used in mp test mode. */
 450                psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
 451                if (psta)
 452                        rtw_free_stainfo(padapter, psta);
 453
 454                /* 3 3. return to normal state (default:station mode) */
 455                pmlmepriv->fw_state = pmppriv->prev_fw_state; /*  WIFI_STATION_STATE; */
 456
 457                /* flush the cur_network */
 458                _rtw_memset(tgt_network, 0, sizeof(struct wlan_network));
 459
 460                _clr_fwstate_(pmlmepriv, WIFI_MP_STATE);
 461
 462end_of_mp_stop_test:
 463
 464                spin_unlock_bh(&pmlmepriv->lock);
 465        }
 466}
 467
 468/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
 469/*
 470 * SetChannel
 471 * Description
 472 *      Use H2C command to change channel,
 473 *      not only modify rf register, but also other setting need to be done.
 474 */
 475void SetChannel(struct adapter *pAdapter)
 476{
 477        Hal_SetChannel(pAdapter);
 478}
 479
 480/*
 481 * Notice
 482 *      Switch bandwitdth may change center frequency(channel)
 483 */
 484void SetBandwidth(struct adapter *pAdapter)
 485{
 486        Hal_SetBandwidth(pAdapter);
 487}
 488
 489void SetAntenna(struct adapter *pAdapter)
 490{
 491        Hal_SetAntenna(pAdapter);
 492}
 493
 494void    SetAntennaPathPower(struct adapter *pAdapter)
 495{
 496        Hal_SetAntennaPathPower(pAdapter);
 497}
 498
 499void SetTxPower(struct adapter *pAdapter)
 500{
 501        Hal_SetTxPower(pAdapter);
 502        }
 503
 504void SetDataRate(struct adapter *pAdapter)
 505{
 506        Hal_SetDataRate(pAdapter);
 507}
 508
 509void MP_PHY_SetRFPathSwitch(struct adapter *pAdapter , bool bMain)
 510{
 511        PHY_SetRFPathSwitch(pAdapter, bMain);
 512}
 513
 514s32 SetThermalMeter(struct adapter *pAdapter, u8 target_ther)
 515{
 516        return Hal_SetThermalMeter(pAdapter, target_ther);
 517}
 518
 519void GetThermalMeter(struct adapter *pAdapter, u8 *value)
 520{
 521        Hal_GetThermalMeter(pAdapter, value);
 522}
 523
 524void SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart)
 525{
 526        PhySetTxPowerLevel(pAdapter);
 527        Hal_SetSingleCarrierTx(pAdapter, bStart);
 528}
 529
 530void SetSingleToneTx(struct adapter *pAdapter, u8 bStart)
 531{
 532        PhySetTxPowerLevel(pAdapter);
 533        Hal_SetSingleToneTx(pAdapter, bStart);
 534}
 535
 536void SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart)
 537{
 538        PhySetTxPowerLevel(pAdapter);
 539        Hal_SetCarrierSuppressionTx(pAdapter, bStart);
 540}
 541
 542void SetContinuousTx(struct adapter *pAdapter, u8 bStart)
 543{
 544        PhySetTxPowerLevel(pAdapter);
 545        Hal_SetContinuousTx(pAdapter, bStart);
 546}
 547
 548
 549void PhySetTxPowerLevel(struct adapter *pAdapter)
 550{
 551        struct mp_priv *pmp_priv = &pAdapter->mppriv;
 552
 553        if (pmp_priv->bSetTxPower == 0) /*  for NO manually set power index */
 554                PHY_SetTxPowerLevel8188E(pAdapter, pmp_priv->channel);
 555}
 556
 557/*  */
 558static void dump_mpframe(struct adapter *padapter, struct xmit_frame *pmpframe)
 559{
 560        rtw_hal_mgnt_xmit(padapter, pmpframe);
 561}
 562
 563static struct xmit_frame *alloc_mp_xmitframe(struct xmit_priv *pxmitpriv)
 564{
 565        struct xmit_frame       *pmpframe;
 566        struct xmit_buf *pxmitbuf;
 567
 568        pmpframe = rtw_alloc_xmitframe(pxmitpriv);
 569        if (pmpframe == NULL)
 570                return NULL;
 571
 572        pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
 573        if (pxmitbuf == NULL) {
 574                rtw_free_xmitframe(pxmitpriv, pmpframe);
 575                return NULL;
 576        }
 577
 578        pmpframe->frame_tag = MP_FRAMETAG;
 579
 580        pmpframe->pxmitbuf = pxmitbuf;
 581
 582        pmpframe->buf_addr = pxmitbuf->pbuf;
 583
 584        pxmitbuf->priv_data = pmpframe;
 585
 586        return pmpframe;
 587}
 588
 589static int mp_xmit_packet_thread(void *context)
 590{
 591        struct xmit_frame       *pxmitframe;
 592        struct mp_tx            *pmptx;
 593        struct mp_priv  *pmp_priv;
 594        struct xmit_priv        *pxmitpriv;
 595        struct adapter *padapter;
 596
 597        pmp_priv = (struct mp_priv *)context;
 598        pmptx = &pmp_priv->tx;
 599        padapter = pmp_priv->papdater;
 600        pxmitpriv = &(padapter->xmitpriv);
 601
 602        thread_enter("RTW_MP_THREAD");
 603
 604        /* DBG_88E("%s:pkTx Start\n", __func__); */
 605        while (1) {
 606                pxmitframe = alloc_mp_xmitframe(pxmitpriv);
 607                if (pxmitframe == NULL) {
 608                        if (pmptx->stop ||
 609                            padapter->bSurpriseRemoved ||
 610                            padapter->bDriverStopped) {
 611                                goto exit;
 612                        } else {
 613                                msleep(1);
 614                                continue;
 615                        }
 616                }
 617
 618                memcpy((u8 *)(pxmitframe->buf_addr+TXDESC_OFFSET), pmptx->buf, pmptx->write_size);
 619                memcpy(&(pxmitframe->attrib), &(pmptx->attrib), sizeof(struct pkt_attrib));
 620
 621                dump_mpframe(padapter, pxmitframe);
 622
 623                pmptx->sended++;
 624                pmp_priv->tx_pktcount++;
 625
 626                if (pmptx->stop ||
 627                    padapter->bSurpriseRemoved ||
 628                    padapter->bDriverStopped)
 629                        goto exit;
 630                if ((pmptx->count != 0) &&
 631                    (pmptx->count == pmptx->sended))
 632                        goto exit;
 633
 634                flush_signals_thread();
 635        }
 636
 637exit:
 638        kfree(pmptx->pallocated_buf);
 639        pmptx->pallocated_buf = NULL;
 640        pmptx->stop = 1;
 641
 642        complete_and_exit(NULL, 0);
 643}
 644
 645void fill_txdesc_for_mp(struct adapter *padapter, struct tx_desc *ptxdesc)
 646{
 647        struct mp_priv *pmp_priv = &padapter->mppriv;
 648        memcpy(ptxdesc, &(pmp_priv->tx.desc), TXDESC_SIZE);
 649}
 650
 651void SetPacketTx(struct adapter *padapter)
 652{
 653        u8 *ptr, *pkt_start, *pkt_end;
 654        u32 pkt_size;
 655        struct tx_desc *desc;
 656        struct rtw_ieee80211_hdr *hdr;
 657        u8 payload;
 658        s32 bmcast;
 659        struct pkt_attrib *pattrib;
 660        struct mp_priv *pmp_priv;
 661
 662
 663        pmp_priv = &padapter->mppriv;
 664        if (pmp_priv->tx.stop)
 665                return;
 666        pmp_priv->tx.sended = 0;
 667        pmp_priv->tx.stop = 0;
 668        pmp_priv->tx_pktcount = 0;
 669
 670        /* 3 1. update_attrib() */
 671        pattrib = &pmp_priv->tx.attrib;
 672        memcpy(pattrib->src, padapter->eeprompriv.mac_addr, ETH_ALEN);
 673        memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
 674        memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
 675        bmcast = IS_MCAST(pattrib->ra);
 676        if (bmcast) {
 677                pattrib->mac_id = 1;
 678                pattrib->psta = rtw_get_bcmc_stainfo(padapter);
 679        } else {
 680                pattrib->mac_id = 0;
 681                pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
 682        }
 683
 684        pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
 685
 686        /* 3 2. allocate xmit buffer */
 687        pkt_size = pattrib->last_txcmdsz;
 688
 689        kfree(pmp_priv->tx.pallocated_buf);
 690        pmp_priv->tx.write_size = pkt_size;
 691        pmp_priv->tx.buf_size = pkt_size + XMITBUF_ALIGN_SZ;
 692        pmp_priv->tx.pallocated_buf = rtw_zmalloc(pmp_priv->tx.buf_size);
 693        if (pmp_priv->tx.pallocated_buf == NULL) {
 694                DBG_88E("%s: malloc(%d) fail!!\n", __func__, pmp_priv->tx.buf_size);
 695                return;
 696        }
 697        pmp_priv->tx.buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pmp_priv->tx.pallocated_buf), XMITBUF_ALIGN_SZ);
 698        ptr = pmp_priv->tx.buf;
 699
 700        desc = &(pmp_priv->tx.desc);
 701        _rtw_memset(desc, 0, TXDESC_SIZE);
 702        pkt_start = ptr;
 703        pkt_end = pkt_start + pkt_size;
 704
 705        /* 3 3. init TX descriptor */
 706        /*  offset 0 */
 707        desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
 708        desc->txdw0 |= cpu_to_le32(pkt_size & 0x0000FFFF); /*  packet size */
 709        desc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00FF0000); /* 32 bytes for TX Desc */
 710        if (bmcast)
 711                desc->txdw0 |= cpu_to_le32(BMC); /*  broadcast packet */
 712
 713        desc->txdw1 |= cpu_to_le32((0x01 << 26) & 0xff000000);
 714        /*  offset 4 */
 715                desc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x3F); /* CAM_ID(MAC_ID) */
 716        desc->txdw1 |= cpu_to_le32((pattrib->qsel << QSEL_SHT) & 0x00001F00); /*  Queue Select, TID */
 717
 718        desc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); /*  Rate Adaptive ID */
 719        /*  offset 8 */
 720        /*  offset 12 */
 721
 722        desc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0x0fff0000);
 723
 724        /*  offset 16 */
 725        desc->txdw4 |= cpu_to_le32(HW_SSN);
 726        desc->txdw4 |= cpu_to_le32(USERATE);
 727        desc->txdw4 |= cpu_to_le32(DISDATAFB);
 728
 729        if (pmp_priv->preamble) {
 730                if (pmp_priv->rateidx <=  MPT_RATE_54M)
 731                        desc->txdw4 |= cpu_to_le32(DATA_SHORT); /*  CCK Short Preamble */
 732        }
 733        if (pmp_priv->bandwidth == HT_CHANNEL_WIDTH_40)
 734                desc->txdw4 |= cpu_to_le32(DATA_BW);
 735
 736        /*  offset 20 */
 737        desc->txdw5 |= cpu_to_le32(pmp_priv->rateidx & 0x0000001F);
 738
 739        if (pmp_priv->preamble) {
 740                if (pmp_priv->rateidx > MPT_RATE_54M)
 741                        desc->txdw5 |= cpu_to_le32(SGI); /*  MCS Short Guard Interval */
 742        }
 743        desc->txdw5 |= cpu_to_le32(RTY_LMT_EN); /*  retry limit enable */
 744        desc->txdw5 |= cpu_to_le32(0x00180000); /*  DATA/RTS Rate Fallback Limit */
 745
 746        /* 3 4. make wlan header, make_wlanhdr() */
 747        hdr = (struct rtw_ieee80211_hdr *)pkt_start;
 748        SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
 749        memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /*  DA */
 750        memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /*  SA */
 751        memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /*  RA, BSSID */
 752
 753        /* 3 5. make payload */
 754        ptr = pkt_start + pattrib->hdrlen;
 755
 756        switch (pmp_priv->tx.payload) {
 757        case 0:
 758                payload = 0x00;
 759                break;
 760        case 1:
 761                payload = 0x5a;
 762                break;
 763        case 2:
 764                payload = 0xa5;
 765                break;
 766        case 3:
 767                payload = 0xff;
 768                break;
 769        default:
 770                payload = 0x00;
 771                break;
 772        }
 773
 774        _rtw_memset(ptr, payload, pkt_end - ptr);
 775
 776        /* 3 6. start thread */
 777        pmp_priv->tx.PktTxThread = kthread_run(mp_xmit_packet_thread, pmp_priv, "RTW_MP_THREAD");
 778        if (IS_ERR(pmp_priv->tx.PktTxThread))
 779                DBG_88E("Create PktTx Thread Fail !!!!!\n");
 780}
 781
 782void SetPacketRx(struct adapter *pAdapter, u8 bStartRx)
 783{
 784        struct hal_data_8188e   *pHalData = GET_HAL_DATA(pAdapter);
 785
 786        if (bStartRx) {
 787                /*  Accept CRC error and destination address */
 788                pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | ADF | AMF | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS;
 789
 790                pHalData->ReceiveConfig |= ACRC32;
 791
 792                rtw_write32(pAdapter, REG_RCR, pHalData->ReceiveConfig);
 793
 794                /*  Accept all data frames */
 795                rtw_write16(pAdapter, REG_RXFLTMAP2, 0xFFFF);
 796        } else {
 797                rtw_write32(pAdapter, REG_RCR, 0);
 798        }
 799}
 800
 801void ResetPhyRxPktCount(struct adapter *pAdapter)
 802{
 803        u32 i, phyrx_set = 0;
 804
 805        for (i = 0; i <= 0xF; i++) {
 806                phyrx_set = 0;
 807                phyrx_set |= _RXERR_RPT_SEL(i); /* select */
 808                phyrx_set |= RXERR_RPT_RST;     /*  set counter to zero */
 809                rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
 810        }
 811}
 812
 813static u32 GetPhyRxPktCounts(struct adapter *pAdapter, u32 selbit)
 814{
 815        /* selection */
 816        u32 phyrx_set = 0, count = 0;
 817
 818        phyrx_set = _RXERR_RPT_SEL(selbit & 0xF);
 819        rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
 820
 821        /* Read packet count */
 822        count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK;
 823
 824        return count;
 825}
 826
 827u32 GetPhyRxPktReceived(struct adapter *pAdapter)
 828{
 829        u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
 830
 831        OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_OK);
 832        CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_OK);
 833        HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_OK);
 834
 835        return OFDM_cnt + CCK_cnt + HT_cnt;
 836}
 837
 838u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter)
 839{
 840        u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
 841
 842        OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_FAIL);
 843        CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_FAIL);
 844        HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_FAIL);
 845
 846        return OFDM_cnt + CCK_cnt + HT_cnt;
 847}
 848
 849/* reg 0x808[9:0]: FFT data x */
 850/* reg 0x808[22]:  0  -->  1  to get 1 FFT data y */
 851/* reg 0x8B4[15:0]: FFT data y report */
 852static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
 853{
 854        int psd_val;
 855
 856
 857        psd_val = rtw_read32(pAdapter, 0x808);
 858        psd_val &= 0xFFBFFC00;
 859        psd_val |= point;
 860
 861        rtw_write32(pAdapter, 0x808, psd_val);
 862        mdelay(1);
 863        psd_val |= 0x00400000;
 864
 865        rtw_write32(pAdapter, 0x808, psd_val);
 866        mdelay(1);
 867        psd_val = rtw_read32(pAdapter, 0x8B4);
 868
 869        psd_val &= 0x0000FFFF;
 870
 871        return psd_val;
 872}
 873
 874/*
 875 *pts   start_point_min         stop_point_max
 876 * 128  64                      64 + 128 = 192
 877 * 256  128                     128 + 256 = 384
 878 * 512  256                     256 + 512 = 768
 879 * 1024 512                     512 + 1024 = 1536
 880 *
 881 */
 882u32 mp_query_psd(struct adapter *pAdapter, u8 *data)
 883{
 884        u32 i, psd_pts = 0, psd_start = 0, psd_stop = 0;
 885        u32 psd_data = 0;
 886        int ret;
 887
 888        if (!netif_running(pAdapter->pnetdev)) {
 889                RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! interface not opened!\n"));
 890                return 0;
 891        }
 892
 893        if (check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE) == false) {
 894                RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! not in MP mode!\n"));
 895                return 0;
 896        }
 897
 898        if (strlen(data) == 0) { /* default value */
 899                psd_pts = 128;
 900                psd_start = 64;
 901                psd_stop = 128;
 902        } else {
 903                ret = sscanf(data, "pts =%d, start =%d, stop =%d",
 904                                &psd_pts, &psd_start, &psd_stop);
 905                if (ret != 3)
 906                        return 0;
 907        }
 908
 909        _rtw_memset(data, '\0', sizeof(*data));
 910
 911        i = psd_start;
 912        while (i < psd_stop) {
 913                if (i >= psd_pts) {
 914                        psd_data = rtw_GetPSDData(pAdapter, i-psd_pts);
 915                } else {
 916                        psd_data = rtw_GetPSDData(pAdapter, i);
 917                }
 918                sprintf(data, "%s%x ", data, psd_data);
 919                i++;
 920        }
 921
 922        msleep(100);
 923        return strlen(data)+1;
 924}
 925
 926void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv)
 927{
 928           int i, res;
 929          struct adapter *padapter = pxmitpriv->adapter;
 930        struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
 931
 932        u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
 933        u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
 934        if (padapter->registrypriv.mp_mode == 0) {
 935                max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
 936                num_xmit_extbuf = NR_XMIT_EXTBUFF;
 937        } else {
 938                max_xmit_extbuf_size = 20000;
 939                num_xmit_extbuf = 1;
 940        }
 941
 942        pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
 943        for (i = 0; i < num_xmit_extbuf; i++) {
 944                rtw_os_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ));
 945
 946                pxmitbuf++;
 947        }
 948
 949        if (pxmitpriv->pallocated_xmit_extbuf)
 950                vfree(pxmitpriv->pallocated_xmit_extbuf);
 951
 952        if (padapter->registrypriv.mp_mode == 0) {
 953                max_xmit_extbuf_size = 20000;
 954                num_xmit_extbuf = 1;
 955        } else {
 956                max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
 957                num_xmit_extbuf = NR_XMIT_EXTBUFF;
 958        }
 959
 960        /*  Init xmit extension buff */
 961        _rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
 962
 963        pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
 964
 965        if (pxmitpriv->pallocated_xmit_extbuf  == NULL) {
 966                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n"));
 967                res = _FAIL;
 968                goto exit;
 969        }
 970
 971        pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4);
 972
 973        pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
 974
 975        for (i = 0; i < num_xmit_extbuf; i++) {
 976                _rtw_init_listhead(&pxmitbuf->list);
 977
 978                pxmitbuf->priv_data = NULL;
 979                pxmitbuf->padapter = padapter;
 980                pxmitbuf->ext_tag = true;
 981
 982                res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
 983                if (res == _FAIL) {
 984                        res = _FAIL;
 985                        goto exit;
 986                }
 987
 988                rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
 989                pxmitbuf++;
 990        }
 991
 992        pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
 993
 994exit:
 995        ;
 996}
 997