Linux Audio

Check our new training course

Loading...
v3.1
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2010  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 * The full GNU General Public License is included in this distribution in the
  19 * file called LICENSE.
  20 *
  21 * Contact Information:
  22 * wlanfae <wlanfae@realtek.com>
  23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  24 * Hsinchu 300, Taiwan.
  25 *
  26 * Larry Finger <Larry.Finger@lwfinger.net>
  27 *
  28****************************************************************************/
  29
  30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  31
  32#include <linux/module.h>
  33
  34#include "../wifi.h"
  35#include "../pci.h"
  36#include "../usb.h"
  37#include "../ps.h"
  38#include "../cam.h"
 
  39#include "reg.h"
  40#include "def.h"
  41#include "phy.h"
  42#include "rf.h"
  43#include "dm.h"
  44#include "mac.h"
  45#include "trx.h"
  46
 
 
  47/* macro to shorten lines */
  48
  49#define LINK_Q	ui_link_quality
  50#define RX_EVM	rx_evm_percentage
  51#define RX_SIGQ	rx_mimo_signalquality
  52
  53
  54void rtl92c_read_chip_version(struct ieee80211_hw *hw)
  55{
  56	struct rtl_priv *rtlpriv = rtl_priv(hw);
  57	struct rtl_phy *rtlphy = &(rtlpriv->phy);
  58	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
  59	enum version_8192c chip_version = VERSION_UNKNOWN;
 
  60	u32 value32;
  61
  62	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
  63	if (value32 & TRP_VAUX_EN) {
  64		chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C :
  65			       VERSION_TEST_CHIP_88C;
  66	} else {
  67		/* Normal mass production chip. */
  68		chip_version = NORMAL_CHIP;
  69		chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0);
  70		chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0);
  71		/* RTL8723 with BT function. */
  72		chip_version |= ((value32 & BT_FUNC) ? CHIP_8723 : 0);
  73		if (IS_VENDOR_UMC(chip_version))
  74			chip_version |= ((value32 & CHIP_VER_RTL_MASK) ?
  75					 CHIP_VENDOR_UMC_B_CUT : 0);
  76		if (IS_92C_SERIAL(chip_version)) {
  77			value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
  78			chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) ==
  79				 CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0);
  80		} else if (IS_8723_SERIES(chip_version)) {
  81			value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
  82			chip_version |= ((value32 & RF_RL_ID) ?
  83					  CHIP_8723_DRV_REV : 0);
  84		}
  85	}
  86	rtlhal->version  = (enum version_8192c)chip_version;
 
  87	switch (rtlhal->version) {
  88	case VERSION_NORMAL_TSMC_CHIP_92C_1T2R:
  89		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  90		 ("Chip Version ID: VERSION_B_CHIP_92C.\n"));
  91		break;
  92	case VERSION_NORMAL_TSMC_CHIP_92C:
  93		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  94			("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_92C.\n"));
  95		break;
  96	case VERSION_NORMAL_TSMC_CHIP_88C:
  97		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  98			("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_88C.\n"));
  99		break;
 100	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
 101		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 102			("Chip Version ID: VERSION_NORMAL_UMC_CHIP_i"
 103			"92C_1T2R_A_CUT.\n"));
 104		break;
 105	case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
 106		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 107			("Chip Version ID: VERSION_NORMAL_UMC_CHIP_"
 108			"92C_A_CUT.\n"));
 109		break;
 110	case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
 111		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 112			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
 113			"_88C_A_CUT.\n"));
 114		break;
 115	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
 116		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 117			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
 118			"_92C_1T2R_B_CUT.\n"));
 119		break;
 120	case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
 121		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 122			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
 123			"_92C_B_CUT.\n"));
 124		break;
 125	case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
 126		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 127			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
 128			"_88C_B_CUT.\n"));
 129		break;
 130	case VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT:
 131		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 132			("Chip Version ID: VERSION_NORMA_UMC_CHIP"
 133			"_8723_1T1R_A_CUT.\n"));
 134		break;
 135	case VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT:
 136		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 137			("Chip Version ID: VERSION_NORMA_UMC_CHIP"
 138			"_8723_1T1R_B_CUT.\n"));
 139		break;
 140	case VERSION_TEST_CHIP_92C:
 141		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 142			("Chip Version ID: VERSION_TEST_CHIP_92C.\n"));
 143		break;
 144	case VERSION_TEST_CHIP_88C:
 145		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 146			("Chip Version ID: VERSION_TEST_CHIP_88C.\n"));
 147		break;
 148	default:
 149		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 150			("Chip Version ID: ???????????????.\n"));
 151		break;
 152	}
 
 
 
 153	if (IS_92C_SERIAL(rtlhal->version))
 154		rtlphy->rf_type =
 155			 (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R;
 156	else
 157		rtlphy->rf_type = RF_1T1R;
 158	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 159		 ("Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ?
 160		  "RF_2T2R" : "RF_1T1R"));
 161	if (get_rf_type(rtlphy) == RF_1T1R)
 162		rtlpriv->dm.rfpath_rxenable[0] = true;
 163	else
 164		rtlpriv->dm.rfpath_rxenable[0] =
 165		    rtlpriv->dm.rfpath_rxenable[1] = true;
 166	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("VersionID = 0x%4x\n",
 167						rtlhal->version));
 168}
 169
 170/**
 171 * writeLLT - LLT table write access
 172 * @io: io callback
 173 * @address: LLT logical address.
 174 * @data: LLT data content
 175 *
 176 * Realtek hardware access function.
 177 *
 178 */
 179bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
 180{
 181	struct rtl_priv *rtlpriv = rtl_priv(hw);
 182	bool status = true;
 183	long count = 0;
 184	u32 value = _LLT_INIT_ADDR(address) |
 185	    _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
 186
 187	rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
 188	do {
 189		value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
 190		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
 191			break;
 192		if (count > POLLING_LLT_THRESHOLD) {
 193			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 194				 ("Failed to polling write LLT done at"
 195				 " address %d! _LLT_OP_VALUE(%x)\n",
 196				 address, _LLT_OP_VALUE(value)));
 197			status = false;
 198			break;
 199		}
 200	} while (++count);
 201	return status;
 202}
 203/**
 204 * rtl92c_init_LLT_table - Init LLT table
 205 * @io: io callback
 206 * @boundary:
 207 *
 208 * Realtek hardware access function.
 209 *
 210 */
 211bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
 212{
 213	bool rst = true;
 214	u32	i;
 215
 216	for (i = 0; i < (boundary - 1); i++) {
 217		rst = rtl92c_llt_write(hw, i , i + 1);
 218		if (true != rst) {
 219			pr_err("===> %s #1 fail\n", __func__);
 220			return rst;
 221		}
 222	}
 223	/* end of list */
 224	rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
 225	if (true != rst) {
 226		pr_err("===> %s #2 fail\n", __func__);
 227		return rst;
 228	}
 229	/* Make the other pages as ring buffer
 230	 * This ring buffer is used as beacon buffer if we config this MAC
 231	 *  as two MAC transfer.
 232	 * Otherwise used as local loopback buffer.
 233	 */
 234	for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
 235		rst = rtl92c_llt_write(hw, i, (i + 1));
 236		if (true != rst) {
 237			pr_err("===> %s #3 fail\n", __func__);
 238			return rst;
 239		}
 240	}
 241	/* Let last entry point to the start entry of ring buffer */
 242	rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
 243	if (true != rst) {
 244		pr_err("===> %s #4 fail\n", __func__);
 245		return rst;
 246	}
 247	return rst;
 248}
 249void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
 250		     u8 *p_macaddr, bool is_group, u8 enc_algo,
 251		     bool is_wepkey, bool clear_all)
 252{
 253	struct rtl_priv *rtlpriv = rtl_priv(hw);
 254	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 255	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 256	u8 *macaddr = p_macaddr;
 257	u32 entry_id = 0;
 258	bool is_pairwise = false;
 259	static u8 cam_const_addr[4][6] = {
 260		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
 261		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
 262		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
 263		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
 264	};
 265	static u8 cam_const_broad[] = {
 266		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 267	};
 268
 269	if (clear_all) {
 270		u8 idx = 0;
 271		u8 cam_offset = 0;
 272		u8 clear_number = 5;
 273
 274		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n"));
 275		for (idx = 0; idx < clear_number; idx++) {
 276			rtl_cam_mark_invalid(hw, cam_offset + idx);
 277			rtl_cam_empty_entry(hw, cam_offset + idx);
 278			if (idx < 5) {
 279				memset(rtlpriv->sec.key_buf[idx], 0,
 280				       MAX_KEY_LEN);
 281				rtlpriv->sec.key_len[idx] = 0;
 282			}
 283		}
 284	} else {
 285		switch (enc_algo) {
 286		case WEP40_ENCRYPTION:
 287			enc_algo = CAM_WEP40;
 288			break;
 289		case WEP104_ENCRYPTION:
 290			enc_algo = CAM_WEP104;
 291			break;
 292		case TKIP_ENCRYPTION:
 293			enc_algo = CAM_TKIP;
 294			break;
 295		case AESCCMP_ENCRYPTION:
 296			enc_algo = CAM_AES;
 297			break;
 298		default:
 299			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 300				("iillegal switch case\n"));
 301			enc_algo = CAM_TKIP;
 302			break;
 303		}
 304		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
 305			macaddr = cam_const_addr[key_index];
 306			entry_id = key_index;
 307		} else {
 308			if (is_group) {
 309				macaddr = cam_const_broad;
 310				entry_id = key_index;
 311			} else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 312				key_index = PAIRWISE_KEYIDX;
 313				entry_id = CAM_PAIRWISE_KEY_POSITION;
 314				is_pairwise = true;
 315			}
 316		}
 317		if (rtlpriv->sec.key_len[key_index] == 0) {
 318			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 319				 ("delete one entry\n"));
 
 
 
 320			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
 321		} else {
 322			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
 323				 ("The insert KEY length is %d\n",
 324				  rtlpriv->sec.key_len[PAIRWISE_KEYIDX]));
 325			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
 326				 ("The insert KEY  is %x %x\n",
 327				  rtlpriv->sec.key_buf[0][0],
 328				  rtlpriv->sec.key_buf[0][1]));
 329			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 330				 ("add one entry\n"));
 331			if (is_pairwise) {
 332				RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
 333					      "Pairwiase Key content :",
 334					      rtlpriv->sec.pairwise_key,
 335					      rtlpriv->sec.
 336					      key_len[PAIRWISE_KEYIDX]);
 337				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 338					 ("set Pairwiase key\n"));
 339
 340				rtl_cam_add_one_entry(hw, macaddr, key_index,
 341						entry_id, enc_algo,
 342						CAM_CONFIG_NO_USEDK,
 343						rtlpriv->sec.
 344						key_buf[key_index]);
 345			} else {
 346				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 347					 ("set group key\n"));
 348				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 349					rtl_cam_add_one_entry(hw,
 350						rtlefuse->dev_addr,
 351						PAIRWISE_KEYIDX,
 352						CAM_PAIRWISE_KEY_POSITION,
 353						enc_algo,
 354						CAM_CONFIG_NO_USEDK,
 355						rtlpriv->sec.key_buf
 356						[entry_id]);
 357				}
 358				rtl_cam_add_one_entry(hw, macaddr, key_index,
 359						entry_id, enc_algo,
 360						CAM_CONFIG_NO_USEDK,
 361						rtlpriv->sec.key_buf[entry_id]);
 362			}
 363		}
 364	}
 365}
 366
 367u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw)
 368{
 369	struct rtl_priv *rtlpriv = rtl_priv(hw);
 370
 371	return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS);
 372}
 373
 374void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
 375{
 376	struct rtl_priv *rtlpriv = rtl_priv(hw);
 377	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 378	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 379	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 380
 381	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
 382		rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] &
 383				0xFFFFFFFF);
 384		rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
 385				0xFFFFFFFF);
 386	} else {
 387		rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
 388				0xFFFFFFFF);
 389		rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
 390				0xFFFFFFFF);
 391	}
 392}
 393
 394void rtl92c_init_interrupt(struct ieee80211_hw *hw)
 395{
 396	 rtl92c_enable_interrupt(hw);
 397}
 398
 399void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
 400{
 401	struct rtl_priv *rtlpriv = rtl_priv(hw);
 402
 403	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
 404	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
 405}
 406
 407void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
 408{
 409	struct rtl_priv *rtlpriv = rtl_priv(hw);
 410	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 411	u32 u4b_ac_param;
 412
 413	rtl92c_dm_init_edca_turbo(hw);
 414	u4b_ac_param = (u32) mac->ac[aci].aifs;
 415	u4b_ac_param |=
 416	    ((u32) le16_to_cpu(mac->ac[aci].cw_min) & 0xF) <<
 417	    AC_PARAM_ECW_MIN_OFFSET;
 418	u4b_ac_param |=
 419	    ((u32) le16_to_cpu(mac->ac[aci].cw_max) & 0xF) <<
 420	    AC_PARAM_ECW_MAX_OFFSET;
 421	u4b_ac_param |= (u32) le16_to_cpu(mac->ac[aci].tx_op) <<
 422			 AC_PARAM_TXOP_OFFSET;
 423	RT_TRACE(rtlpriv, COMP_QOS, DBG_LOUD,
 424		 ("queue:%x, ac_param:%x\n", aci, u4b_ac_param));
 425	switch (aci) {
 426	case AC1_BK:
 427		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
 428		break;
 429	case AC0_BE:
 430		rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param);
 431		break;
 432	case AC2_VI:
 433		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param);
 434		break;
 435	case AC3_VO:
 436		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param);
 437		break;
 438	default:
 439		RT_ASSERT(false, ("invalid aci: %d !\n", aci));
 440		break;
 441	}
 442}
 443
 444/*-------------------------------------------------------------------------
 445 * HW MAC Address
 446 *-------------------------------------------------------------------------*/
 447void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr)
 448{
 449	u32 i;
 450	struct rtl_priv *rtlpriv = rtl_priv(hw);
 451
 452	for (i = 0 ; i < ETH_ALEN ; i++)
 453		rtl_write_byte(rtlpriv, (REG_MACID + i), *(addr+i));
 454
 455	RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("MAC Address: %02X-%02X-%02X-"
 456		"%02X-%02X-%02X\n",
 457		rtl_read_byte(rtlpriv, REG_MACID),
 458		rtl_read_byte(rtlpriv, REG_MACID+1),
 459		rtl_read_byte(rtlpriv, REG_MACID+2),
 460		rtl_read_byte(rtlpriv, REG_MACID+3),
 461		rtl_read_byte(rtlpriv, REG_MACID+4),
 462		rtl_read_byte(rtlpriv, REG_MACID+5)));
 463}
 464
 465void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
 466{
 467	struct rtl_priv *rtlpriv = rtl_priv(hw);
 468	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
 469}
 470
 471int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
 472{
 473	u8 value;
 474	struct rtl_priv *rtlpriv = rtl_priv(hw);
 475
 476	switch (type) {
 477	case NL80211_IFTYPE_UNSPECIFIED:
 478		value = NT_NO_LINK;
 479		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 480			("Set Network type to NO LINK!\n"));
 481		break;
 482	case NL80211_IFTYPE_ADHOC:
 483		value = NT_LINK_AD_HOC;
 484		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 485			("Set Network type to Ad Hoc!\n"));
 486		break;
 487	case NL80211_IFTYPE_STATION:
 488		value = NT_LINK_AP;
 489		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 490			("Set Network type to STA!\n"));
 491		break;
 492	case NL80211_IFTYPE_AP:
 493		value = NT_AS_AP;
 494		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 495			("Set Network type to AP!\n"));
 496		break;
 497	default:
 498		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 499			("Network type %d not support!\n", type));
 500		return -EOPNOTSUPP;
 501	}
 502	rtl_write_byte(rtlpriv, (REG_CR + 2), value);
 503	return 0;
 504}
 505
 506void rtl92c_init_network_type(struct ieee80211_hw *hw)
 507{
 508	rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED);
 509}
 510
 511void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw)
 512{
 513	u16	value16;
 514	u32	value32;
 515	struct rtl_priv *rtlpriv = rtl_priv(hw);
 516
 517	/* Response Rate Set */
 518	value32 = rtl_read_dword(rtlpriv, REG_RRSR);
 519	value32 &= ~RATE_BITMAP_ALL;
 520	value32 |= RATE_RRSR_CCK_ONLY_1M;
 521	rtl_write_dword(rtlpriv, REG_RRSR, value32);
 522	/* SIFS (used in NAV) */
 523	value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
 524	rtl_write_word(rtlpriv,  REG_SPEC_SIFS, value16);
 525	/* Retry Limit */
 526	value16 = _LRL(0x30) | _SRL(0x30);
 527	rtl_write_dword(rtlpriv,  REG_RL, value16);
 528}
 529
 530void rtl92c_init_rate_fallback(struct ieee80211_hw *hw)
 531{
 532	struct rtl_priv *rtlpriv = rtl_priv(hw);
 533
 534	/* Set Data Auto Rate Fallback Retry Count register. */
 535	rtl_write_dword(rtlpriv,  REG_DARFRC, 0x00000000);
 536	rtl_write_dword(rtlpriv,  REG_DARFRC+4, 0x10080404);
 537	rtl_write_dword(rtlpriv,  REG_RARFRC, 0x04030201);
 538	rtl_write_dword(rtlpriv,  REG_RARFRC+4, 0x08070605);
 539}
 540
 541static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
 542				u8 ctx_sifs)
 543{
 544	struct rtl_priv *rtlpriv = rtl_priv(hw);
 545
 546	rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs);
 547	rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs);
 548}
 549
 550static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
 551				 u8 ctx_sifs)
 552{
 553	struct rtl_priv *rtlpriv = rtl_priv(hw);
 554
 555	rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs);
 556	rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs);
 557}
 558
 559void rtl92c_init_edca_param(struct ieee80211_hw *hw,
 560			    u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs)
 561{
 562	/* sequence: VO, VI, BE, BK ==> the same as 92C hardware design.
 563	 * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function.
 564	 */
 565	u32 value;
 566	struct rtl_priv *rtlpriv = rtl_priv(hw);
 567
 568	value = (u32)aifs;
 569	value |= ((u32)cw_min & 0xF) << 8;
 570	value |= ((u32)cw_max & 0xF) << 12;
 571	value |= (u32)txop << 16;
 572	/* 92C hardware register sequence is the same as queue number. */
 573	rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value);
 574}
 575
 576void rtl92c_init_edca(struct ieee80211_hw *hw)
 577{
 578	u16 value16;
 579	struct rtl_priv *rtlpriv = rtl_priv(hw);
 580
 581	/* disable EDCCA count down, to reduce collison and retry */
 582	value16 = rtl_read_word(rtlpriv, REG_RD_CTRL);
 583	value16 |= DIS_EDCA_CNT_DWN;
 584	rtl_write_word(rtlpriv, REG_RD_CTRL, value16);
 585	/* Update SIFS timing.  ??????????
 586	 * pHalData->SifsTime = 0x0e0e0a0a; */
 587	rtl92c_set_cck_sifs(hw, 0xa, 0xa);
 588	rtl92c_set_ofdm_sifs(hw, 0xe, 0xe);
 589	/* Set CCK/OFDM SIFS to be 10us. */
 590	rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a);
 591	rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010);
 592	rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204);
 593	rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004);
 594	/* TXOP */
 595	rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B);
 596	rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F);
 597	rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324);
 598	rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226);
 599	/* PIFS */
 600	rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
 601	/* AGGR BREAK TIME Register */
 602	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
 603	rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040);
 604	rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02);
 605	rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02);
 606}
 607
 608void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw)
 609{
 610	struct rtl_priv *rtlpriv = rtl_priv(hw);
 611
 612	rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631);
 613	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
 614	/* init AMPDU aggregation number, tuning for Tx's TP, */
 615	rtl_write_word(rtlpriv, 0x4CA, 0x0708);
 616}
 617
 618void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode)
 619{
 620	struct rtl_priv *rtlpriv = rtl_priv(hw);
 621
 622	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
 623}
 624
 625void rtl92c_init_rdg_setting(struct ieee80211_hw *hw)
 626{
 627	struct rtl_priv *rtlpriv = rtl_priv(hw);
 628
 629	rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF);
 630	rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
 631	rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
 632}
 633
 634void rtl92c_init_retry_function(struct ieee80211_hw *hw)
 635{
 636	u8	value8;
 637	struct rtl_priv *rtlpriv = rtl_priv(hw);
 638
 639	value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL);
 640	value8 |= EN_AMPDU_RTY_NEW;
 641	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8);
 642	/* Set ACK timeout */
 643	rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
 644}
 645
 646void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
 647				   enum version_8192c version)
 648{
 649	struct rtl_priv *rtlpriv = rtl_priv(hw);
 650	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 651
 652	rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
 653	rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
 654	rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
 655	if (IS_NORMAL_CHIP(rtlhal->version))
 656		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
 657	else
 658		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
 659}
 660
 661void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
 662{
 663	struct rtl_priv *rtlpriv = rtl_priv(hw);
 664
 665	rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0);
 666}
 667
 668void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T)
 669{
 670	struct rtl_priv *rtlpriv = rtl_priv(hw);
 671	u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T;
 672
 673	rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value);
 674}
 675
 676u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw)
 677{
 678	struct rtl_priv *rtlpriv = rtl_priv(hw);
 679
 680	return rtl_read_word(rtlpriv, REG_RXFLTMAP0);
 681}
 682
 683void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter)
 684{
 685	struct rtl_priv *rtlpriv = rtl_priv(hw);
 686
 687	rtl_write_word(rtlpriv, REG_RXFLTMAP0, filter);
 688}
 689
 690u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw)
 691{
 692	struct rtl_priv *rtlpriv = rtl_priv(hw);
 693
 694	return rtl_read_word(rtlpriv, REG_RXFLTMAP1);
 695}
 696
 697void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter)
 698{
 699	struct rtl_priv *rtlpriv = rtl_priv(hw);
 700
 701	rtl_write_word(rtlpriv, REG_RXFLTMAP1, filter);
 702}
 703
 704u16 rtl92c_get_data_filter(struct ieee80211_hw *hw)
 705{
 706	struct rtl_priv *rtlpriv = rtl_priv(hw);
 707
 708	return rtl_read_word(rtlpriv,  REG_RXFLTMAP2);
 709}
 710
 711void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter)
 712{
 713	struct rtl_priv *rtlpriv = rtl_priv(hw);
 714
 715	rtl_write_word(rtlpriv, REG_RXFLTMAP2, filter);
 716}
 717/*==============================================================*/
 718
 719static u8 _rtl92c_query_rxpwrpercentage(char antpower)
 720{
 721	if ((antpower <= -100) || (antpower >= 20))
 722		return 0;
 723	else if (antpower >= 0)
 724		return 100;
 725	else
 726		return 100 + antpower;
 727}
 728
 729static u8 _rtl92c_evm_db_to_percentage(char value)
 730{
 731	char ret_val;
 732
 733	ret_val = value;
 734	if (ret_val >= 0)
 735		ret_val = 0;
 736	if (ret_val <= -33)
 737		ret_val = -33;
 738	ret_val = 0 - ret_val;
 739	ret_val *= 3;
 740	if (ret_val == 99)
 741		ret_val = 100;
 742	return ret_val;
 743}
 744
 745static long _rtl92c_translate_todbm(struct ieee80211_hw *hw,
 746				     u8 signal_strength_index)
 747{
 748	long signal_power;
 749
 750	signal_power = (long)((signal_strength_index + 1) >> 1);
 751	signal_power -= 95;
 752	return signal_power;
 753}
 754
 755static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
 756		long currsig)
 757{
 758	long retsig;
 759
 760	if (currsig >= 61 && currsig <= 100)
 761		retsig = 90 + ((currsig - 60) / 4);
 762	else if (currsig >= 41 && currsig <= 60)
 763		retsig = 78 + ((currsig - 40) / 2);
 764	else if (currsig >= 31 && currsig <= 40)
 765		retsig = 66 + (currsig - 30);
 766	else if (currsig >= 21 && currsig <= 30)
 767		retsig = 54 + (currsig - 20);
 768	else if (currsig >= 5 && currsig <= 20)
 769		retsig = 42 + (((currsig - 5) * 2) / 3);
 770	else if (currsig == 4)
 771		retsig = 36;
 772	else if (currsig == 3)
 773		retsig = 27;
 774	else if (currsig == 2)
 775		retsig = 18;
 776	else if (currsig == 1)
 777		retsig = 9;
 778	else
 779		retsig = currsig;
 780	return retsig;
 781}
 782
 783static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
 784				      struct rtl_stats *pstats,
 785				      struct rx_desc_92c *pdesc,
 786				      struct rx_fwinfo_92c *p_drvinfo,
 787				      bool packet_match_bssid,
 788				      bool packet_toself,
 789				      bool packet_beacon)
 790{
 791	struct rtl_priv *rtlpriv = rtl_priv(hw);
 792	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 793	struct phy_sts_cck_8192s_t *cck_buf;
 794	s8 rx_pwr_all = 0, rx_pwr[4];
 795	u8 rf_rx_num = 0, evm, pwdb_all;
 796	u8 i, max_spatial_stream;
 797	u32 rssi, total_rssi = 0;
 798	bool in_powersavemode = false;
 799	bool is_cck_rate;
 
 800
 801	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
 802	pstats->packet_matchbssid = packet_match_bssid;
 803	pstats->packet_toself = packet_toself;
 804	pstats->is_cck = is_cck_rate;
 805	pstats->packet_beacon = packet_beacon;
 806	pstats->is_cck = is_cck_rate;
 807	pstats->RX_SIGQ[0] = -1;
 808	pstats->RX_SIGQ[1] = -1;
 809	if (is_cck_rate) {
 810		u8 report, cck_highpwr;
 811		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 812		if (!in_powersavemode)
 813			cck_highpwr = rtlphy->cck_high_power;
 814		else
 815			cck_highpwr = false;
 816		if (!cck_highpwr) {
 817			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 818			report = cck_buf->cck_agc_rpt & 0xc0;
 819			report = report >> 6;
 820			switch (report) {
 821			case 0x3:
 822				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
 823				break;
 824			case 0x2:
 825				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
 826				break;
 827			case 0x1:
 828				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
 829				break;
 830			case 0x0:
 831				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
 832				break;
 833			}
 834		} else {
 835			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 836			report = p_drvinfo->cfosho[0] & 0x60;
 837			report = report >> 5;
 838			switch (report) {
 839			case 0x3:
 840				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
 841				break;
 842			case 0x2:
 843				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
 844				break;
 845			case 0x1:
 846				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
 847				break;
 848			case 0x0:
 849				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
 850				break;
 851			}
 852		}
 853		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 854		pstats->rx_pwdb_all = pwdb_all;
 855		pstats->recvsignalpower = rx_pwr_all;
 856		if (packet_match_bssid) {
 857			u8 sq;
 858			if (pstats->rx_pwdb_all > 40)
 859				sq = 100;
 860			else {
 861				sq = cck_buf->sq_rpt;
 862				if (sq > 64)
 863					sq = 0;
 864				else if (sq < 20)
 865					sq = 100;
 866				else
 867					sq = ((64 - sq) * 100) / 44;
 868			}
 869			pstats->signalquality = sq;
 870			pstats->RX_SIGQ[0] = sq;
 871			pstats->RX_SIGQ[1] = -1;
 872		}
 873	} else {
 874		rtlpriv->dm.rfpath_rxenable[0] =
 875		    rtlpriv->dm.rfpath_rxenable[1] = true;
 876		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
 877			if (rtlpriv->dm.rfpath_rxenable[i])
 878				rf_rx_num++;
 879			rx_pwr[i] =
 880			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
 881			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
 882			total_rssi += rssi;
 883			rtlpriv->stats.rx_snr_db[i] =
 884			    (long)(p_drvinfo->rxsnr[i] / 2);
 885
 886			if (packet_match_bssid)
 887				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 888		}
 889		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 890		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 891		pstats->rx_pwdb_all = pwdb_all;
 892		pstats->rxpower = rx_pwr_all;
 893		pstats->recvsignalpower = rx_pwr_all;
 894		if (GET_RX_DESC_RX_MCS(pdesc) &&
 895		    GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 &&
 896		    GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15)
 897			max_spatial_stream = 2;
 898		else
 899			max_spatial_stream = 1;
 900		for (i = 0; i < max_spatial_stream; i++) {
 901			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 902			if (packet_match_bssid) {
 903				if (i == 0)
 904					pstats->signalquality =
 905					    (u8) (evm & 0xff);
 906				pstats->RX_SIGQ[i] =
 907				    (u8) (evm & 0xff);
 908			}
 909		}
 910	}
 911	if (is_cck_rate)
 912		pstats->signalstrength =
 913		    (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all));
 914	else if (rf_rx_num != 0)
 915		pstats->signalstrength =
 916		    (u8) (_rtl92c_signal_scale_mapping
 917			  (hw, total_rssi /= rf_rx_num));
 918}
 919
 920static void _rtl92c_process_ui_rssi(struct ieee80211_hw *hw,
 921		struct rtl_stats *pstats)
 922{
 923	struct rtl_priv *rtlpriv = rtl_priv(hw);
 924	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 925	u8 rfpath;
 926	u32 last_rssi, tmpval;
 927
 928	if (pstats->packet_toself || pstats->packet_beacon) {
 929		rtlpriv->stats.rssi_calculate_cnt++;
 930		if (rtlpriv->stats.ui_rssi.total_num++ >=
 931		    PHY_RSSI_SLID_WIN_MAX) {
 932			rtlpriv->stats.ui_rssi.total_num =
 933			    PHY_RSSI_SLID_WIN_MAX;
 934			last_rssi =
 935			    rtlpriv->stats.ui_rssi.elements[rtlpriv->
 936							   stats.ui_rssi.index];
 937			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
 938		}
 939		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
 940		rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
 941					index++] = pstats->signalstrength;
 942		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
 943			rtlpriv->stats.ui_rssi.index = 0;
 944		tmpval = rtlpriv->stats.ui_rssi.total_val /
 945		    rtlpriv->stats.ui_rssi.total_num;
 946		rtlpriv->stats.signal_strength =
 947		    _rtl92c_translate_todbm(hw, (u8) tmpval);
 948		pstats->rssi = rtlpriv->stats.signal_strength;
 949	}
 950	if (!pstats->is_cck && pstats->packet_toself) {
 951		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
 952		     rfpath++) {
 953			if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
 954				continue;
 955			if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
 956				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 957				    pstats->rx_mimo_signalstrength[rfpath];
 958			}
 959			if (pstats->rx_mimo_signalstrength[rfpath] >
 960			    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
 961				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 962				    ((rtlpriv->stats.
 963				      rx_rssi_percentage[rfpath] *
 964				      (RX_SMOOTH_FACTOR - 1)) +
 965				     (pstats->rx_mimo_signalstrength[rfpath])) /
 966				    (RX_SMOOTH_FACTOR);
 967
 968				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 969				    rtlpriv->stats.rx_rssi_percentage[rfpath] +
 970				    1;
 971			} else {
 972				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 973				    ((rtlpriv->stats.
 974				      rx_rssi_percentage[rfpath] *
 975				      (RX_SMOOTH_FACTOR - 1)) +
 976				     (pstats->rx_mimo_signalstrength[rfpath])) /
 977				    (RX_SMOOTH_FACTOR);
 978			}
 979		}
 980	}
 981}
 982
 983static void _rtl92c_update_rxsignalstatistics(struct ieee80211_hw *hw,
 984					       struct rtl_stats *pstats)
 985{
 986	struct rtl_priv *rtlpriv = rtl_priv(hw);
 987	int weighting = 0;
 988
 989	if (rtlpriv->stats.recv_signal_power == 0)
 990		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
 991	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
 992		weighting = 5;
 993	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
 994		weighting = (-5);
 995	rtlpriv->stats.recv_signal_power =
 996	    (rtlpriv->stats.recv_signal_power * 5 +
 997	     pstats->recvsignalpower + weighting) / 6;
 998}
 999
1000static void _rtl92c_process_pwdb(struct ieee80211_hw *hw,
1001		struct rtl_stats *pstats)
1002{
1003	struct rtl_priv *rtlpriv = rtl_priv(hw);
1004	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1005	long undecorated_smoothed_pwdb = 0;
1006
1007	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1008		return;
1009	} else {
1010		undecorated_smoothed_pwdb =
1011		    rtlpriv->dm.undecorated_smoothed_pwdb;
1012	}
1013	if (pstats->packet_toself || pstats->packet_beacon) {
1014		if (undecorated_smoothed_pwdb < 0)
1015			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
1016		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
1017			undecorated_smoothed_pwdb =
1018			    (((undecorated_smoothed_pwdb) *
1019			      (RX_SMOOTH_FACTOR - 1)) +
1020			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
1021			undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
1022			    + 1;
1023		} else {
1024			undecorated_smoothed_pwdb =
1025			    (((undecorated_smoothed_pwdb) *
1026			      (RX_SMOOTH_FACTOR - 1)) +
1027			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
1028		}
1029		rtlpriv->dm.undecorated_smoothed_pwdb =
1030		    undecorated_smoothed_pwdb;
1031		_rtl92c_update_rxsignalstatistics(hw, pstats);
1032	}
1033}
1034
1035static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw,
1036					     struct rtl_stats *pstats)
1037{
1038	struct rtl_priv *rtlpriv = rtl_priv(hw);
1039	u32 last_evm = 0, n_stream, tmpval;
1040
1041	if (pstats->signalquality != 0) {
1042		if (pstats->packet_toself || pstats->packet_beacon) {
1043			if (rtlpriv->stats.LINK_Q.total_num++ >=
1044			    PHY_LINKQUALITY_SLID_WIN_MAX) {
1045				rtlpriv->stats.LINK_Q.total_num =
1046				    PHY_LINKQUALITY_SLID_WIN_MAX;
1047				last_evm =
1048				    rtlpriv->stats.LINK_Q.elements
1049				    [rtlpriv->stats.LINK_Q.index];
1050				rtlpriv->stats.LINK_Q.total_val -=
1051				    last_evm;
1052			}
1053			rtlpriv->stats.LINK_Q.total_val +=
1054			    pstats->signalquality;
1055			rtlpriv->stats.LINK_Q.elements
1056			   [rtlpriv->stats.LINK_Q.index++] =
1057			    pstats->signalquality;
1058			if (rtlpriv->stats.LINK_Q.index >=
1059			    PHY_LINKQUALITY_SLID_WIN_MAX)
1060				rtlpriv->stats.LINK_Q.index = 0;
1061			tmpval = rtlpriv->stats.LINK_Q.total_val /
1062			    rtlpriv->stats.LINK_Q.total_num;
1063			rtlpriv->stats.signal_quality = tmpval;
1064			rtlpriv->stats.last_sigstrength_inpercent = tmpval;
1065			for (n_stream = 0; n_stream < 2;
1066			     n_stream++) {
1067				if (pstats->RX_SIGQ[n_stream] != -1) {
1068					if (!rtlpriv->stats.RX_EVM[n_stream]) {
1069						rtlpriv->stats.RX_EVM[n_stream]
1070						 = pstats->RX_SIGQ[n_stream];
1071					}
1072					rtlpriv->stats.RX_EVM[n_stream] =
1073					    ((rtlpriv->stats.RX_EVM
1074					    [n_stream] *
1075					    (RX_SMOOTH_FACTOR - 1)) +
1076					    (pstats->RX_SIGQ
1077					    [n_stream] * 1)) /
1078					    (RX_SMOOTH_FACTOR);
1079				}
1080			}
1081		}
1082	} else {
1083		;
1084	}
1085}
1086
1087static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw,
1088				     u8 *buffer,
1089				     struct rtl_stats *pcurrent_stats)
1090{
1091	if (!pcurrent_stats->packet_matchbssid &&
1092	    !pcurrent_stats->packet_beacon)
1093		return;
1094	_rtl92c_process_ui_rssi(hw, pcurrent_stats);
1095	_rtl92c_process_pwdb(hw, pcurrent_stats);
1096	_rtl92c_process_LINK_Q(hw, pcurrent_stats);
1097}
1098
1099void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
1100					       struct sk_buff *skb,
1101					       struct rtl_stats *pstats,
1102					       struct rx_desc_92c *pdesc,
1103					       struct rx_fwinfo_92c *p_drvinfo)
1104{
1105	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1106	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1107	struct ieee80211_hdr *hdr;
1108	u8 *tmp_buf;
1109	u8 *praddr;
1110	__le16 fc;
1111	u16 type, cpu_fc;
1112	bool packet_matchbssid, packet_toself, packet_beacon;
1113
1114	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
1115	hdr = (struct ieee80211_hdr *)tmp_buf;
1116	fc = hdr->frame_control;
1117	cpu_fc = le16_to_cpu(fc);
1118	type = WLAN_FC_GET_TYPE(fc);
1119	praddr = hdr->addr1;
1120	packet_matchbssid =
1121	    ((IEEE80211_FTYPE_CTL != type) &&
1122	     (!compare_ether_addr(mac->bssid,
1123			  (cpu_fc & IEEE80211_FCTL_TODS) ?
1124			  hdr->addr1 : (cpu_fc & IEEE80211_FCTL_FROMDS) ?
1125			  hdr->addr2 : hdr->addr3)) &&
1126	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
1127
1128	packet_toself = packet_matchbssid &&
1129	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
1130	if (ieee80211_is_beacon(fc))
1131		packet_beacon = true;
1132	_rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
1133				   packet_matchbssid, packet_toself,
1134				   packet_beacon);
1135	_rtl92c_process_phyinfo(hw, tmp_buf, pstats);
1136}
v3.15
  1/******************************************************************************
  2 *
  3 * Copyright(c) 2009-2012  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 * The full GNU General Public License is included in this distribution in the
 19 * file called LICENSE.
 20 *
 21 * Contact Information:
 22 * wlanfae <wlanfae@realtek.com>
 23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
 24 * Hsinchu 300, Taiwan.
 25 *
 26 * Larry Finger <Larry.Finger@lwfinger.net>
 27 *
 28****************************************************************************/
 29
 
 
 
 
 30#include "../wifi.h"
 31#include "../pci.h"
 32#include "../usb.h"
 33#include "../ps.h"
 34#include "../cam.h"
 35#include "../stats.h"
 36#include "reg.h"
 37#include "def.h"
 38#include "phy.h"
 39#include "rf.h"
 40#include "dm.h"
 41#include "mac.h"
 42#include "trx.h"
 43
 44#include <linux/module.h>
 45
 46/* macro to shorten lines */
 47
 48#define LINK_Q	ui_link_quality
 49#define RX_EVM	rx_evm_percentage
 50#define RX_SIGQ	rx_mimo_sig_qual
 51
 52
 53void rtl92c_read_chip_version(struct ieee80211_hw *hw)
 54{
 55	struct rtl_priv *rtlpriv = rtl_priv(hw);
 56	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 57	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 58	enum version_8192c chip_version = VERSION_UNKNOWN;
 59	const char *versionid;
 60	u32 value32;
 61
 62	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
 63	if (value32 & TRP_VAUX_EN) {
 64		chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C :
 65			       VERSION_TEST_CHIP_88C;
 66	} else {
 67		/* Normal mass production chip. */
 68		chip_version = NORMAL_CHIP;
 69		chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0);
 70		chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0);
 71		/* RTL8723 with BT function. */
 72		chip_version |= ((value32 & BT_FUNC) ? CHIP_8723 : 0);
 73		if (IS_VENDOR_UMC(chip_version))
 74			chip_version |= ((value32 & CHIP_VER_RTL_MASK) ?
 75					 CHIP_VENDOR_UMC_B_CUT : 0);
 76		if (IS_92C_SERIAL(chip_version)) {
 77			value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
 78			chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) ==
 79				 CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0);
 80		} else if (IS_8723_SERIES(chip_version)) {
 81			value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
 82			chip_version |= ((value32 & RF_RL_ID) ?
 83					  CHIP_8723_DRV_REV : 0);
 84		}
 85	}
 86	rtlhal->version  = (enum version_8192c)chip_version;
 87	pr_info("Chip version 0x%x\n", chip_version);
 88	switch (rtlhal->version) {
 89	case VERSION_NORMAL_TSMC_CHIP_92C_1T2R:
 90		versionid = "NORMAL_B_CHIP_92C";
 
 91		break;
 92	case VERSION_NORMAL_TSMC_CHIP_92C:
 93		versionid = "NORMAL_TSMC_CHIP_92C";
 
 94		break;
 95	case VERSION_NORMAL_TSMC_CHIP_88C:
 96		versionid = "NORMAL_TSMC_CHIP_88C";
 
 97		break;
 98	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
 99		versionid = "NORMAL_UMC_CHIP_i92C_1T2R_A_CUT";
 
 
100		break;
101	case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
102		versionid = "NORMAL_UMC_CHIP_92C_A_CUT";
 
 
103		break;
104	case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
105		versionid = "NORMAL_UMC_CHIP_88C_A_CUT";
 
 
106		break;
107	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
108		versionid = "NORMAL_UMC_CHIP_92C_1T2R_B_CUT";
 
 
109		break;
110	case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
111		versionid = "NORMAL_UMC_CHIP_92C_B_CUT";
 
 
112		break;
113	case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
114		versionid = "NORMAL_UMC_CHIP_88C_B_CUT";
 
 
115		break;
116	case VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT:
117		versionid = "NORMAL_UMC_CHIP_8723_1T1R_A_CUT";
 
 
118		break;
119	case VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT:
120		versionid = "NORMAL_UMC_CHIP_8723_1T1R_B_CUT";
 
 
121		break;
122	case VERSION_TEST_CHIP_92C:
123		versionid = "TEST_CHIP_92C";
 
124		break;
125	case VERSION_TEST_CHIP_88C:
126		versionid = "TEST_CHIP_88C";
 
127		break;
128	default:
129		versionid = "UNKNOWN";
 
130		break;
131	}
132	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
133		 "Chip Version ID: %s\n", versionid);
134
135	if (IS_92C_SERIAL(rtlhal->version))
136		rtlphy->rf_type =
137			 (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R;
138	else
139		rtlphy->rf_type = RF_1T1R;
140	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
141		 "Chip RF Type: %s\n",
142		 rtlphy->rf_type == RF_2T2R ? "RF_2T2R" : "RF_1T1R");
143	if (get_rf_type(rtlphy) == RF_1T1R)
144		rtlpriv->dm.rfpath_rxenable[0] = true;
145	else
146		rtlpriv->dm.rfpath_rxenable[0] =
147		    rtlpriv->dm.rfpath_rxenable[1] = true;
148	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
149		 rtlhal->version);
150}
151
152/**
153 * writeLLT - LLT table write access
154 * @io: io callback
155 * @address: LLT logical address.
156 * @data: LLT data content
157 *
158 * Realtek hardware access function.
159 *
160 */
161bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
162{
163	struct rtl_priv *rtlpriv = rtl_priv(hw);
164	bool status = true;
165	long count = 0;
166	u32 value = _LLT_INIT_ADDR(address) |
167	    _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
168
169	rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
170	do {
171		value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
172		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
173			break;
174		if (count > POLLING_LLT_THRESHOLD) {
175			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
176				 "Failed to polling write LLT done at address %d! _LLT_OP_VALUE(%x)\n",
177				 address, _LLT_OP_VALUE(value));
 
178			status = false;
179			break;
180		}
181	} while (++count);
182	return status;
183}
184/**
185 * rtl92c_init_LLT_table - Init LLT table
186 * @io: io callback
187 * @boundary:
188 *
189 * Realtek hardware access function.
190 *
191 */
192bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
193{
194	bool rst = true;
195	u32	i;
196
197	for (i = 0; i < (boundary - 1); i++) {
198		rst = rtl92c_llt_write(hw, i , i + 1);
199		if (true != rst) {
200			pr_err("===> %s #1 fail\n", __func__);
201			return rst;
202		}
203	}
204	/* end of list */
205	rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
206	if (true != rst) {
207		pr_err("===> %s #2 fail\n", __func__);
208		return rst;
209	}
210	/* Make the other pages as ring buffer
211	 * This ring buffer is used as beacon buffer if we config this MAC
212	 *  as two MAC transfer.
213	 * Otherwise used as local loopback buffer.
214	 */
215	for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
216		rst = rtl92c_llt_write(hw, i, (i + 1));
217		if (true != rst) {
218			pr_err("===> %s #3 fail\n", __func__);
219			return rst;
220		}
221	}
222	/* Let last entry point to the start entry of ring buffer */
223	rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
224	if (true != rst) {
225		pr_err("===> %s #4 fail\n", __func__);
226		return rst;
227	}
228	return rst;
229}
230void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
231		     u8 *p_macaddr, bool is_group, u8 enc_algo,
232		     bool is_wepkey, bool clear_all)
233{
234	struct rtl_priv *rtlpriv = rtl_priv(hw);
235	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
236	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
237	u8 *macaddr = p_macaddr;
238	u32 entry_id = 0;
239	bool is_pairwise = false;
240	static u8 cam_const_addr[4][6] = {
241		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
242		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
243		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
244		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
245	};
246	static u8 cam_const_broad[] = {
247		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
248	};
249
250	if (clear_all) {
251		u8 idx = 0;
252		u8 cam_offset = 0;
253		u8 clear_number = 5;
254
255		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
256		for (idx = 0; idx < clear_number; idx++) {
257			rtl_cam_mark_invalid(hw, cam_offset + idx);
258			rtl_cam_empty_entry(hw, cam_offset + idx);
259			if (idx < 5) {
260				memset(rtlpriv->sec.key_buf[idx], 0,
261				       MAX_KEY_LEN);
262				rtlpriv->sec.key_len[idx] = 0;
263			}
264		}
265	} else {
266		switch (enc_algo) {
267		case WEP40_ENCRYPTION:
268			enc_algo = CAM_WEP40;
269			break;
270		case WEP104_ENCRYPTION:
271			enc_algo = CAM_WEP104;
272			break;
273		case TKIP_ENCRYPTION:
274			enc_algo = CAM_TKIP;
275			break;
276		case AESCCMP_ENCRYPTION:
277			enc_algo = CAM_AES;
278			break;
279		default:
280			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
281				 "illegal switch case\n");
282			enc_algo = CAM_TKIP;
283			break;
284		}
285		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
286			macaddr = cam_const_addr[key_index];
287			entry_id = key_index;
288		} else {
289			if (is_group) {
290				macaddr = cam_const_broad;
291				entry_id = key_index;
292			} else {
293				if (mac->opmode == NL80211_IFTYPE_AP ||
294				    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
295					entry_id = rtl_cam_get_free_entry(hw,
296								 p_macaddr);
297					if (entry_id >=  TOTAL_CAM_ENTRY) {
298						RT_TRACE(rtlpriv, COMP_SEC,
299							 DBG_EMERG,
300							 "Can not find free hw security cam entry\n");
301						return;
302					}
303				} else {
304					entry_id = CAM_PAIRWISE_KEY_POSITION;
305				}
306
307				key_index = PAIRWISE_KEYIDX;
 
308				is_pairwise = true;
309			}
310		}
311		if (rtlpriv->sec.key_len[key_index] == 0) {
312			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
313				 "delete one entry\n");
314			if (mac->opmode == NL80211_IFTYPE_AP ||
315			    mac->opmode == NL80211_IFTYPE_MESH_POINT)
316				rtl_cam_del_entry(hw, p_macaddr);
317			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
318		} else {
319			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
320				 "The insert KEY length is %d\n",
321				 rtlpriv->sec.key_len[PAIRWISE_KEYIDX]);
322			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
323				 "The insert KEY is %x %x\n",
324				 rtlpriv->sec.key_buf[0][0],
325				 rtlpriv->sec.key_buf[0][1]);
326			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
327				 "add one entry\n");
328			if (is_pairwise) {
329				RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
330					      "Pairwise Key content",
331					      rtlpriv->sec.pairwise_key,
332					      rtlpriv->sec.
333					      key_len[PAIRWISE_KEYIDX]);
334				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
335					 "set Pairwise key\n");
336
337				rtl_cam_add_one_entry(hw, macaddr, key_index,
338						entry_id, enc_algo,
339						CAM_CONFIG_NO_USEDK,
340						rtlpriv->sec.
341						key_buf[key_index]);
342			} else {
343				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
344					 "set group key\n");
345				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
346					rtl_cam_add_one_entry(hw,
347						rtlefuse->dev_addr,
348						PAIRWISE_KEYIDX,
349						CAM_PAIRWISE_KEY_POSITION,
350						enc_algo,
351						CAM_CONFIG_NO_USEDK,
352						rtlpriv->sec.key_buf
353						[entry_id]);
354				}
355				rtl_cam_add_one_entry(hw, macaddr, key_index,
356						entry_id, enc_algo,
357						CAM_CONFIG_NO_USEDK,
358						rtlpriv->sec.key_buf[entry_id]);
359			}
360		}
361	}
362}
363
364u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw)
365{
366	struct rtl_priv *rtlpriv = rtl_priv(hw);
367
368	return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS);
369}
370
371void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
372{
373	struct rtl_priv *rtlpriv = rtl_priv(hw);
374	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
375	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
376	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
377
378	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
379		rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] &
380				0xFFFFFFFF);
381		rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
382				0xFFFFFFFF);
383	} else {
384		rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
385				0xFFFFFFFF);
386		rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
387				0xFFFFFFFF);
388	}
389}
390
391void rtl92c_init_interrupt(struct ieee80211_hw *hw)
392{
393	 rtl92c_enable_interrupt(hw);
394}
395
396void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
397{
398	struct rtl_priv *rtlpriv = rtl_priv(hw);
399
400	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
401	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
402}
403
404void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
405{
406	struct rtl_priv *rtlpriv = rtl_priv(hw);
407	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
408	u32 u4b_ac_param;
409
410	rtl92c_dm_init_edca_turbo(hw);
411	u4b_ac_param = (u32) mac->ac[aci].aifs;
412	u4b_ac_param |=
413	    ((u32) le16_to_cpu(mac->ac[aci].cw_min) & 0xF) <<
414	    AC_PARAM_ECW_MIN_OFFSET;
415	u4b_ac_param |=
416	    ((u32) le16_to_cpu(mac->ac[aci].cw_max) & 0xF) <<
417	    AC_PARAM_ECW_MAX_OFFSET;
418	u4b_ac_param |= (u32) le16_to_cpu(mac->ac[aci].tx_op) <<
419			 AC_PARAM_TXOP_OFFSET;
420	RT_TRACE(rtlpriv, COMP_QOS, DBG_LOUD, "queue:%x, ac_param:%x\n",
421		 aci, u4b_ac_param);
422	switch (aci) {
423	case AC1_BK:
424		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
425		break;
426	case AC0_BE:
427		rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param);
428		break;
429	case AC2_VI:
430		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param);
431		break;
432	case AC3_VO:
433		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param);
434		break;
435	default:
436		RT_ASSERT(false, "invalid aci: %d !\n", aci);
437		break;
438	}
439}
440
441/*-------------------------------------------------------------------------
442 * HW MAC Address
443 *-------------------------------------------------------------------------*/
444void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr)
445{
446	u32 i;
447	struct rtl_priv *rtlpriv = rtl_priv(hw);
448
449	for (i = 0 ; i < ETH_ALEN ; i++)
450		rtl_write_byte(rtlpriv, (REG_MACID + i), *(addr+i));
451
452	RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
453		 "MAC Address: %02X-%02X-%02X-%02X-%02X-%02X\n",
454		 rtl_read_byte(rtlpriv, REG_MACID),
455		 rtl_read_byte(rtlpriv, REG_MACID+1),
456		 rtl_read_byte(rtlpriv, REG_MACID+2),
457		 rtl_read_byte(rtlpriv, REG_MACID+3),
458		 rtl_read_byte(rtlpriv, REG_MACID+4),
459		 rtl_read_byte(rtlpriv, REG_MACID+5));
460}
461
462void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
463{
464	struct rtl_priv *rtlpriv = rtl_priv(hw);
465	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
466}
467
468int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
469{
470	u8 value;
471	struct rtl_priv *rtlpriv = rtl_priv(hw);
472
473	switch (type) {
474	case NL80211_IFTYPE_UNSPECIFIED:
475		value = NT_NO_LINK;
476		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
477			 "Set Network type to NO LINK!\n");
478		break;
479	case NL80211_IFTYPE_ADHOC:
480		value = NT_LINK_AD_HOC;
481		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
482			 "Set Network type to Ad Hoc!\n");
483		break;
484	case NL80211_IFTYPE_STATION:
485		value = NT_LINK_AP;
486		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
487			 "Set Network type to STA!\n");
488		break;
489	case NL80211_IFTYPE_AP:
490		value = NT_AS_AP;
491		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
492			 "Set Network type to AP!\n");
493		break;
494	default:
495		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
496			 "Network type %d not supported!\n", type);
497		return -EOPNOTSUPP;
498	}
499	rtl_write_byte(rtlpriv, (REG_CR + 2), value);
500	return 0;
501}
502
503void rtl92c_init_network_type(struct ieee80211_hw *hw)
504{
505	rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED);
506}
507
508void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw)
509{
510	u16	value16;
511	u32	value32;
512	struct rtl_priv *rtlpriv = rtl_priv(hw);
513
514	/* Response Rate Set */
515	value32 = rtl_read_dword(rtlpriv, REG_RRSR);
516	value32 &= ~RATE_BITMAP_ALL;
517	value32 |= RATE_RRSR_CCK_ONLY_1M;
518	rtl_write_dword(rtlpriv, REG_RRSR, value32);
519	/* SIFS (used in NAV) */
520	value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
521	rtl_write_word(rtlpriv,  REG_SPEC_SIFS, value16);
522	/* Retry Limit */
523	value16 = _LRL(0x30) | _SRL(0x30);
524	rtl_write_dword(rtlpriv,  REG_RL, value16);
525}
526
527void rtl92c_init_rate_fallback(struct ieee80211_hw *hw)
528{
529	struct rtl_priv *rtlpriv = rtl_priv(hw);
530
531	/* Set Data Auto Rate Fallback Retry Count register. */
532	rtl_write_dword(rtlpriv,  REG_DARFRC, 0x00000000);
533	rtl_write_dword(rtlpriv,  REG_DARFRC+4, 0x10080404);
534	rtl_write_dword(rtlpriv,  REG_RARFRC, 0x04030201);
535	rtl_write_dword(rtlpriv,  REG_RARFRC+4, 0x08070605);
536}
537
538static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
539				u8 ctx_sifs)
540{
541	struct rtl_priv *rtlpriv = rtl_priv(hw);
542
543	rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs);
544	rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs);
545}
546
547static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
548				 u8 ctx_sifs)
549{
550	struct rtl_priv *rtlpriv = rtl_priv(hw);
551
552	rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs);
553	rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs);
554}
555
556void rtl92c_init_edca_param(struct ieee80211_hw *hw,
557			    u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs)
558{
559	/* sequence: VO, VI, BE, BK ==> the same as 92C hardware design.
560	 * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function.
561	 */
562	u32 value;
563	struct rtl_priv *rtlpriv = rtl_priv(hw);
564
565	value = (u32)aifs;
566	value |= ((u32)cw_min & 0xF) << 8;
567	value |= ((u32)cw_max & 0xF) << 12;
568	value |= (u32)txop << 16;
569	/* 92C hardware register sequence is the same as queue number. */
570	rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value);
571}
572
573void rtl92c_init_edca(struct ieee80211_hw *hw)
574{
575	u16 value16;
576	struct rtl_priv *rtlpriv = rtl_priv(hw);
577
578	/* disable EDCCA count down, to reduce collison and retry */
579	value16 = rtl_read_word(rtlpriv, REG_RD_CTRL);
580	value16 |= DIS_EDCA_CNT_DWN;
581	rtl_write_word(rtlpriv, REG_RD_CTRL, value16);
582	/* Update SIFS timing.  ??????????
583	 * pHalData->SifsTime = 0x0e0e0a0a; */
584	rtl92c_set_cck_sifs(hw, 0xa, 0xa);
585	rtl92c_set_ofdm_sifs(hw, 0xe, 0xe);
586	/* Set CCK/OFDM SIFS to be 10us. */
587	rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a);
588	rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010);
589	rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204);
590	rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004);
591	/* TXOP */
592	rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B);
593	rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F);
594	rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324);
595	rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226);
596	/* PIFS */
597	rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
598	/* AGGR BREAK TIME Register */
599	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
600	rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040);
601	rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02);
602	rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02);
603}
604
605void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw)
606{
607	struct rtl_priv *rtlpriv = rtl_priv(hw);
608
609	rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631);
610	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
611	/* init AMPDU aggregation number, tuning for Tx's TP, */
612	rtl_write_word(rtlpriv, 0x4CA, 0x0708);
613}
614
615void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode)
616{
617	struct rtl_priv *rtlpriv = rtl_priv(hw);
618
619	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
620}
621
622void rtl92c_init_rdg_setting(struct ieee80211_hw *hw)
623{
624	struct rtl_priv *rtlpriv = rtl_priv(hw);
625
626	rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF);
627	rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
628	rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
629}
630
631void rtl92c_init_retry_function(struct ieee80211_hw *hw)
632{
633	u8	value8;
634	struct rtl_priv *rtlpriv = rtl_priv(hw);
635
636	value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL);
637	value8 |= EN_AMPDU_RTY_NEW;
638	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8);
639	/* Set ACK timeout */
640	rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
641}
642
643void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
644				   enum version_8192c version)
645{
646	struct rtl_priv *rtlpriv = rtl_priv(hw);
647	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
648
649	rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
650	rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
651	rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
652	if (IS_NORMAL_CHIP(rtlhal->version))
653		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
654	else
655		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
656}
657
658void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
659{
660	struct rtl_priv *rtlpriv = rtl_priv(hw);
661
662	rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0);
663}
664
665void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T)
666{
667	struct rtl_priv *rtlpriv = rtl_priv(hw);
668	u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T;
669
670	rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value);
671}
672
673u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw)
674{
675	struct rtl_priv *rtlpriv = rtl_priv(hw);
676
677	return rtl_read_word(rtlpriv, REG_RXFLTMAP0);
678}
679
680void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter)
681{
682	struct rtl_priv *rtlpriv = rtl_priv(hw);
683
684	rtl_write_word(rtlpriv, REG_RXFLTMAP0, filter);
685}
686
687u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw)
688{
689	struct rtl_priv *rtlpriv = rtl_priv(hw);
690
691	return rtl_read_word(rtlpriv, REG_RXFLTMAP1);
692}
693
694void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter)
695{
696	struct rtl_priv *rtlpriv = rtl_priv(hw);
697
698	rtl_write_word(rtlpriv, REG_RXFLTMAP1, filter);
699}
700
701u16 rtl92c_get_data_filter(struct ieee80211_hw *hw)
702{
703	struct rtl_priv *rtlpriv = rtl_priv(hw);
704
705	return rtl_read_word(rtlpriv,  REG_RXFLTMAP2);
706}
707
708void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter)
709{
710	struct rtl_priv *rtlpriv = rtl_priv(hw);
711
712	rtl_write_word(rtlpriv, REG_RXFLTMAP2, filter);
713}
714/*==============================================================*/
715
716static u8 _rtl92c_query_rxpwrpercentage(char antpower)
717{
718	if ((antpower <= -100) || (antpower >= 20))
719		return 0;
720	else if (antpower >= 0)
721		return 100;
722	else
723		return 100 + antpower;
724}
725
726static u8 _rtl92c_evm_db_to_percentage(char value)
727{
728	char ret_val;
729
730	ret_val = value;
731	if (ret_val >= 0)
732		ret_val = 0;
733	if (ret_val <= -33)
734		ret_val = -33;
735	ret_val = 0 - ret_val;
736	ret_val *= 3;
737	if (ret_val == 99)
738		ret_val = 100;
739	return ret_val;
740}
741
 
 
 
 
 
 
 
 
 
 
742static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
743		long currsig)
744{
745	long retsig;
746
747	if (currsig >= 61 && currsig <= 100)
748		retsig = 90 + ((currsig - 60) / 4);
749	else if (currsig >= 41 && currsig <= 60)
750		retsig = 78 + ((currsig - 40) / 2);
751	else if (currsig >= 31 && currsig <= 40)
752		retsig = 66 + (currsig - 30);
753	else if (currsig >= 21 && currsig <= 30)
754		retsig = 54 + (currsig - 20);
755	else if (currsig >= 5 && currsig <= 20)
756		retsig = 42 + (((currsig - 5) * 2) / 3);
757	else if (currsig == 4)
758		retsig = 36;
759	else if (currsig == 3)
760		retsig = 27;
761	else if (currsig == 2)
762		retsig = 18;
763	else if (currsig == 1)
764		retsig = 9;
765	else
766		retsig = currsig;
767	return retsig;
768}
769
770static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
771				      struct rtl_stats *pstats,
772				      struct rx_desc_92c *p_desc,
773				      struct rx_fwinfo_92c *p_drvinfo,
774				      bool packet_match_bssid,
775				      bool packet_toself,
776				      bool packet_beacon)
777{
778	struct rtl_priv *rtlpriv = rtl_priv(hw);
779	struct rtl_phy *rtlphy = &(rtlpriv->phy);
780	struct phy_sts_cck_8192s_t *cck_buf;
781	s8 rx_pwr_all = 0, rx_pwr[4];
782	u8 rf_rx_num = 0, evm, pwdb_all;
783	u8 i, max_spatial_stream;
784	u32 rssi, total_rssi = 0;
785	bool in_powersavemode = false;
786	bool is_cck_rate;
787	u8 *pdesc = (u8 *)p_desc;
788
789	is_cck_rate = RX_HAL_IS_CCK_RATE(p_desc);
790	pstats->packet_matchbssid = packet_match_bssid;
791	pstats->packet_toself = packet_toself;
 
792	pstats->packet_beacon = packet_beacon;
793	pstats->is_cck = is_cck_rate;
794	pstats->RX_SIGQ[0] = -1;
795	pstats->RX_SIGQ[1] = -1;
796	if (is_cck_rate) {
797		u8 report, cck_highpwr;
798		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
799		if (!in_powersavemode)
800			cck_highpwr = rtlphy->cck_high_power;
801		else
802			cck_highpwr = false;
803		if (!cck_highpwr) {
804			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
805			report = cck_buf->cck_agc_rpt & 0xc0;
806			report = report >> 6;
807			switch (report) {
808			case 0x3:
809				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
810				break;
811			case 0x2:
812				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
813				break;
814			case 0x1:
815				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
816				break;
817			case 0x0:
818				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
819				break;
820			}
821		} else {
822			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
823			report = p_drvinfo->cfosho[0] & 0x60;
824			report = report >> 5;
825			switch (report) {
826			case 0x3:
827				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
828				break;
829			case 0x2:
830				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
831				break;
832			case 0x1:
833				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
834				break;
835			case 0x0:
836				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
837				break;
838			}
839		}
840		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
841		pstats->rx_pwdb_all = pwdb_all;
842		pstats->recvsignalpower = rx_pwr_all;
843		if (packet_match_bssid) {
844			u8 sq;
845			if (pstats->rx_pwdb_all > 40)
846				sq = 100;
847			else {
848				sq = cck_buf->sq_rpt;
849				if (sq > 64)
850					sq = 0;
851				else if (sq < 20)
852					sq = 100;
853				else
854					sq = ((64 - sq) * 100) / 44;
855			}
856			pstats->signalquality = sq;
857			pstats->RX_SIGQ[0] = sq;
858			pstats->RX_SIGQ[1] = -1;
859		}
860	} else {
861		rtlpriv->dm.rfpath_rxenable[0] =
862		    rtlpriv->dm.rfpath_rxenable[1] = true;
863		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
864			if (rtlpriv->dm.rfpath_rxenable[i])
865				rf_rx_num++;
866			rx_pwr[i] =
867			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
868			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
869			total_rssi += rssi;
870			rtlpriv->stats.rx_snr_db[i] =
871			    (long)(p_drvinfo->rxsnr[i] / 2);
872
873			if (packet_match_bssid)
874				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
875		}
876		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
877		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
878		pstats->rx_pwdb_all = pwdb_all;
879		pstats->rxpower = rx_pwr_all;
880		pstats->recvsignalpower = rx_pwr_all;
881		if (GET_RX_DESC_RX_MCS(pdesc) &&
882		    GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 &&
883		    GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15)
884			max_spatial_stream = 2;
885		else
886			max_spatial_stream = 1;
887		for (i = 0; i < max_spatial_stream; i++) {
888			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
889			if (packet_match_bssid) {
890				if (i == 0)
891					pstats->signalquality =
892					    (u8) (evm & 0xff);
893				pstats->RX_SIGQ[i] =
894				    (u8) (evm & 0xff);
895			}
896		}
897	}
898	if (is_cck_rate)
899		pstats->signalstrength =
900		    (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all));
901	else if (rf_rx_num != 0)
902		pstats->signalstrength =
903		    (u8) (_rtl92c_signal_scale_mapping
904			  (hw, total_rssi /= rf_rx_num));
905}
906
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
907void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
908					       struct sk_buff *skb,
909					       struct rtl_stats *pstats,
910					       struct rx_desc_92c *pdesc,
911					       struct rx_fwinfo_92c *p_drvinfo)
912{
913	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
914	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
915	struct ieee80211_hdr *hdr;
916	u8 *tmp_buf;
917	u8 *praddr;
918	__le16 fc;
919	u16 type, cpu_fc;
920	bool packet_matchbssid, packet_toself, packet_beacon = false;
921
922	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
923	hdr = (struct ieee80211_hdr *)tmp_buf;
924	fc = hdr->frame_control;
925	cpu_fc = le16_to_cpu(fc);
926	type = WLAN_FC_GET_TYPE(fc);
927	praddr = hdr->addr1;
928	packet_matchbssid =
929	    ((IEEE80211_FTYPE_CTL != type) &&
930	     ether_addr_equal(mac->bssid,
931			      (cpu_fc & IEEE80211_FCTL_TODS) ? hdr->addr1 :
932			      (cpu_fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 :
933			      hdr->addr3) &&
934	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
935
936	packet_toself = packet_matchbssid &&
937	    ether_addr_equal(praddr, rtlefuse->dev_addr);
938	if (ieee80211_is_beacon(fc))
939		packet_beacon = true;
940	_rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
941				   packet_matchbssid, packet_toself,
942				   packet_beacon);
943	rtl_process_phyinfo(hw, tmp_buf, pstats);
944}