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 36 uint oid_null_function(struct oid_par_priv *poid_par_priv) 37 { 38 return RNDIS_STATUS_SUCCESS; 39 } 40 41 uint 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 68 uint 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 89 uint 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 111 uint 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 134 uint 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*/ 159 static 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 pseudo 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); 213 end_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 */ 219 static 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 pseudo 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)); 241 end_of_mp_stop_test: 242 spin_unlock_irqrestore(&pmlmepriv->lock, irqL); 243 return _SUCCESS; 244 } 245 246 int 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 262 uint 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 281 uint 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 310 uint 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 323 uint 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 342 uint 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 359 uint 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 378 uint 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 399 uint 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 420 uint 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 441 uint 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 453 uint 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 471 uint 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 483 uint 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 499 uint 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 515 uint 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 528 uint 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 542 uint 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 556 uint 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 570 uint 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 584 uint 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 625 uint 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 685 uint 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 713 uint 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 /*------------------------------------------------------------------------*/ 743 uint 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 771 uint 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 789 uint 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 804 uint 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 815 uint 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 847 uint 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 865 uint 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*/ 908 unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv) 909 { 910 return _SUCCESS; 911 } 912 /*-------------------------------------------------------------------------*/ 913 uint 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 /*-------------------------------------------------------------------------- */ 922 uint 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