linux/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
<<
>>
Prefs
   1/******************************************************************************
   2 * rtl871x_mp_ioctl.c
   3 *
   4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   5 * Linux device driver for RTL8192SU
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of version 2 of the GNU General Public License as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program; if not, write to the Free Software Foundation, Inc.,
  18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  19 *
  20 * Modifications for inclusion into the Linux staging tree are
  21 * Copyright(c) 2010 Larry Finger. All rights reserved.
  22 *
  23 * Contact information:
  24 * WLAN FAE <wlanfae@realtek.com>
  25 * Larry Finger <Larry.Finger@lwfinger.net>
  26 *
  27 ******************************************************************************/
  28
  29#include <linux/rndis.h>
  30#include "osdep_service.h"
  31#include "drv_types.h"
  32#include "mlme_osdep.h"
  33#include "rtl871x_mp.h"
  34#include "rtl871x_mp_ioctl.h"
  35
  36uint oid_null_function(struct oid_par_priv *poid_par_priv)
  37{
  38        return RNDIS_STATUS_SUCCESS;
  39}
  40
  41uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
  42{
  43        uint status = RNDIS_STATUS_SUCCESS;
  44        struct _adapter *Adapter = (struct _adapter *)
  45                                   (poid_par_priv->adapter_context);
  46
  47        if (poid_par_priv->type_of_oid == SET_OID) {
  48                if (poid_par_priv->information_buf_len >= sizeof(u8))
  49                        Adapter->registrypriv.wireless_mode =
  50                                        *(u8 *)poid_par_priv->information_buf;
  51                else
  52                        status = RNDIS_STATUS_INVALID_LENGTH;
  53        } else if (poid_par_priv->type_of_oid == QUERY_OID) {
  54                if (poid_par_priv->information_buf_len >= sizeof(u8)) {
  55                        *(u8 *)poid_par_priv->information_buf =
  56                                         Adapter->registrypriv.wireless_mode;
  57                        *poid_par_priv->bytes_rw =
  58                                        poid_par_priv->information_buf_len;
  59                } else {
  60                        status = RNDIS_STATUS_INVALID_LENGTH;
  61                }
  62        } else {
  63                status = RNDIS_STATUS_NOT_ACCEPTED;
  64        }
  65        return status;
  66}
  67
  68uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
  69{
  70        struct _adapter *Adapter = (struct _adapter *)
  71                                   (poid_par_priv->adapter_context);
  72        struct bb_reg_param *pbbreg;
  73        u16 offset;
  74        u32 value;
  75
  76        if (poid_par_priv->type_of_oid != SET_OID)
  77                return RNDIS_STATUS_NOT_ACCEPTED;
  78        if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
  79                return RNDIS_STATUS_INVALID_LENGTH;
  80        pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
  81        offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
  82        if (offset < BB_REG_BASE_ADDR)
  83                offset |= BB_REG_BASE_ADDR;
  84        value = pbbreg->value;
  85        r8712_bb_reg_write(Adapter, offset, value);
  86        return RNDIS_STATUS_SUCCESS;
  87}
  88
  89uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
  90{
  91        struct _adapter *Adapter = (struct _adapter *)
  92                                   (poid_par_priv->adapter_context);
  93        struct bb_reg_param *pbbreg;
  94        u16 offset;
  95        u32 value;
  96
  97        if (poid_par_priv->type_of_oid != QUERY_OID)
  98                return RNDIS_STATUS_NOT_ACCEPTED;
  99        if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
 100                return RNDIS_STATUS_INVALID_LENGTH;
 101        pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
 102        offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
 103        if (offset < BB_REG_BASE_ADDR)
 104                offset |= BB_REG_BASE_ADDR;
 105        value = r8712_bb_reg_read(Adapter, offset);
 106        pbbreg->value = value;
 107        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 108        return RNDIS_STATUS_SUCCESS;
 109}
 110
 111uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
 112{
 113        struct _adapter *Adapter = (struct _adapter *)
 114                                   (poid_par_priv->adapter_context);
 115        struct rf_reg_param *pbbreg;
 116        u8 path;
 117        u8 offset;
 118        u32 value;
 119
 120        if (poid_par_priv->type_of_oid != SET_OID)
 121                return RNDIS_STATUS_NOT_ACCEPTED;
 122        if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
 123                return RNDIS_STATUS_INVALID_LENGTH;
 124        pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
 125        path = (u8)pbbreg->path;
 126        if (path > RF_PATH_B)
 127                return RNDIS_STATUS_NOT_ACCEPTED;
 128        offset = (u8)pbbreg->offset;
 129        value = pbbreg->value;
 130        r8712_rf_reg_write(Adapter, path, offset, value);
 131        return RNDIS_STATUS_SUCCESS;
 132}
 133
 134uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
 135{
 136        struct _adapter *Adapter = (struct _adapter *)
 137                                   (poid_par_priv->adapter_context);
 138        struct rf_reg_param *pbbreg;
 139        u8 path;
 140        u8 offset;
 141        u32 value;
 142
 143        if (poid_par_priv->type_of_oid != QUERY_OID)
 144                return RNDIS_STATUS_NOT_ACCEPTED;
 145        if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
 146                return RNDIS_STATUS_INVALID_LENGTH;
 147        pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
 148        path = (u8)pbbreg->path;
 149        if (path > RF_PATH_B) /* 1T2R  path_a /path_b */
 150                return RNDIS_STATUS_NOT_ACCEPTED;
 151        offset = (u8)pbbreg->offset;
 152        value = r8712_rf_reg_read(Adapter, path, offset);
 153        pbbreg->value = value;
 154        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 155        return RNDIS_STATUS_SUCCESS;
 156}
 157
 158/*This function initializes the DUT to the MP test mode*/
 159static int mp_start_test(struct _adapter *padapter)
 160{
 161        struct mp_priv *pmppriv = &padapter->mppriv;
 162        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 163        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 164        struct wlan_bssid_ex bssid;
 165        struct sta_info *psta;
 166        unsigned long length;
 167        unsigned long irqL;
 168        int res = _SUCCESS;
 169
 170        /* 3 1. initialize a new struct wlan_bssid_ex */
 171        memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
 172        bssid.Ssid.SsidLength = 16;
 173        memcpy(bssid.Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc",
 174                bssid.Ssid.SsidLength);
 175        bssid.InfrastructureMode = Ndis802_11IBSS;
 176        bssid.NetworkTypeInUse = Ndis802_11DS;
 177        bssid.IELength = 0;
 178        length = r8712_get_wlan_bssid_ex_sz(&bssid);
 179        if (length % 4) {
 180                /*round up to multiple of 4 bytes.*/
 181                bssid.Length = ((length >> 2) + 1) << 2;
 182        } else {
 183                bssid.Length = length;
 184        }
 185        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 186        if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
 187                goto end_of_mp_start_test;
 188        /*init mp_start_test status*/
 189        pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
 190        pmlmepriv->fw_state = WIFI_MP_STATE;
 191        if (pmppriv->mode == _LOOPBOOK_MODE_)
 192                set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); /*append txdesc*/
 193        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 194        /* 3 2. create a new psta for mp driver */
 195        /* clear psta in the cur_network, if any */
 196        psta = r8712_get_stainfo(&padapter->stapriv,
 197                                 tgt_network->network.MacAddress);
 198        if (psta)
 199                r8712_free_stainfo(padapter, psta);
 200        psta = r8712_alloc_stainfo(&padapter->stapriv, bssid.MacAddress);
 201        if (psta == NULL) {
 202                res = _FAIL;
 203                goto end_of_mp_start_test;
 204        }
 205        /* 3 3. join psudo AdHoc */
 206        tgt_network->join_res = 1;
 207        tgt_network->aid = psta->aid = 1;
 208        memcpy(&tgt_network->network, &bssid, length);
 209        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 210        r8712_os_indicate_connect(padapter);
 211        /* Set to LINKED STATE for MP TRX Testing */
 212        set_fwstate(pmlmepriv, _FW_LINKED);
 213end_of_mp_start_test:
 214        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 215        return res;
 216}
 217
 218/*This function change the DUT from the MP test mode into normal mode */
 219static int mp_stop_test(struct _adapter *padapter)
 220{
 221        struct mp_priv *pmppriv = &padapter->mppriv;
 222        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 223        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 224        struct sta_info *psta;
 225        unsigned long irqL;
 226
 227        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 228        if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
 229                goto end_of_mp_stop_test;
 230        /* 3 1. disconnect psudo AdHoc */
 231        r8712_os_indicate_disconnect(padapter);
 232        /* 3 2. clear psta used in mp test mode. */
 233        psta = r8712_get_stainfo(&padapter->stapriv,
 234                                 tgt_network->network.MacAddress);
 235        if (psta)
 236                r8712_free_stainfo(padapter, psta);
 237        /* 3 3. return to normal state (default:station mode) */
 238        pmlmepriv->fw_state = pmppriv->prev_fw_state; /* WIFI_STATION_STATE;*/
 239        /*flush the cur_network*/
 240        memset(tgt_network, 0, sizeof(struct wlan_network));
 241end_of_mp_stop_test:
 242        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 243        return _SUCCESS;
 244}
 245
 246int mp_start_joinbss(struct _adapter *padapter, struct ndis_802_11_ssid *pssid)
 247{
 248        struct mp_priv *pmppriv = &padapter->mppriv;
 249        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 250        unsigned char res = _SUCCESS;
 251
 252        if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
 253                return _FAIL;
 254        if (!check_fwstate(pmlmepriv, _FW_LINKED))
 255                return _FAIL;
 256        _clr_fwstate_(pmlmepriv, _FW_LINKED);
 257        res = r8712_setassocsta_cmd(padapter, pmppriv->network_macaddr);
 258        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 259        return res;
 260}
 261
 262uint oid_rt_pro_set_data_rate_hdl(struct oid_par_priv
 263                                         *poid_par_priv)
 264{
 265        struct _adapter *Adapter = (struct _adapter *)
 266                                   (poid_par_priv->adapter_context);
 267        u32 ratevalue;
 268
 269        if (poid_par_priv->type_of_oid != SET_OID)
 270                return RNDIS_STATUS_NOT_ACCEPTED;
 271        if (poid_par_priv->information_buf_len != sizeof(u32))
 272                return RNDIS_STATUS_INVALID_LENGTH;
 273        ratevalue = *((u32 *)poid_par_priv->information_buf);
 274        if (ratevalue >= MPT_RATE_LAST)
 275                return RNDIS_STATUS_INVALID_DATA;
 276        Adapter->mppriv.curr_rateidx = ratevalue;
 277        r8712_SetDataRate(Adapter);
 278        return RNDIS_STATUS_SUCCESS;
 279}
 280
 281uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
 282{
 283        struct _adapter *Adapter = (struct _adapter *)
 284                                   (poid_par_priv->adapter_context);
 285        uint status = RNDIS_STATUS_SUCCESS;
 286        u32 mode;
 287        u8 val8;
 288
 289        if (poid_par_priv->type_of_oid != SET_OID)
 290                return  RNDIS_STATUS_NOT_ACCEPTED;
 291        mode = *((u32 *)poid_par_priv->information_buf);
 292        Adapter->mppriv.mode = mode;/* 1 for loopback*/
 293        if (mp_start_test(Adapter) == _FAIL)
 294                status = RNDIS_STATUS_NOT_ACCEPTED;
 295        r8712_write8(Adapter, MSR, 1); /* Link in ad hoc network, 0x1025004C */
 296        r8712_write8(Adapter, RCR, 0); /* RCR : disable all pkt, 0x10250048 */
 297        /* RCR disable Check BSSID, 0x1025004a */
 298        r8712_write8(Adapter, RCR + 2, 0x57);
 299        /* disable RX filter map , mgt frames will put in RX FIFO 0 */
 300        r8712_write16(Adapter, RXFLTMAP0, 0x0);
 301        val8 = r8712_read8(Adapter, EE_9346CR);
 302        if (!(val8 & _9356SEL)) { /*boot from EFUSE*/
 303                r8712_efuse_reg_init(Adapter);
 304                r8712_efuse_change_max_size(Adapter);
 305                r8712_efuse_reg_uninit(Adapter);
 306        }
 307        return status;
 308}
 309
 310uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
 311{
 312        struct _adapter *Adapter = (struct _adapter *)
 313                                   (poid_par_priv->adapter_context);
 314        uint status = RNDIS_STATUS_SUCCESS;
 315
 316        if (poid_par_priv->type_of_oid != SET_OID)
 317                return RNDIS_STATUS_NOT_ACCEPTED;
 318        if (mp_stop_test(Adapter) == _FAIL)
 319                status = RNDIS_STATUS_NOT_ACCEPTED;
 320        return status;
 321}
 322
 323uint oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv
 324                                                   *poid_par_priv)
 325{
 326        struct _adapter *Adapter = (struct _adapter *)
 327                                   (poid_par_priv->adapter_context);
 328        u32             Channel;
 329
 330        if (poid_par_priv->type_of_oid != SET_OID)
 331                return RNDIS_STATUS_NOT_ACCEPTED;
 332        if (poid_par_priv->information_buf_len != sizeof(u32))
 333                return RNDIS_STATUS_INVALID_LENGTH;
 334        Channel = *((u32 *)poid_par_priv->information_buf);
 335        if (Channel > 14)
 336                return RNDIS_STATUS_NOT_ACCEPTED;
 337        Adapter->mppriv.curr_ch = Channel;
 338        r8712_SetChannel(Adapter);
 339        return RNDIS_STATUS_SUCCESS;
 340}
 341
 342uint oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
 343{
 344        struct _adapter *Adapter = (struct _adapter *)
 345                                   (poid_par_priv->adapter_context);
 346        u32 antenna;
 347
 348        if (poid_par_priv->type_of_oid != SET_OID)
 349                return RNDIS_STATUS_NOT_ACCEPTED;
 350        if (poid_par_priv->information_buf_len != sizeof(u32))
 351                return RNDIS_STATUS_INVALID_LENGTH;
 352        antenna = *((u32 *)poid_par_priv->information_buf);
 353        Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16);
 354        Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF);
 355        r8712_SwitchAntenna(Adapter);
 356        return RNDIS_STATUS_SUCCESS;
 357}
 358
 359uint oid_rt_pro_set_tx_power_control_hdl(
 360                                        struct oid_par_priv *poid_par_priv)
 361{
 362        struct _adapter *Adapter = (struct _adapter *)
 363                                   (poid_par_priv->adapter_context);
 364        u32 tx_pwr_idx;
 365
 366        if (poid_par_priv->type_of_oid != SET_OID)
 367                return RNDIS_STATUS_NOT_ACCEPTED;
 368        if (poid_par_priv->information_buf_len != sizeof(u32))
 369                return RNDIS_STATUS_INVALID_LENGTH;
 370        tx_pwr_idx = *((u32 *)poid_par_priv->information_buf);
 371        if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE)
 372                return RNDIS_STATUS_NOT_ACCEPTED;
 373        Adapter->mppriv.curr_txpoweridx = (u8)tx_pwr_idx;
 374        r8712_SetTxPower(Adapter);
 375        return RNDIS_STATUS_SUCCESS;
 376}
 377
 378uint oid_rt_pro_query_tx_packet_sent_hdl(
 379                                        struct oid_par_priv *poid_par_priv)
 380{
 381        uint status = RNDIS_STATUS_SUCCESS;
 382        struct _adapter *Adapter = (struct _adapter *)
 383                                   (poid_par_priv->adapter_context);
 384
 385        if (poid_par_priv->type_of_oid != QUERY_OID) {
 386                status = RNDIS_STATUS_NOT_ACCEPTED;
 387                return status;
 388        }
 389        if (poid_par_priv->information_buf_len == sizeof(u32)) {
 390                *(u32 *)poid_par_priv->information_buf =
 391                                        Adapter->mppriv.tx_pktcount;
 392                *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 393        } else {
 394                status = RNDIS_STATUS_INVALID_LENGTH;
 395        }
 396        return status;
 397}
 398
 399uint oid_rt_pro_query_rx_packet_received_hdl(
 400                                        struct oid_par_priv *poid_par_priv)
 401{
 402        uint status = RNDIS_STATUS_SUCCESS;
 403        struct _adapter *Adapter = (struct _adapter *)
 404                                   (poid_par_priv->adapter_context);
 405
 406        if (poid_par_priv->type_of_oid != QUERY_OID) {
 407                status = RNDIS_STATUS_NOT_ACCEPTED;
 408                return status;
 409        }
 410        if (poid_par_priv->information_buf_len == sizeof(u32)) {
 411                *(u32 *)poid_par_priv->information_buf =
 412                                        Adapter->mppriv.rx_pktcount;
 413                *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 414        } else {
 415                status = RNDIS_STATUS_INVALID_LENGTH;
 416        }
 417        return status;
 418}
 419
 420uint oid_rt_pro_query_rx_packet_crc32_error_hdl(
 421                                        struct oid_par_priv *poid_par_priv)
 422{
 423        uint status = RNDIS_STATUS_SUCCESS;
 424        struct _adapter *Adapter = (struct _adapter *)
 425                                   (poid_par_priv->adapter_context);
 426
 427        if (poid_par_priv->type_of_oid != QUERY_OID) {
 428                status = RNDIS_STATUS_NOT_ACCEPTED;
 429                return status;
 430        }
 431        if (poid_par_priv->information_buf_len == sizeof(u32)) {
 432                *(u32 *)poid_par_priv->information_buf =
 433                                        Adapter->mppriv.rx_crcerrpktcount;
 434                *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 435        } else {
 436                status = RNDIS_STATUS_INVALID_LENGTH;
 437        }
 438        return status;
 439}
 440
 441uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv
 442                                                *poid_par_priv)
 443{
 444        struct _adapter *Adapter = (struct _adapter *)
 445                                   (poid_par_priv->adapter_context);
 446
 447        if (poid_par_priv->type_of_oid != SET_OID)
 448                return RNDIS_STATUS_NOT_ACCEPTED;
 449        Adapter->mppriv.tx_pktcount = 0;
 450        return RNDIS_STATUS_SUCCESS;
 451}
 452
 453uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv
 454                                                    *poid_par_priv)
 455{
 456        uint status = RNDIS_STATUS_SUCCESS;
 457        struct _adapter *Adapter = (struct _adapter *)
 458                                   (poid_par_priv->adapter_context);
 459
 460        if (poid_par_priv->type_of_oid != SET_OID)
 461                return RNDIS_STATUS_NOT_ACCEPTED;
 462        if (poid_par_priv->information_buf_len == sizeof(u32)) {
 463                Adapter->mppriv.rx_pktcount = 0;
 464                Adapter->mppriv.rx_crcerrpktcount = 0;
 465        } else {
 466                status = RNDIS_STATUS_INVALID_LENGTH;
 467        }
 468        return status;
 469}
 470
 471uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv
 472                                                 *poid_par_priv)
 473{
 474        struct _adapter *Adapter = (struct _adapter *)
 475                                   (poid_par_priv->adapter_context);
 476
 477        if (poid_par_priv->type_of_oid != SET_OID)
 478                return RNDIS_STATUS_NOT_ACCEPTED;
 479        r8712_ResetPhyRxPktCount(Adapter);
 480        return RNDIS_STATUS_SUCCESS;
 481}
 482
 483uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv
 484                                                  *poid_par_priv)
 485{
 486        struct _adapter *Adapter = (struct _adapter *)
 487                                   (poid_par_priv->adapter_context);
 488
 489        if (poid_par_priv->type_of_oid != QUERY_OID)
 490                return RNDIS_STATUS_NOT_ACCEPTED;
 491        if (poid_par_priv->information_buf_len != sizeof(u32))
 492                return RNDIS_STATUS_INVALID_LENGTH;
 493        *(u32 *)poid_par_priv->information_buf =
 494                                         r8712_GetPhyRxPktReceived(Adapter);
 495        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 496        return RNDIS_STATUS_SUCCESS;
 497}
 498
 499uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv
 500                                                     *poid_par_priv)
 501{
 502        struct _adapter *Adapter = (struct _adapter *)
 503                                   (poid_par_priv->adapter_context);
 504
 505        if (poid_par_priv->type_of_oid != QUERY_OID)
 506                return RNDIS_STATUS_NOT_ACCEPTED;
 507        if (poid_par_priv->information_buf_len != sizeof(u32))
 508                return RNDIS_STATUS_INVALID_LENGTH;
 509        *(u32 *)poid_par_priv->information_buf =
 510                                         r8712_GetPhyRxPktCRC32Error(Adapter);
 511        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 512        return RNDIS_STATUS_SUCCESS;
 513}
 514
 515uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv
 516                                          *poid_par_priv)
 517{
 518        struct _adapter *Adapter = (struct _adapter *)
 519                                   (poid_par_priv->adapter_context);
 520
 521        if (poid_par_priv->type_of_oid != SET_OID)
 522                return RNDIS_STATUS_NOT_ACCEPTED;
 523
 524        Adapter->mppriv.curr_modem = *((u8 *)poid_par_priv->information_buf);
 525        return RNDIS_STATUS_SUCCESS;
 526}
 527
 528uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv
 529                                             *poid_par_priv)
 530{
 531        struct _adapter *Adapter = (struct _adapter *)
 532                                   (poid_par_priv->adapter_context);
 533        u32             bStartTest;
 534
 535        if (poid_par_priv->type_of_oid != SET_OID)
 536                return RNDIS_STATUS_NOT_ACCEPTED;
 537        bStartTest = *((u32 *)poid_par_priv->information_buf);
 538        r8712_SetContinuousTx(Adapter, (u8)bStartTest);
 539        return RNDIS_STATUS_SUCCESS;
 540}
 541
 542uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv
 543                                                 *poid_par_priv)
 544{
 545        struct _adapter *Adapter = (struct _adapter *)
 546                                   (poid_par_priv->adapter_context);
 547        u32             bStartTest;
 548
 549        if (poid_par_priv->type_of_oid != SET_OID)
 550                return RNDIS_STATUS_NOT_ACCEPTED;
 551        bStartTest = *((u32 *)poid_par_priv->information_buf);
 552        r8712_SetSingleCarrierTx(Adapter, (u8)bStartTest);
 553        return RNDIS_STATUS_SUCCESS;
 554}
 555
 556uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv
 557                                                      *poid_par_priv)
 558{
 559        struct _adapter *Adapter = (struct _adapter *)
 560                                   (poid_par_priv->adapter_context);
 561        u32             bStartTest;
 562
 563        if (poid_par_priv->type_of_oid != SET_OID)
 564                return RNDIS_STATUS_NOT_ACCEPTED;
 565        bStartTest = *((u32 *)poid_par_priv->information_buf);
 566        r8712_SetCarrierSuppressionTx(Adapter, (u8)bStartTest);
 567        return RNDIS_STATUS_SUCCESS;
 568}
 569
 570uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv
 571                                              *poid_par_priv)
 572{
 573        struct _adapter *Adapter = (struct _adapter *)
 574                                   (poid_par_priv->adapter_context);
 575        u32             bStartTest;
 576
 577        if (poid_par_priv->type_of_oid != SET_OID)
 578                return RNDIS_STATUS_NOT_ACCEPTED;
 579        bStartTest = *((u32 *)poid_par_priv->information_buf);
 580        r8712_SetSingleToneTx(Adapter, (u8)bStartTest);
 581        return RNDIS_STATUS_SUCCESS;
 582}
 583
 584uint oid_rt_pro_read_register_hdl(struct oid_par_priv
 585                                         *poid_par_priv)
 586{
 587        struct _adapter *Adapter = (struct _adapter *)
 588                                   (poid_par_priv->adapter_context);
 589        uint status = RNDIS_STATUS_SUCCESS;
 590        struct mp_rw_reg *RegRWStruct;
 591        u16             offset;
 592
 593        if (poid_par_priv->type_of_oid != QUERY_OID)
 594                return RNDIS_STATUS_NOT_ACCEPTED;
 595        RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
 596        if ((RegRWStruct->offset >= 0x10250800) &&
 597            (RegRWStruct->offset <= 0x10250FFF)) {
 598                /*baseband register*/
 599                /*0ffset :0x800~0xfff*/
 600                offset = (u16)(RegRWStruct->offset) & 0xFFF;
 601                RegRWStruct->value = r8712_bb_reg_read(Adapter, offset);
 602        } else {
 603                switch (RegRWStruct->width) {
 604                case 1:
 605                        RegRWStruct->value = r8712_read8(Adapter,
 606                                                   RegRWStruct->offset);
 607                        break;
 608                case 2:
 609                        RegRWStruct->value = r8712_read16(Adapter,
 610                                                    RegRWStruct->offset);
 611                        break;
 612                case 4:
 613                        RegRWStruct->value = r8712_read32(Adapter,
 614                                                    RegRWStruct->offset);
 615                        break;
 616                default:
 617                        status = RNDIS_STATUS_NOT_ACCEPTED;
 618                        break;
 619                }
 620        }
 621        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 622        return status;
 623}
 624
 625uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
 626{
 627        struct _adapter *Adapter = (struct _adapter *)
 628                                   (poid_par_priv->adapter_context);
 629        uint status = RNDIS_STATUS_SUCCESS;
 630        struct mp_rw_reg *RegRWStruct;
 631        u16             offset;
 632        u32             value;
 633        u32 oldValue = 0;
 634
 635        if (poid_par_priv->type_of_oid != SET_OID)
 636                return RNDIS_STATUS_NOT_ACCEPTED;
 637        RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
 638        if ((RegRWStruct->offset >= 0x10250800) &&
 639            (RegRWStruct->offset <= 0x10250FFF)) {
 640                /*baseband register*/
 641                offset = (u16)(RegRWStruct->offset) & 0xFFF;
 642                value = RegRWStruct->value;
 643                switch (RegRWStruct->width) {
 644                case 1:
 645                        oldValue = r8712_bb_reg_read(Adapter, offset);
 646                        oldValue &= 0xFFFFFF00;
 647                        value &= 0x000000FF;
 648                        value |= oldValue;
 649                        break;
 650                case 2:
 651                        oldValue = r8712_bb_reg_read(Adapter, offset);
 652                        oldValue &= 0xFFFF0000;
 653                        value &= 0x0000FFFF;
 654                        value |= oldValue;
 655                        break;
 656                }
 657                r8712_bb_reg_write(Adapter, offset, value);
 658        } else {
 659                switch (RegRWStruct->width) {
 660                case 1:
 661                        r8712_write8(Adapter, RegRWStruct->offset,
 662                               (unsigned char)RegRWStruct->value);
 663                        break;
 664                case 2:
 665                        r8712_write16(Adapter, RegRWStruct->offset,
 666                                (unsigned short)RegRWStruct->value);
 667                        break;
 668                case 4:
 669                        r8712_write32(Adapter, RegRWStruct->offset,
 670                                (unsigned int)RegRWStruct->value);
 671                        break;
 672                default:
 673                        status = RNDIS_STATUS_NOT_ACCEPTED;
 674                        break;
 675                }
 676
 677                if ((status == RNDIS_STATUS_SUCCESS) &&
 678                    (RegRWStruct->offset == HIMR) &&
 679                    (RegRWStruct->width == 4))
 680                        Adapter->ImrContent = RegRWStruct->value;
 681        }
 682        return status;
 683}
 684
 685uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
 686{
 687        struct _adapter *Adapter = (struct _adapter *)
 688                                   (poid_par_priv->adapter_context);
 689
 690        if (poid_par_priv->type_of_oid != QUERY_OID)
 691                return RNDIS_STATUS_NOT_ACCEPTED;
 692
 693        if (Adapter->mppriv.act_in_progress)
 694                return RNDIS_STATUS_NOT_ACCEPTED;
 695
 696        if (poid_par_priv->information_buf_len < sizeof(u8))
 697                return RNDIS_STATUS_INVALID_LENGTH;
 698        /*init workparam*/
 699        Adapter->mppriv.act_in_progress = true;
 700        Adapter->mppriv.workparam.bcompleted = false;
 701        Adapter->mppriv.workparam.act_type = MPT_GET_THERMAL_METER;
 702        Adapter->mppriv.workparam.io_offset = 0;
 703        Adapter->mppriv.workparam.io_value = 0xFFFFFFFF;
 704        r8712_GetThermalMeter(Adapter, &Adapter->mppriv.workparam.io_value);
 705        Adapter->mppriv.workparam.bcompleted = true;
 706        Adapter->mppriv.act_in_progress = false;
 707        *(u32 *)poid_par_priv->information_buf =
 708                                 Adapter->mppriv.workparam.io_value;
 709        *poid_par_priv->bytes_rw = sizeof(u32);
 710        return RNDIS_STATUS_SUCCESS;
 711}
 712
 713uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
 714{
 715        struct _adapter *Adapter = (struct _adapter *)
 716                                   (poid_par_priv->adapter_context);
 717
 718        uint status = RNDIS_STATUS_SUCCESS;
 719
 720        struct EFUSE_ACCESS_STRUCT *pefuse;
 721        u8 *data;
 722        u16 addr = 0, cnts = 0;
 723
 724        if (poid_par_priv->type_of_oid != QUERY_OID)
 725                return RNDIS_STATUS_NOT_ACCEPTED;
 726        if (poid_par_priv->information_buf_len <
 727            sizeof(struct EFUSE_ACCESS_STRUCT))
 728                return RNDIS_STATUS_INVALID_LENGTH;
 729        pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
 730        addr = pefuse->start_addr;
 731        cnts = pefuse->cnts;
 732        data = pefuse->data;
 733        memset(data, 0xFF, cnts);
 734        if ((addr > 511) || (cnts < 1) || (cnts > 512) || (addr + cnts) >
 735             EFUSE_MAX_SIZE)
 736                return RNDIS_STATUS_NOT_ACCEPTED;
 737        if (!r8712_efuse_access(Adapter, true, addr, cnts, data))
 738                status = RNDIS_STATUS_FAILURE;
 739        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 740        return status;
 741}
 742/*------------------------------------------------------------------------*/
 743uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
 744{
 745        struct _adapter *Adapter = (struct _adapter *)
 746                                   (poid_par_priv->adapter_context);
 747
 748        uint status = RNDIS_STATUS_SUCCESS;
 749
 750        struct EFUSE_ACCESS_STRUCT *pefuse;
 751        u8 *data;
 752        u16 addr = 0, cnts = 0;
 753
 754        if (poid_par_priv->type_of_oid != SET_OID)
 755                return RNDIS_STATUS_NOT_ACCEPTED;
 756
 757        pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
 758        addr = pefuse->start_addr;
 759        cnts = pefuse->cnts;
 760        data = pefuse->data;
 761
 762        if ((addr > 511) || (cnts < 1) || (cnts > 512) ||
 763            (addr + cnts) > r8712_efuse_get_max_size(Adapter))
 764                return RNDIS_STATUS_NOT_ACCEPTED;
 765        if (!r8712_efuse_access(Adapter, false, addr, cnts, data))
 766                status = RNDIS_STATUS_FAILURE;
 767        return status;
 768}
 769/*----------------------------------------------------------------------*/
 770
 771uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv
 772                                              *poid_par_priv)
 773{
 774        struct _adapter *Adapter = (struct _adapter *)
 775                                   (poid_par_priv->adapter_context);
 776
 777        if (poid_par_priv->type_of_oid != QUERY_OID)
 778                return RNDIS_STATUS_NOT_ACCEPTED;
 779        if (poid_par_priv->information_buf_len < sizeof(int))
 780                return RNDIS_STATUS_INVALID_LENGTH;
 781        r8712_efuse_reg_init(Adapter);
 782        *(int *)poid_par_priv->information_buf =
 783                                 r8712_efuse_get_current_size(Adapter);
 784        r8712_efuse_reg_uninit(Adapter);
 785        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 786        return RNDIS_STATUS_SUCCESS;
 787}
 788
 789uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
 790{
 791        struct _adapter *Adapter = (struct _adapter *)
 792                                   (poid_par_priv->adapter_context);
 793
 794        if (poid_par_priv->type_of_oid != QUERY_OID)
 795                return RNDIS_STATUS_NOT_ACCEPTED;
 796        if (poid_par_priv->information_buf_len < sizeof(u32))
 797                return RNDIS_STATUS_INVALID_LENGTH;
 798        *(int *)poid_par_priv->information_buf =
 799                                         r8712_efuse_get_max_size(Adapter);
 800        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 801        return RNDIS_STATUS_SUCCESS;
 802}
 803
 804uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
 805{
 806        uint status = RNDIS_STATUS_SUCCESS;
 807
 808        if (poid_par_priv->type_of_oid == QUERY_OID)
 809                status = oid_rt_pro_read_efuse_hdl(poid_par_priv);
 810        else
 811                status = oid_rt_pro_write_efuse_hdl(poid_par_priv);
 812        return status;
 813}
 814
 815uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
 816{
 817        struct _adapter *Adapter = (struct _adapter *)
 818                                   (poid_par_priv->adapter_context);
 819        uint status = RNDIS_STATUS_SUCCESS;
 820        u8              *data;
 821
 822        *poid_par_priv->bytes_rw = 0;
 823        if (poid_par_priv->information_buf_len < EFUSE_MAP_MAX_SIZE)
 824                return RNDIS_STATUS_INVALID_LENGTH;
 825        data = (u8 *)poid_par_priv->information_buf;
 826        if (poid_par_priv->type_of_oid == QUERY_OID) {
 827                if (r8712_efuse_map_read(Adapter, 0, EFUSE_MAP_MAX_SIZE, data))
 828                        *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
 829                else
 830                        status = RNDIS_STATUS_FAILURE;
 831        } else {
 832                /* SET_OID */
 833                if (r8712_efuse_reg_init(Adapter)) {
 834                        if (r8712_efuse_map_write(Adapter, 0,
 835                            EFUSE_MAP_MAX_SIZE, data))
 836                                *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
 837                        else
 838                                status = RNDIS_STATUS_FAILURE;
 839                        r8712_efuse_reg_uninit(Adapter);
 840                } else {
 841                        status = RNDIS_STATUS_FAILURE;
 842                }
 843        }
 844        return status;
 845}
 846
 847uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
 848{
 849        struct _adapter *Adapter = (struct _adapter *)
 850                                   (poid_par_priv->adapter_context);
 851        u32             bandwidth;
 852
 853        if (poid_par_priv->type_of_oid != SET_OID)
 854                return RNDIS_STATUS_NOT_ACCEPTED;
 855        if (poid_par_priv->information_buf_len < sizeof(u32))
 856                return RNDIS_STATUS_INVALID_LENGTH;
 857        bandwidth = *((u32 *)poid_par_priv->information_buf);/*4*/
 858        if (bandwidth != HT_CHANNEL_WIDTH_20)
 859                bandwidth = HT_CHANNEL_WIDTH_40;
 860        Adapter->mppriv.curr_bandwidth = (u8)bandwidth;
 861        r8712_SwitchBandwidth(Adapter);
 862        return RNDIS_STATUS_SUCCESS;
 863}
 864
 865uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv
 866                                           *poid_par_priv)
 867{
 868        struct _adapter *Adapter = (struct _adapter *)
 869                                   (poid_par_priv->adapter_context);
 870        u8              rx_pkt_type;
 871        u32             rcr_val32;
 872
 873        if (poid_par_priv->type_of_oid != SET_OID)
 874                return RNDIS_STATUS_NOT_ACCEPTED;
 875        if (poid_par_priv->information_buf_len < sizeof(u8))
 876                return RNDIS_STATUS_INVALID_LENGTH;
 877        rx_pkt_type = *((u8 *)poid_par_priv->information_buf);/*4*/
 878        rcr_val32 = r8712_read32(Adapter, RCR);/*RCR = 0x10250048*/
 879        rcr_val32 &= ~(RCR_CBSSID | RCR_AB | RCR_AM | RCR_APM | RCR_AAP);
 880        switch (rx_pkt_type) {
 881        case RX_PKT_BROADCAST:
 882                rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
 883                break;
 884        case RX_PKT_DEST_ADDR:
 885                rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
 886                break;
 887        case RX_PKT_PHY_MATCH:
 888                rcr_val32 |= (RCR_APM | RCR_ACRC32);
 889                break;
 890        default:
 891                rcr_val32 &= ~(RCR_AAP |
 892                               RCR_APM |
 893                               RCR_AM |
 894                               RCR_AB |
 895                               RCR_ACRC32);
 896                break;
 897        }
 898        if (rx_pkt_type == RX_PKT_DEST_ADDR)
 899                Adapter->mppriv.check_mp_pkt = 1;
 900        else
 901                Adapter->mppriv.check_mp_pkt = 0;
 902        r8712_write32(Adapter, RCR, rcr_val32);
 903        return RNDIS_STATUS_SUCCESS;
 904}
 905
 906/*--------------------------------------------------------------------------*/
 907/*Linux*/
 908unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
 909{
 910        return _SUCCESS;
 911}
 912/*-------------------------------------------------------------------------*/
 913uint oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
 914{
 915        if (poid_par_priv->type_of_oid != SET_OID)
 916                return RNDIS_STATUS_NOT_ACCEPTED;
 917        /*CALL  the power_down function*/
 918        return RNDIS_STATUS_SUCCESS;
 919}
 920
 921/*-------------------------------------------------------------------------- */
 922uint oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv)
 923{
 924        struct _adapter *Adapter = (struct _adapter *)
 925                                   (poid_par_priv->adapter_context);
 926
 927        if (poid_par_priv->type_of_oid != QUERY_OID)
 928                return RNDIS_STATUS_NOT_ACCEPTED;
 929        if (poid_par_priv->information_buf_len < sizeof(u32))
 930                return RNDIS_STATUS_INVALID_LENGTH;
 931        *(int *)poid_par_priv->information_buf =
 932                 Adapter->registrypriv.low_power ? POWER_LOW : POWER_NORMAL;
 933        *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 934        return RNDIS_STATUS_SUCCESS;
 935}
 936