blob: 4d77e83eb418985f2ed3fa59c275b9210c6ef780 [file] [log] [blame]
/*
*************************************************************************
* Ralink Tech Inc.
* 5F., No.36, Taiyuan St., Jhubei City,
* Hsinchu County 302,
* Taiwan, R.O.C.
*
* (c) Copyright 2002-2007, Ralink Technology, Inc.
*
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
*************************************************************************
Module Name:
cmm_asic.c
Abstract:
Functions used to communicate with ASIC
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "../rt_config.h"
/* Reset the RFIC setting to new series */
struct rt_rtmp_rf_regs RF2850RegTable[] = {
/* ch R1 R2 R3(TX0~4=0) R4 */
{1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b}
,
{2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f}
,
{3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b}
,
{4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f}
,
{5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b}
,
{6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f}
,
{7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b}
,
{8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f}
,
{9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b}
,
{10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f}
,
{11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b}
,
{12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f}
,
{13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b}
,
{14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193}
,
/* 802.11 UNI / HyperLan 2 */
{36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3}
,
{38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193}
,
{40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183}
,
{44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3}
,
{46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b}
,
{48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b}
,
{52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193}
,
{54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3}
,
{56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b}
,
{60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183}
,
{62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193}
,
{64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}
, /* Plugfest#4, Day4, change RFR3 left4th 9->5. */
/* 802.11 HyperLan 2 */
{100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783}
,
/* 2008.04.30 modified */
/* The system team has AN to improve the EVM value */
/* for channel 102 to 108 for the RT2850/RT2750 dual band solution. */
{102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793}
,
{104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3}
,
{108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193}
,
{110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183}
,
{112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b}
,
{116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3}
,
{118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193}
,
{120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183}
,
{124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193}
,
{126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}
, /* 0x980ed1bb->0x980ed15b required by Rory 20070927 */
{128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3}
,
{132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b}
,
{134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193}
,
{136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b}
,
{140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183}
,
/* 802.11 UNII */
{149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7}
,
{151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187}
,
{153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f}
,
{157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f}
,
{159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7}
,
{161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187}
,
{165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197}
,
{167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f}
,
{169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327}
,
{171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307}
,
{173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f}
,
/* Japan */
{184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}
,
{188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}
,
{192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}
,
{196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}
,
{208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}
,
{212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}
,
{216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}
,
/* still lack of MMAC(Japan) ch 34,38,42,46 */
};
u8 NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(struct rt_rtmp_rf_regs));
struct rt_frequency_item FreqItems3020[] = {
/**************************************************/
/* ISM : 2.4 to 2.483 GHz // */
/**************************************************/
/* 11g */
/**************************************************/
/*-CH---N-------R---K----------- */
{1, 241, 2, 2}
,
{2, 241, 2, 7}
,
{3, 242, 2, 2}
,
{4, 242, 2, 7}
,
{5, 243, 2, 2}
,
{6, 243, 2, 7}
,
{7, 244, 2, 2}
,
{8, 244, 2, 7}
,
{9, 245, 2, 2}
,
{10, 245, 2, 7}
,
{11, 246, 2, 2}
,
{12, 246, 2, 7}
,
{13, 247, 2, 2}
,
{14, 248, 2, 4}
,
};
u8 NUM_OF_3020_CHNL = (sizeof(FreqItems3020) / sizeof(struct rt_frequency_item));
void AsicUpdateAutoFallBackTable(struct rt_rtmp_adapter *pAd, u8 *pRateTable)
{
u8 i;
HT_FBK_CFG0_STRUC HtCfg0;
HT_FBK_CFG1_STRUC HtCfg1;
LG_FBK_CFG0_STRUC LgCfg0;
LG_FBK_CFG1_STRUC LgCfg1;
struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate;
/* set to initial value */
HtCfg0.word = 0x65432100;
HtCfg1.word = 0xedcba988;
LgCfg0.word = 0xedcba988;
LgCfg1.word = 0x00002100;
pNextTxRate = (struct rt_rtmp_tx_rate_switch *) pRateTable + 1;
for (i = 1; i < *((u8 *)pRateTable); i++) {
pCurrTxRate = (struct rt_rtmp_tx_rate_switch *) pRateTable + 1 + i;
switch (pCurrTxRate->Mode) {
case 0: /*CCK */
break;
case 1: /*OFDM */
{
switch (pCurrTxRate->CurrMCS) {
case 0:
LgCfg0.field.OFDMMCS0FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
case 1:
LgCfg0.field.OFDMMCS1FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
case 2:
LgCfg0.field.OFDMMCS2FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
case 3:
LgCfg0.field.OFDMMCS3FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
case 4:
LgCfg0.field.OFDMMCS4FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
case 5:
LgCfg0.field.OFDMMCS5FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
case 6:
LgCfg0.field.OFDMMCS6FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
case 7:
LgCfg0.field.OFDMMCS7FBK =
(pNextTxRate->Mode ==
MODE_OFDM) ? (pNextTxRate->
CurrMCS +
8) : pNextTxRate->
CurrMCS;
break;
}
}
break;
case 2: /*HT-MIX */
case 3: /*HT-GF */
{
if ((pNextTxRate->Mode >= MODE_HTMIX)
&& (pCurrTxRate->CurrMCS !=
pNextTxRate->CurrMCS)) {
switch (pCurrTxRate->CurrMCS) {
case 0:
HtCfg0.field.HTMCS0FBK =
pNextTxRate->CurrMCS;
break;
case 1:
HtCfg0.field.HTMCS1FBK =
pNextTxRate->CurrMCS;
break;
case 2:
HtCfg0.field.HTMCS2FBK =
pNextTxRate->CurrMCS;
break;
case 3:
HtCfg0.field.HTMCS3FBK =
pNextTxRate->CurrMCS;
break;
case 4:
HtCfg0.field.HTMCS4FBK =
pNextTxRate->CurrMCS;
break;
case 5:
HtCfg0.field.HTMCS5FBK =
pNextTxRate->CurrMCS;
break;
case 6:
HtCfg0.field.HTMCS6FBK =
pNextTxRate->CurrMCS;
break;
case 7:
HtCfg0.field.HTMCS7FBK =
pNextTxRate->CurrMCS;
break;
case 8:
HtCfg1.field.HTMCS8FBK =
pNextTxRate->CurrMCS;
break;
case 9:
HtCfg1.field.HTMCS9FBK =
pNextTxRate->CurrMCS;
break;
case 10:
HtCfg1.field.HTMCS10FBK =
pNextTxRate->CurrMCS;
break;
case 11:
HtCfg1.field.HTMCS11FBK =
pNextTxRate->CurrMCS;
break;
case 12:
HtCfg1.field.HTMCS12FBK =
pNextTxRate->CurrMCS;
break;
case 13:
HtCfg1.field.HTMCS13FBK =
pNextTxRate->CurrMCS;
break;
case 14:
HtCfg1.field.HTMCS14FBK =
pNextTxRate->CurrMCS;
break;
case 15:
HtCfg1.field.HTMCS15FBK =
pNextTxRate->CurrMCS;
break;
default:
DBGPRINT(RT_DEBUG_ERROR,
("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n",
pCurrTxRate->
CurrMCS));
}
}
}
break;
}
pNextTxRate = pCurrTxRate;
}
RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
}
/*
========================================================================
Routine Description:
Set MAC register value according operation mode.
OperationMode AND bNonGFExist are for MM and GF Proteciton.
If MM or GF mask is not set, those passing argument doesn't not take effect.
Operation mode meaning:
= 0 : Pure HT, no preotection.
= 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
= 0x10: No Transmission in 40M is protected.
= 0x11: Transmission in both 40M and 20M shall be protected
if (bNonGFExist)
we should choose not to use GF. But still set correct ASIC registers.
========================================================================
*/
void AsicUpdateProtect(struct rt_rtmp_adapter *pAd,
u16 OperationMode,
u8 SetMask,
IN BOOLEAN bDisableBGProtect, IN BOOLEAN bNonGFExist)
{
PROT_CFG_STRUC ProtCfg, ProtCfg4;
u32 Protect[6];
u16 offset;
u8 i;
u32 MacReg = 0;
if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) {
return;
}
if (pAd->BATable.numDoneOriginator) {
/* */
/* enable the RTS/CTS to avoid channel collision */
/* */
SetMask = ALLN_SETPROTECT;
OperationMode = 8;
}
/* Config ASIC RTS threshold register */
RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
MacReg &= 0xFF0000FF;
/* If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 */
if (((pAd->CommonCfg.BACapability.field.AmsduEnable) ||
(pAd->CommonCfg.bAggregationCapable == TRUE))
&& pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) {
MacReg |= (0x1000 << 8);
} else {
MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
}
RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
/* Initial common protection settings */
RTMPZeroMemory(Protect, sizeof(Protect));
ProtCfg4.word = 0;
ProtCfg.word = 0;
ProtCfg.field.TxopAllowGF40 = 1;
ProtCfg.field.TxopAllowGF20 = 1;
ProtCfg.field.TxopAllowMM40 = 1;
ProtCfg.field.TxopAllowMM20 = 1;
ProtCfg.field.TxopAllowOfdm = 1;
ProtCfg.field.TxopAllowCck = 1;
ProtCfg.field.RTSThEn = 1;
ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
/* update PHY mode and rate */
if (pAd->CommonCfg.Channel > 14)
ProtCfg.field.ProtectRate = 0x4000;
ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
/* Handle legacy(B/G) protection */
if (bDisableBGProtect) {
/*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; */
ProtCfg.field.ProtectCtrl = 0;
Protect[0] = ProtCfg.word;
Protect[1] = ProtCfg.word;
pAd->FlgCtsEnabled = 0; /* CTS-self is not used */
} else {
/*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; */
ProtCfg.field.ProtectCtrl = 0; /* CCK do not need to be protected */
Protect[0] = ProtCfg.word;
ProtCfg.field.ProtectCtrl = ASIC_CTS; /* OFDM needs using CCK to protect */
Protect[1] = ProtCfg.word;
pAd->FlgCtsEnabled = 1; /* CTS-self is used */
}
/* Decide HT frame protection. */
if ((SetMask & ALLN_SETPROTECT) != 0) {
switch (OperationMode) {
case 0x0:
/* NO PROTECT */
/* 1.All STAs in the BSS are 20/40 MHz HT */
/* 2. in ai 20/40MHz BSS */
/* 3. all STAs are 20MHz in a 20MHz BSS */
/* Pure HT. no protection. */
/* MM20_PROT_CFG */
/* Reserved (31:27) */
/* PROT_TXOP(25:20) -- 010111 */
/* PROT_NAV(19:18) -- 01 (Short NAV protection) */
/* PROT_CTRL(17:16) -- 00 (None) */
/* PROT_RATE(15:0) -- 0x4004 (OFDM 24M) */
Protect[2] = 0x01744004;
/* MM40_PROT_CFG */
/* Reserved (31:27) */
/* PROT_TXOP(25:20) -- 111111 */
/* PROT_NAV(19:18) -- 01 (Short NAV protection) */
/* PROT_CTRL(17:16) -- 00 (None) */
/* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) */
Protect[3] = 0x03f44084;
/* CF20_PROT_CFG */
/* Reserved (31:27) */
/* PROT_TXOP(25:20) -- 010111 */
/* PROT_NAV(19:18) -- 01 (Short NAV protection) */
/* PROT_CTRL(17:16) -- 00 (None) */
/* PROT_RATE(15:0) -- 0x4004 (OFDM 24M) */
Protect[4] = 0x01744004;
/* CF40_PROT_CFG */
/* Reserved (31:27) */
/* PROT_TXOP(25:20) -- 111111 */
/* PROT_NAV(19:18) -- 01 (Short NAV protection) */
/* PROT_CTRL(17:16) -- 00 (None) */
/* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) */
Protect[5] = 0x03f44084;
if (bNonGFExist) {
/* PROT_NAV(19:18) -- 01 (Short NAV protectiion) */
/* PROT_CTRL(17:16) -- 01 (RTS/CTS) */
Protect[4] = 0x01754004;
Protect[5] = 0x03f54084;
}
pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
break;
case 1:
/* This is "HT non-member protection mode." */
/* If there may be non-HT STAs my BSS */
ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */
ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1. */
if (OPSTATUS_TEST_FLAG
(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) {
ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18.. */
ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */
}
/*Assign Protection method for 20&40 MHz packets */
ProtCfg.field.ProtectCtrl = ASIC_RTS;
ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
ProtCfg4.field.ProtectCtrl = ASIC_RTS;
ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
Protect[2] = ProtCfg.word;
Protect[3] = ProtCfg4.word;
Protect[4] = ProtCfg.word;
Protect[5] = ProtCfg4.word;
pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
break;
case 2:
/* If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets */
ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */
ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1. */
/*Assign Protection method for 40MHz packets */
ProtCfg4.field.ProtectCtrl = ASIC_RTS;
ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
Protect[2] = ProtCfg.word;
Protect[3] = ProtCfg4.word;
if (bNonGFExist) {
ProtCfg.field.ProtectCtrl = ASIC_RTS;
ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
}
Protect[4] = ProtCfg.word;
Protect[5] = ProtCfg4.word;
pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
break;
case 3:
/* HT mixed mode. PROTECT ALL! */
/* Assign Rate */
ProtCfg.word = 0x01744004; /*duplicaet legacy 24M. BW set 1. */
ProtCfg4.word = 0x03f44084;
/* both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the */
if (OPSTATUS_TEST_FLAG
(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) {
ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18.. */
ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083 */
}
/*Assign Protection method for 20&40 MHz packets */
ProtCfg.field.ProtectCtrl = ASIC_RTS;
ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
ProtCfg4.field.ProtectCtrl = ASIC_RTS;
ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
Protect[2] = ProtCfg.word;
Protect[3] = ProtCfg4.word;
Protect[4] = ProtCfg.word;
Protect[5] = ProtCfg4.word;
pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
break;
case 8:
/* Special on for Atheros problem n chip. */
Protect[2] = 0x01754004;
Protect[3] = 0x03f54084;
Protect[4] = 0x01754004;
Protect[5] = 0x03f54084;
pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
break;
}
}
offset = CCK_PROT_CFG;
for (i = 0; i < 6; i++) {
if ((SetMask & (1 << i))) {
RTMP_IO_WRITE32(pAd, offset + i * 4, Protect[i]);
}
}
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicSwitchChannel(struct rt_rtmp_adapter *pAd, u8 Channel, IN BOOLEAN bScan)
{
unsigned long R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
char TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; /*Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; */
u8 index;
u32 Value = 0; /*BbpReg, Value; */
struct rt_rtmp_rf_regs *RFRegTable;
u8 RFValue;
RFValue = 0;
/* Search Tx power value */
/* We can't use ChannelList to search channel, since some central channl's txpowr doesn't list */
/* in ChannelList, so use TxPower array instead. */
/* */
for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) {
if (Channel == pAd->TxPower[index].Channel) {
TxPwer = pAd->TxPower[index].Power;
TxPwer2 = pAd->TxPower[index].Power2;
break;
}
}
if (index == MAX_NUM_OF_CHANNELS) {
DBGPRINT(RT_DEBUG_ERROR,
("AsicSwitchChannel: Can't find the Channel#%d \n",
Channel));
}
#ifdef RT30xx
/* The RF programming sequence is difference between 3xxx and 2xxx */
if ((IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3390(pAd))
&& ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)
|| (pAd->RfIcType == RFIC_3021)
|| (pAd->RfIcType == RFIC_3022))) {
/* modify by WY for Read RF Reg. error */
for (index = 0; index < NUM_OF_3020_CHNL; index++) {
if (Channel == FreqItems3020[index].Channel) {
/* Programming channel parameters */
RT30xxWriteRFRegister(pAd, RF_R02,
FreqItems3020[index].N);
RT30xxWriteRFRegister(pAd, RF_R03,
FreqItems3020[index].K);
RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
RFValue =
(RFValue & 0xFC) | FreqItems3020[index].R;
RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
/* Set Tx0 Power */
RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
RFValue = (RFValue & 0xE0) | TxPwer;
RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
/* Set Tx1 Power */
RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
RFValue = (RFValue & 0xE0) | TxPwer2;
RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
/* Tx/Rx Stream setting */
RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
/*if (IS_RT3090(pAd)) */
/* RFValue |= 0x01; // Enable RF block. */
RFValue &= 0x03; /*clear bit[7~2] */
if (pAd->Antenna.field.TxPath == 1)
RFValue |= 0xA0;
else if (pAd->Antenna.field.TxPath == 2)
RFValue |= 0x80;
if (pAd->Antenna.field.RxPath == 1)
RFValue |= 0x50;
else if (pAd->Antenna.field.RxPath == 2)
RFValue |= 0x40;
RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
/* Set RF offset */
RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
/* Set BW */
if (!bScan
&& (pAd->CommonCfg.BBPCurrentBW == BW_40)) {
RFValue = pAd->Mlme.CaliBW40RfR24;
/*DISABLE_11N_CHECK(pAd); */
} else {
RFValue = pAd->Mlme.CaliBW20RfR24;
}
RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
/* Enable RF tuning */
RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
RFValue = RFValue | 0x1;
RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
/* latch channel for future usage. */
pAd->LatchRfRegs.Channel = Channel;
DBGPRINT(RT_DEBUG_TRACE,
("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
Channel, pAd->RfIcType, TxPwer,
TxPwer2, pAd->Antenna.field.TxPath,
FreqItems3020[index].N,
FreqItems3020[index].K,
FreqItems3020[index].R));
break;
}
}
} else
#endif /* RT30xx // */
{
RFRegTable = RF2850RegTable;
switch (pAd->RfIcType) {
case RFIC_2820:
case RFIC_2850:
case RFIC_2720:
case RFIC_2750:
for (index = 0; index < NUM_OF_2850_CHNL; index++) {
if (Channel == RFRegTable[index].Channel) {
R2 = RFRegTable[index].R2;
if (pAd->Antenna.field.TxPath == 1) {
R2 |= 0x4000; /* If TXpath is 1, bit 14 = 1; */
}
if (pAd->Antenna.field.RxPath == 2) {
R2 |= 0x40; /* write 1 to off Rxpath. */
} else if (pAd->Antenna.field.RxPath ==
1) {
R2 |= 0x20040; /* write 1 to off RxPath */
}
if (Channel > 14) {
/* initialize R3, R4 */
R3 = (RFRegTable[index].
R3 & 0xffffc1ff);
R4 = (RFRegTable[index].
R4 & (~0x001f87c0)) |
(pAd->RfFreqOffset << 15);
/* 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB */
/* R3 */
if ((TxPwer >= -7)
&& (TxPwer < 0)) {
TxPwer = (7 + TxPwer);
TxPwer =
(TxPwer >
0xF) ? (0xF)
: (TxPwer);
R3 |= (TxPwer << 10);
DBGPRINT(RT_DEBUG_ERROR,
("AsicSwitchChannel: TxPwer=%d \n",
TxPwer));
} else {
TxPwer =
(TxPwer >
0xF) ? (0xF)
: (TxPwer);
R3 |=
(TxPwer << 10) | (1
<<
9);
}
/* R4 */
if ((TxPwer2 >= -7)
&& (TxPwer2 < 0)) {
TxPwer2 = (7 + TxPwer2);
TxPwer2 =
(TxPwer2 >
0xF) ? (0xF)
: (TxPwer2);
R4 |= (TxPwer2 << 7);
DBGPRINT(RT_DEBUG_ERROR,
("AsicSwitchChannel: TxPwer2=%d \n",
TxPwer2));
} else {
TxPwer2 =
(TxPwer2 >
0xF) ? (0xF)
: (TxPwer2);
R4 |=
(TxPwer2 << 7) | (1
<<
6);
}
} else {
R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); /* set TX power0 */
R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 << 6); /* Set freq Offset & TxPwr1 */
}
/* Based on BBP current mode before changing RF channel. */
if (!bScan
&& (pAd->CommonCfg.BBPCurrentBW ==
BW_40)) {
R4 |= 0x200000;
}
/* Update variables */
pAd->LatchRfRegs.Channel = Channel;
pAd->LatchRfRegs.R1 =
RFRegTable[index].R1;
pAd->LatchRfRegs.R2 = R2;
pAd->LatchRfRegs.R3 = R3;
pAd->LatchRfRegs.R4 = R4;
/* Set RF value 1's set R3[bit2] = [0] */
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R1);
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R2);
RTMP_RF_IO_WRITE32(pAd,
(pAd->LatchRfRegs.
R3 & (~0x04)));
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R4);
RTMPusecDelay(200);
/* Set RF value 2's set R3[bit2] = [1] */
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R1);
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R2);
RTMP_RF_IO_WRITE32(pAd,
(pAd->LatchRfRegs.
R3 | 0x04));
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R4);
RTMPusecDelay(200);
/* Set RF value 3's set R3[bit2] = [0] */
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R1);
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R2);
RTMP_RF_IO_WRITE32(pAd,
(pAd->LatchRfRegs.
R3 & (~0x04)));
RTMP_RF_IO_WRITE32(pAd,
pAd->LatchRfRegs.R4);
break;
}
}
break;
default:
break;
}
DBGPRINT(RT_DEBUG_TRACE,
("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
Channel, pAd->RfIcType, (R3 & 0x00003e00) >> 9,
(R4 & 0x000007c0) >> 6, pAd->Antenna.field.TxPath,
pAd->LatchRfRegs.R1, pAd->LatchRfRegs.R2,
pAd->LatchRfRegs.R3, pAd->LatchRfRegs.R4));
}
/* Change BBP setting during siwtch from a->g, g->a */
if (Channel <= 14) {
unsigned long TxPinCfg = 0x00050F0A; /*Gary 2007/08/09 0x050A0A */
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62,
(0x37 - GET_LNA_GAIN(pAd)));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63,
(0x37 - GET_LNA_GAIN(pAd)));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64,
(0x37 - GET_LNA_GAIN(pAd)));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); /*(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. */
/*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); */
/* Rx High power VGA offset for LNA select */
if (pAd->NicConfig2.field.ExternalLNAForG) {
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
} else {
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
}
/* 5G band selection PIN, bit1 and bit2 are complement */
RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
Value &= (~0x6);
Value |= (0x04);
RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
/* Turn off unused PA or LNA when only 1T or 1R */
if (pAd->Antenna.field.TxPath == 1) {
TxPinCfg &= 0xFFFFFFF3;
}
if (pAd->Antenna.field.RxPath == 1) {
TxPinCfg &= 0xFFFFF3FF;
}
RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
#if defined(RT3090) || defined(RT3390)
/* PCIe PHY Transmit attenuation adjustment */
if (IS_RT3090A(pAd) || IS_RT3390(pAd)) {
TX_ATTENUATION_CTRL_STRUC TxAttenuationCtrl = {
.word = 0};
RTMP_IO_READ32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL,
&TxAttenuationCtrl.word);
if (Channel == 14) /* Channel #14 */
{
TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 1; /* Enable PCIe PHY Tx attenuation */
TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 4; /* 9/16 full drive level */
} else /* Channel #1~#13 */
{
TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 0; /* Disable PCIe PHY Tx attenuation */
TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 0; /* n/a */
}
RTMP_IO_WRITE32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL,
TxAttenuationCtrl.word);
}
#endif
} else {
unsigned long TxPinCfg = 0x00050F05; /*Gary 2007/8/9 0x050505 */
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62,
(0x37 - GET_LNA_GAIN(pAd)));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63,
(0x37 - GET_LNA_GAIN(pAd)));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64,
(0x37 - GET_LNA_GAIN(pAd)));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); /*(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. */
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
/* Rx High power VGA offset for LNA select */
if (pAd->NicConfig2.field.ExternalLNAForA) {
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
} else {
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
}
/* 5G band selection PIN, bit1 and bit2 are complement */
RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
Value &= (~0x6);
Value |= (0x02);
RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
/* Turn off unused PA or LNA when only 1T or 1R */
if (pAd->Antenna.field.TxPath == 1) {
TxPinCfg &= 0xFFFFFFF3;
}
if (pAd->Antenna.field.RxPath == 1) {
TxPinCfg &= 0xFFFFF3FF;
}
RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
}
/* R66 should be set according to Channel and use 20MHz when scanning */
/*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); */
if (bScan)
RTMPSetAGCInitValue(pAd, BW_20);
else
RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
/* */
/* On 11A, We should delay and wait RF/BBP to be stable */
/* and the appropriate time should be 1000 micro seconds */
/* 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. */
/* */
RTMPusecDelay(1000);
}
void AsicResetBBPAgent(struct rt_rtmp_adapter *pAd)
{
BBP_CSR_CFG_STRUC BbpCsr;
DBGPRINT(RT_DEBUG_ERROR, ("Reset BBP Agent busy bit!\n"));
/* Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. */
RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word);
BbpCsr.field.Busy = 0;
RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word);
}
/*
==========================================================================
Description:
This function is required for 2421 only, and should not be used during
site survey. It's only required after NIC decided to stay at a channel
for a longer period.
When this function is called, it's always after AsicSwitchChannel().
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicLockChannel(struct rt_rtmp_adapter *pAd, u8 Channel)
{
}
void AsicRfTuningExec(void *SystemSpecific1,
void *FunctionContext,
void *SystemSpecific2, void *SystemSpecific3)
{
}
/*
==========================================================================
Description:
Gives CCK TX rate 2 more dB TX power.
This routine works only in LINK UP in INFRASTRUCTURE mode.
calculate desired Tx power in RF R3.Tx0~5, should consider -
0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
1. TxPowerPercentage
2. auto calibration based on TSSI feedback
3. extra 2 db for CCK
4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
it should be called AFTER MlmeDynamicTxRatSwitching()
==========================================================================
*/
void AsicAdjustTxPower(struct rt_rtmp_adapter *pAd)
{
int i, j;
char DeltaPwr = 0;
BOOLEAN bAutoTxAgc = FALSE;
u8 TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
u8 BbpR1 = 0, BbpR49 = 0, idx;
char *pTxAgcCompensate;
unsigned long TxPwr[5];
char Value;
char Rssi = -127;
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) ||
#ifdef RTMP_MAC_PCI
(pAd->bPCIclkOff == TRUE) ||
#endif /* RTMP_MAC_PCI // */
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
return;
Rssi = RTMPMaxRssi(pAd,
pAd->StaCfg.RssiSample.AvgRssi0,
pAd->StaCfg.RssiSample.AvgRssi1,
pAd->StaCfg.RssiSample.AvgRssi2);
if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
if (pAd->CommonCfg.CentralChannel > 14) {
TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
} else {
TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
}
} else {
if (pAd->CommonCfg.Channel > 14) {
TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
} else {
TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
}
}
/* TX power compensation for temperature variation based on TSSI. try every 4 second */
if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) {
if (pAd->CommonCfg.Channel <= 14) {
/* bg channel */
bAutoTxAgc = pAd->bAutoTxAgcG;
TssiRef = pAd->TssiRefG;
pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
TxAgcStep = pAd->TxAgcStepG;
pTxAgcCompensate = &pAd->TxAgcCompensateG;
} else {
/* a channel */
bAutoTxAgc = pAd->bAutoTxAgcA;
TssiRef = pAd->TssiRefA;
pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
TxAgcStep = pAd->TxAgcStepA;
pTxAgcCompensate = &pAd->TxAgcCompensateA;
}
if (bAutoTxAgc) {
/* BbpR1 is unsigned char */
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
/* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
/* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
/* step value is defined in pAd->TxAgcStepG for tx power value */
/* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
/* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
above value are examined in mass factory production */
/* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
/* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
/* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
/* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
if (BbpR49 > pTssiMinusBoundary[1]) {
/* Reading is larger than the reference value */
/* check for how large we need to decrease the Tx power */
for (idx = 1; idx < 5; idx++) {
if (BbpR49 <= pTssiMinusBoundary[idx]) /* Found the range */
break;
}
/* The index is the step we should decrease, idx = 0 means there is nothing to compensate */
/* if (R3 > (unsigned long)(TxAgcStep * (idx-1))) */
*pTxAgcCompensate = -(TxAgcStep * (idx - 1));
/* else */
/* *pTxAgcCompensate = -((u8)R3); */
DeltaPwr += (*pTxAgcCompensate);
DBGPRINT(RT_DEBUG_TRACE,
("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
BbpR49, TssiRef, TxAgcStep, idx - 1));
} else if (BbpR49 < pTssiPlusBoundary[1]) {
/* Reading is smaller than the reference value */
/* check for how large we need to increase the Tx power */
for (idx = 1; idx < 5; idx++) {
if (BbpR49 >= pTssiPlusBoundary[idx]) /* Found the range */
break;
}
/* The index is the step we should increase, idx = 0 means there is nothing to compensate */
*pTxAgcCompensate = TxAgcStep * (idx - 1);
DeltaPwr += (*pTxAgcCompensate);
DBGPRINT(RT_DEBUG_TRACE,
("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
BbpR49, TssiRef, TxAgcStep, idx - 1));
} else {
*pTxAgcCompensate = 0;
DBGPRINT(RT_DEBUG_TRACE,
(" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
BbpR49, TssiRef, TxAgcStep, 0));
}
}
} else {
if (pAd->CommonCfg.Channel <= 14) {
bAutoTxAgc = pAd->bAutoTxAgcG;
pTxAgcCompensate = &pAd->TxAgcCompensateG;
} else {
bAutoTxAgc = pAd->bAutoTxAgcA;
pTxAgcCompensate = &pAd->TxAgcCompensateA;
}
if (bAutoTxAgc)
DeltaPwr += (*pTxAgcCompensate);
}
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
BbpR1 &= 0xFC;
/* calculate delta power based on the percentage specified from UI */
/* E2PROM setting is calibrated for maximum TX power (i.e. 100%) */
/* We lower TX power here according to the percentage specified from UI */
if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) /* AUTO TX POWER control */
{
{
/* to patch high power issue with some APs, like Belkin N1. */
if (Rssi > -35) {
BbpR1 |= 0x02; /* DeltaPwr -= 12; */
} else if (Rssi > -40) {
BbpR1 |= 0x01; /* DeltaPwr -= 6; */
} else;
}
} else if (pAd->CommonCfg.TxPowerPercentage > 90) /* 91 ~ 100% & AUTO, treat as 100% in terms of mW */
;
else if (pAd->CommonCfg.TxPowerPercentage > 60) /* 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; */
{
DeltaPwr -= 1;
} else if (pAd->CommonCfg.TxPowerPercentage > 30) /* 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; */
{
DeltaPwr -= 3;
} else if (pAd->CommonCfg.TxPowerPercentage > 15) /* 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; */
{
BbpR1 |= 0x01;
} else if (pAd->CommonCfg.TxPowerPercentage > 9) /* 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; */
{
BbpR1 |= 0x01;
DeltaPwr -= 3;
} else /* 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; */
{
BbpR1 |= 0x02;
}
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
/* reset different new tx power for different TX rate */
for (i = 0; i < 5; i++) {
if (TxPwr[i] != 0xffffffff) {
for (j = 0; j < 8; j++) {
Value = (char)((TxPwr[i] >> j * 4) & 0x0F); /* 0 ~ 15 */
if ((Value + DeltaPwr) < 0) {
Value = 0; /* min */
} else if ((Value + DeltaPwr) > 0xF) {
Value = 0xF; /* max */
} else {
Value += DeltaPwr; /* temperature compensation */
}
/* fill new value to CSR offset */
TxPwr[i] =
(TxPwr[i] & ~(0x0000000F << j * 4)) | (Value
<< j
* 4);
}
/* write tx power value to CSR */
/* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
TX power for OFDM 6M/9M
TX power for CCK5.5M/11M
TX power for CCK1M/2M */
/* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i * 4, TxPwr[i]);
}
}
}
/*
==========================================================================
Description:
put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
the wakeup timer timeout. Driver has to issue a separate command to wake
PHY up.
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd,
u16 TbttNumToNextWakeUp)
{
RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
}
/*
==========================================================================
Description:
AsicForceWakeup() is used whenever manual wakeup is required
AsicForceSleep() should only be used when not in INFRA BSS. When
in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
==========================================================================
*/
void AsicForceSleep(struct rt_rtmp_adapter *pAd)
{
}
/*
==========================================================================
Description:
AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
expired.
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx)
{
DBGPRINT(RT_DEBUG_INFO, ("--> AsicForceWakeup \n"));
RTMP_STA_FORCE_WAKEUP(pAd, bFromTx);
}
/*
==========================================================================
Description:
Set My BSSID
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicSetBssid(struct rt_rtmp_adapter *pAd, u8 *pBssid)
{
unsigned long Addr4;
DBGPRINT(RT_DEBUG_TRACE,
("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", pBssid[0],
pBssid[1], pBssid[2], pBssid[3], pBssid[4], pBssid[5]));
Addr4 = (unsigned long)(pBssid[0]) |
(unsigned long)(pBssid[1] << 8) |
(unsigned long)(pBssid[2] << 16) | (unsigned long)(pBssid[3] << 24);
RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
Addr4 = 0;
/* always one BSSID in STA mode */
Addr4 = (unsigned long)(pBssid[4]) | (unsigned long)(pBssid[5] << 8);
RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
}
void AsicSetMcastWC(struct rt_rtmp_adapter *pAd)
{
struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[MCAST_WCID];
u16 offset;
pEntry->Sst = SST_ASSOC;
pEntry->Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index */
pEntry->PsMode = PWR_ACTIVE;
pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicDelWcidTab(struct rt_rtmp_adapter *pAd, u8 Wcid)
{
unsigned long Addr0 = 0x0, Addr1 = 0x0;
unsigned long offset;
DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n", Wcid));
offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
RTMP_IO_WRITE32(pAd, offset, Addr0);
offset += 4;
RTMP_IO_WRITE32(pAd, offset, Addr1);
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicEnableRDG(struct rt_rtmp_adapter *pAd)
{
TX_LINK_CFG_STRUC TxLinkCfg;
u32 Data = 0;
RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
TxLinkCfg.field.TxRDGEn = 1;
RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
Data &= 0xFFFFFF00;
Data |= 0x80;
RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
/*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); */
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicDisableRDG(struct rt_rtmp_adapter *pAd)
{
TX_LINK_CFG_STRUC TxLinkCfg;
u32 Data = 0;
RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
TxLinkCfg.field.TxRDGEn = 0;
RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
Data &= 0xFFFFFF00;
/*Data |= 0x20; */
#ifndef WIFI_TEST
/*if ( pAd->CommonCfg.bEnableTxBurst ) */
/* Data |= 0x60; // for performance issue not set the TXOP to 0 */
#endif
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
&& (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
) {
/* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode */
if (pAd->CommonCfg.bEnableTxBurst)
Data |= 0x20;
}
RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicDisableSync(struct rt_rtmp_adapter *pAd)
{
BCN_TIME_CFG_STRUC csr;
DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
/* 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect */
/* that NIC will never wakes up because TSF stops and no more */
/* TBTT interrupts */
pAd->TbttTickCount = 0;
RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
csr.field.bBeaconGen = 0;
csr.field.bTBTTEnable = 0;
csr.field.TsfSyncMode = 0;
csr.field.bTsfTicking = 0;
RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicEnableBssSync(struct rt_rtmp_adapter *pAd)
{
BCN_TIME_CFG_STRUC csr;
DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
/* RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000); */
{
csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU */
csr.field.bTsfTicking = 1;
csr.field.TsfSyncMode = 1; /* sync TSF in INFRASTRUCTURE mode */
csr.field.bBeaconGen = 0; /* do NOT generate BEACON */
csr.field.bTBTTEnable = 1;
}
RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
}
/*
==========================================================================
Description:
Note:
BEACON frame in shared memory should be built ok before this routine
can be called. Otherwise, a garbage frame maybe transmitted out every
Beacon period.
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicEnableIbssSync(struct rt_rtmp_adapter *pAd)
{
BCN_TIME_CFG_STRUC csr9;
u8 *ptr;
u32 i;
DBGPRINT(RT_DEBUG_TRACE,
("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n",
pAd->BeaconTxWI.MPDUtotalByteCount));
RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
csr9.field.bBeaconGen = 0;
csr9.field.bTBTTEnable = 0;
csr9.field.bTsfTicking = 0;
RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
#ifdef RTMP_MAC_PCI
/* move BEACON TXD and frame content to on-chip memory */
ptr = (u8 *)& pAd->BeaconTxWI;
for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */
{
u32 longptr =
*ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) +
(*(ptr + 3) << 24);
RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
ptr += 4;
}
/* start right after the 16-byte TXWI field */
ptr = pAd->BeaconBuf;
for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 4) {
u32 longptr =
*ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) +
(*(ptr + 3) << 24);
RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
ptr += 4;
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
/* move BEACON TXD and frame content to on-chip memory */
ptr = (u8 *)& pAd->BeaconTxWI;
for (i = 0; i < TXWI_SIZE; i += 2) /* 16-byte TXWI field */
{
/*u32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); */
/*RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); */
RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
ptr += 2;
}
/* start right after the 16-byte TXWI field */
ptr = pAd->BeaconBuf;
for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 2) {
/*u32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); */
/*RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); */
RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
ptr += 2;
}
#endif /* RTMP_MAC_USB // */
/* */
/* For Wi-Fi faily generated beacons between participating stations. */
/* Set TBTT phase adaptive adjustment step to 8us (default 16us) */
/* don't change settings 2006-5- by Jerry */
/*RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010); */
/* start sending BEACON */
csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU */
csr9.field.bTsfTicking = 1;
csr9.field.TsfSyncMode = 2; /* sync TSF in IBSS mode */
csr9.field.bTBTTEnable = 1;
csr9.field.bBeaconGen = 1;
RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicSetEdcaParm(struct rt_rtmp_adapter *pAd, struct rt_edca_parm *pEdcaParm)
{
EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
AC_TXOP_CSR0_STRUC csr0;
AC_TXOP_CSR1_STRUC csr1;
AIFSN_CSR_STRUC AifsnCsr;
CWMIN_CSR_STRUC CwminCsr;
CWMAX_CSR_STRUC CwmaxCsr;
int i;
Ac0Cfg.word = 0;
Ac1Cfg.word = 0;
Ac2Cfg.word = 0;
Ac3Cfg.word = 0;
if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) {
DBGPRINT(RT_DEBUG_TRACE, ("AsicSetEdcaParm\n"));
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) {
if (pAd->MacTab.Content[i].ValidAsCLI
|| pAd->MacTab.Content[i].ValidAsApCli)
CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.
Content[i],
fCLIENT_STATUS_WMM_CAPABLE);
}
/*======================================================== */
/* MAC Register has a copy . */
/*======================================================== */
/*#ifndef WIFI_TEST */
if (pAd->CommonCfg.bEnableTxBurst) {
/* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode */
Ac0Cfg.field.AcTxop = 0x20; /* Suggest by John for TxBurst in HT Mode */
} else
Ac0Cfg.field.AcTxop = 0; /* QID_AC_BE */
/*#else */
/* Ac0Cfg.field.AcTxop = 0; // QID_AC_BE */
/*#endif */
Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
Ac0Cfg.field.Aifsn = 2;
RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
Ac1Cfg.field.AcTxop = 0; /* QID_AC_BK */
Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
Ac1Cfg.field.Aifsn = 2;
RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
if (pAd->CommonCfg.PhyMode == PHY_11B) {
Ac2Cfg.field.AcTxop = 192; /* AC_VI: 192*32us ~= 6ms */
Ac3Cfg.field.AcTxop = 96; /* AC_VO: 96*32us ~= 3ms */
} else {
Ac2Cfg.field.AcTxop = 96; /* AC_VI: 96*32us ~= 3ms */
Ac3Cfg.field.AcTxop = 48; /* AC_VO: 48*32us ~= 1.5ms */
}
Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
Ac2Cfg.field.Aifsn = 2;
RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
Ac3Cfg.field.Aifsn = 2;
RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
/*======================================================== */
/* DMA Register has a copy too. */
/*======================================================== */
csr0.field.Ac0Txop = 0; /* QID_AC_BE */
csr0.field.Ac1Txop = 0; /* QID_AC_BK */
RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
if (pAd->CommonCfg.PhyMode == PHY_11B) {
csr1.field.Ac2Txop = 192; /* AC_VI: 192*32us ~= 6ms */
csr1.field.Ac3Txop = 96; /* AC_VO: 96*32us ~= 3ms */
} else {
csr1.field.Ac2Txop = 96; /* AC_VI: 96*32us ~= 3ms */
csr1.field.Ac3Txop = 48; /* AC_VO: 48*32us ~= 1.5ms */
}
RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
CwminCsr.word = 0;
CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
CwmaxCsr.word = 0;
CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(struct rt_edca_parm));
} else {
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
/*======================================================== */
/* MAC Register has a copy. */
/*======================================================== */
/* */
/* Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 */
/* To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. */
/* */
/*pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this */
Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
Ac0Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BE];
Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; /*+1; */
Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; /*+2; */
Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; /*+1; */
Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
if (pAd->Antenna.field.TxPath == 1) {
Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI] + 1;
Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI] + 1;
} else {
Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
}
Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 1;
#ifdef RTMP_MAC_USB
Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 3;
#endif /* RTMP_MAC_USB // */
{
/* Tuning for Wi-Fi WMM S06 */
if (pAd->CommonCfg.bWiFiTest &&
pEdcaParm->Aifsn[QID_AC_VI] == 10)
Ac2Cfg.field.Aifsn -= 1;
/* Tuning for TGn Wi-Fi 5.2.32 */
/* STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta */
if (STA_TGN_WIFI_ON(pAd) &&
pEdcaParm->Aifsn[QID_AC_VI] == 10) {
Ac0Cfg.field.Aifsn = 3;
Ac2Cfg.field.AcTxop = 5;
}
#ifdef RT30xx
if (pAd->RfIcType == RFIC_3020
|| pAd->RfIcType == RFIC_2020) {
/* Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta. */
Ac2Cfg.field.Aifsn = 5;
}
#endif /* RT30xx // */
}
Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
/*#ifdef WIFI_TEST */
if (pAd->CommonCfg.bWiFiTest) {
if (Ac3Cfg.field.AcTxop == 102) {
Ac0Cfg.field.AcTxop =
pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->
Txop[QID_AC_BE] : 10;
Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE] - 1; /* AIFSN must >= 1 */
Ac1Cfg.field.AcTxop =
pEdcaParm->Txop[QID_AC_BK];
Ac1Cfg.field.Aifsn =
pEdcaParm->Aifsn[QID_AC_BK];
Ac2Cfg.field.AcTxop =
pEdcaParm->Txop[QID_AC_VI];
} /* End of if */
}
/*#endif // WIFI_TEST // */
RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
/*======================================================== */
/* DMA Register has a copy too. */
/*======================================================== */
csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
CwminCsr.word = 0;
CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; /*for TGn wifi test */
RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
CwmaxCsr.word = 0;
CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
AifsnCsr.word = 0;
AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BE]; */
AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BK]; */
AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VI]; */
{
/* Tuning for Wi-Fi WMM S06 */
if (pAd->CommonCfg.bWiFiTest &&
pEdcaParm->Aifsn[QID_AC_VI] == 10)
AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
/* Tuning for TGn Wi-Fi 5.2.32 */
/* STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta */
if (STA_TGN_WIFI_ON(pAd) &&
pEdcaParm->Aifsn[QID_AC_VI] == 10) {
AifsnCsr.field.Aifsn0 = 3;
AifsnCsr.field.Aifsn2 = 7;
}
if (INFRA_ON(pAd))
CLIENT_STATUS_SET_FLAG(&pAd->MacTab.
Content[BSSID_WCID],
fCLIENT_STATUS_WMM_CAPABLE);
}
{
AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; /*pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test */
#ifdef RT30xx
/* TODO: Shiang, this modification also suitable for RT3052/RT3050 ??? */
if (pAd->RfIcType == RFIC_3020
|| pAd->RfIcType == RFIC_2020) {
AifsnCsr.field.Aifsn2 = 0x2; /*pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04. */
}
#endif /* RT30xx // */
}
RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm,
sizeof(struct rt_edca_parm));
if (!ADHOC_ON(pAd)) {
DBGPRINT(RT_DEBUG_TRACE,
("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n",
pEdcaParm->EdcaUpdateCount));
DBGPRINT(RT_DEBUG_TRACE,
(" AC_BE %2d %2d %2d %4d %d\n",
pEdcaParm->Aifsn[0], pEdcaParm->Cwmin[0],
pEdcaParm->Cwmax[0], pEdcaParm->Txop[0] << 5,
pEdcaParm->bACM[0]));
DBGPRINT(RT_DEBUG_TRACE,
(" AC_BK %2d %2d %2d %4d %d\n",
pEdcaParm->Aifsn[1], pEdcaParm->Cwmin[1],
pEdcaParm->Cwmax[1], pEdcaParm->Txop[1] << 5,
pEdcaParm->bACM[1]));
DBGPRINT(RT_DEBUG_TRACE,
(" AC_VI %2d %2d %2d %4d %d\n",
pEdcaParm->Aifsn[2], pEdcaParm->Cwmin[2],
pEdcaParm->Cwmax[2], pEdcaParm->Txop[2] << 5,
pEdcaParm->bACM[2]));
DBGPRINT(RT_DEBUG_TRACE,
(" AC_VO %2d %2d %2d %4d %d\n",
pEdcaParm->Aifsn[3], pEdcaParm->Cwmin[3],
pEdcaParm->Cwmax[3], pEdcaParm->Txop[3] << 5,
pEdcaParm->bACM[3]));
}
}
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
void AsicSetSlotTime(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUseShortSlotTime)
{
unsigned long SlotTime;
u32 RegValue = 0;
if (pAd->CommonCfg.Channel > 14)
bUseShortSlotTime = TRUE;
if (bUseShortSlotTime
&& OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
return;
else if ((!bUseShortSlotTime)
&& (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)))
return;
if (bUseShortSlotTime)
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
else
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
SlotTime = (bUseShortSlotTime) ? 9 : 20;
{
/* force using short SLOT time for FAE to demo performance when TxBurst is ON */
if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
&& (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
|| ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)
&& (pAd->CommonCfg.BACapability.field.Policy ==
BA_NOTUSE))
) {
/* In this case, we will think it is doing Wi-Fi test */
/* And we will not set to short slot when bEnableTxBurst is TRUE. */
} else if (pAd->CommonCfg.bEnableTxBurst) {
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
SlotTime = 9;
}
}
/* */
/* For some reasons, always set it to short slot time. */
/* */
/* ToDo: Should consider capability with 11B */
/* */
{
if (pAd->StaCfg.BssType == BSS_ADHOC) {
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
SlotTime = 20;
}
}
RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
RegValue = RegValue & 0xFFFFFF00;
RegValue |= SlotTime;
RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
}
/*
========================================================================
Description:
Add Shared key information into ASIC.
Update shared key, TxMic and RxMic to Asic Shared key table
Update its cipherAlg to Asic Shared key Mode.
Return:
========================================================================
*/
void AsicAddSharedKeyEntry(struct rt_rtmp_adapter *pAd,
u8 BssIndex,
u8 KeyIdx,
u8 CipherAlg,
u8 *pKey, u8 *pTxMic, u8 *pRxMic)
{
unsigned long offset; /*, csr0; */
SHAREDKEY_MODE_STRUC csr1;
#ifdef RTMP_MAC_PCI
int i;
#endif /* RTMP_MAC_PCI // */
DBGPRINT(RT_DEBUG_TRACE,
("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,
KeyIdx));
/*============================================================================================ */
DBGPRINT(RT_DEBUG_TRACE,
("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg],
BssIndex * 4 + KeyIdx));
DBGPRINT_RAW(RT_DEBUG_TRACE,
(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pKey[0], pKey[1], pKey[2], pKey[3], pKey[4],
pKey[5], pKey[6], pKey[7], pKey[8], pKey[9],
pKey[10], pKey[11], pKey[12], pKey[13], pKey[14],
pKey[15]));
if (pRxMic) {
DBGPRINT_RAW(RT_DEBUG_TRACE,
(" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3],
pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7]));
}
if (pTxMic) {
DBGPRINT_RAW(RT_DEBUG_TRACE,
(" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3],
pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7]));
}
/*============================================================================================ */
/* */
/* fill key material - key + TX MIC + RX MIC */
/* */
#ifdef RTMP_MAC_PCI
offset =
SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
for (i = 0; i < MAX_LEN_OF_SHARE_KEY; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
}
offset += MAX_LEN_OF_SHARE_KEY;
if (pTxMic) {
for (i = 0; i < 8; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
}
}
offset += 8;
if (pRxMic) {
for (i = 0; i < 8; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
}
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
{
offset =
SHARED_KEY_TABLE_BASE + (4 * BssIndex +
KeyIdx) * HW_KEY_ENTRY_SIZE;
RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
offset += MAX_LEN_OF_SHARE_KEY;
if (pTxMic) {
RTUSBMultiWrite(pAd, offset, pTxMic, 8);
}
offset += 8;
if (pRxMic) {
RTUSBMultiWrite(pAd, offset, pRxMic, 8);
}
}
#endif /* RTMP_MAC_USB // */
/* */
/* Update cipher algorithm. WSTA always use BSS0 */
/* */
RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2),
&csr1.word);
DBGPRINT(RT_DEBUG_TRACE,
("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n",
BssIndex, KeyIdx, csr1.word));
if ((BssIndex % 2) == 0) {
if (KeyIdx == 0)
csr1.field.Bss0Key0CipherAlg = CipherAlg;
else if (KeyIdx == 1)
csr1.field.Bss0Key1CipherAlg = CipherAlg;
else if (KeyIdx == 2)
csr1.field.Bss0Key2CipherAlg = CipherAlg;
else
csr1.field.Bss0Key3CipherAlg = CipherAlg;
} else {
if (KeyIdx == 0)
csr1.field.Bss1Key0CipherAlg = CipherAlg;
else if (KeyIdx == 1)
csr1.field.Bss1Key1CipherAlg = CipherAlg;
else if (KeyIdx == 2)
csr1.field.Bss1Key2CipherAlg = CipherAlg;
else
csr1.field.Bss1Key3CipherAlg = CipherAlg;
}
DBGPRINT(RT_DEBUG_TRACE,
("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n",
BssIndex, csr1.word));
RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2),
csr1.word);
}
/* IRQL = DISPATCH_LEVEL */
void AsicRemoveSharedKeyEntry(struct rt_rtmp_adapter *pAd,
u8 BssIndex, u8 KeyIdx)
{
/*unsigned long SecCsr0; */
SHAREDKEY_MODE_STRUC csr1;
DBGPRINT(RT_DEBUG_TRACE,
("AsicRemoveSharedKeyEntry: #%d \n", BssIndex * 4 + KeyIdx));
RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2),
&csr1.word);
if ((BssIndex % 2) == 0) {
if (KeyIdx == 0)
csr1.field.Bss0Key0CipherAlg = 0;
else if (KeyIdx == 1)
csr1.field.Bss0Key1CipherAlg = 0;
else if (KeyIdx == 2)
csr1.field.Bss0Key2CipherAlg = 0;
else
csr1.field.Bss0Key3CipherAlg = 0;
} else {
if (KeyIdx == 0)
csr1.field.Bss1Key0CipherAlg = 0;
else if (KeyIdx == 1)
csr1.field.Bss1Key1CipherAlg = 0;
else if (KeyIdx == 2)
csr1.field.Bss1Key2CipherAlg = 0;
else
csr1.field.Bss1Key3CipherAlg = 0;
}
DBGPRINT(RT_DEBUG_TRACE,
("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n",
BssIndex, csr1.word));
RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2),
csr1.word);
ASSERT(BssIndex < 4);
ASSERT(KeyIdx < 4);
}
void AsicUpdateWCIDAttribute(struct rt_rtmp_adapter *pAd,
u16 WCID,
u8 BssIndex,
u8 CipherAlg,
IN BOOLEAN bUsePairewiseKeyTable)
{
unsigned long WCIDAttri = 0, offset;
/* */
/* Update WCID attribute. */
/* Only TxKey could update WCID attribute. */
/* */
offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
WCIDAttri =
(BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
}
void AsicUpdateWCIDIVEIV(struct rt_rtmp_adapter *pAd,
u16 WCID, unsigned long uIV, unsigned long uEIV)
{
unsigned long offset;
offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
RTMP_IO_WRITE32(pAd, offset, uIV);
RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
}
void AsicUpdateRxWCIDTable(struct rt_rtmp_adapter *pAd,
u16 WCID, u8 *pAddr)
{
unsigned long offset;
unsigned long Addr;
offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
Addr = pAddr[0] + (pAddr[1] << 8) + (pAddr[2] << 16) + (pAddr[3] << 24);
RTMP_IO_WRITE32(pAd, offset, Addr);
Addr = pAddr[4] + (pAddr[5] << 8);
RTMP_IO_WRITE32(pAd, offset + 4, Addr);
}
/*
========================================================================
Routine Description:
Set Cipher Key, Cipher algorithm, IV/EIV to Asic
Arguments:
pAd Pointer to our adapter
WCID WCID Entry number.
BssIndex BSSID index, station or none multiple BSSID support
this value should be 0.
KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
pCipherKey Pointer to Cipher Key.
bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
otherwise PairewiseKey table
bTxKey This is the transmit key if enabled.
Return Value:
None
Note:
This routine will set the relative key stuff to Asic including WCID attribute,
Cipher Key, Cipher algorithm and IV/EIV.
IV/EIV will be update if this CipherKey is the transmission key because
ASIC will base on IV's KeyID value to select Cipher Key.
If bTxKey sets to FALSE, this is not the TX key, but it could be
RX key
For AP mode bTxKey must be always set to TRUE.
========================================================================
*/
void AsicAddKeyEntry(struct rt_rtmp_adapter *pAd,
u16 WCID,
u8 BssIndex,
u8 KeyIdx,
struct rt_cipher_key *pCipherKey,
IN BOOLEAN bUsePairewiseKeyTable, IN BOOLEAN bTxKey)
{
unsigned long offset;
/* unsigned long WCIDAttri = 0; */
u8 IV4 = 0;
u8 *pKey = pCipherKey->Key;
/* unsigned long KeyLen = pCipherKey->KeyLen; */
u8 *pTxMic = pCipherKey->TxMic;
u8 *pRxMic = pCipherKey->RxMic;
u8 *pTxtsc = pCipherKey->TxTsc;
u8 CipherAlg = pCipherKey->CipherAlg;
SHAREDKEY_MODE_STRUC csr1;
#ifdef RTMP_MAC_PCI
u8 i;
#endif /* RTMP_MAC_PCI // */
/* ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY); */
DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
/* */
/* 1.) decide key table offset */
/* */
if (bUsePairewiseKeyTable)
offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
else
offset =
SHARED_KEY_TABLE_BASE + (4 * BssIndex +
KeyIdx) * HW_KEY_ENTRY_SIZE;
/* */
/* 2.) Set Key to Asic */
/* */
/*for (i = 0; i < KeyLen; i++) */
#ifdef RTMP_MAC_PCI
for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
}
offset += MAX_LEN_OF_PEER_KEY;
/* */
/* 3.) Set MIC key if available */
/* */
if (pTxMic) {
for (i = 0; i < 8; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
}
}
offset += LEN_TKIP_TXMICK;
if (pRxMic) {
for (i = 0; i < 8; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
}
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
offset += MAX_LEN_OF_PEER_KEY;
/* */
/* 3.) Set MIC key if available */
/* */
if (pTxMic) {
RTUSBMultiWrite(pAd, offset, pTxMic, 8);
}
offset += LEN_TKIP_TXMICK;
if (pRxMic) {
RTUSBMultiWrite(pAd, offset, pRxMic, 8);
}
#endif /* RTMP_MAC_USB // */
/* */
/* 4.) Modify IV/EIV if needs */
/* This will force Asic to use this key ID by setting IV. */
/* */
if (bTxKey) {
#ifdef RTMP_MAC_PCI
offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
/* */
/* Write IV */
/* */
RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
IV4 = (KeyIdx << 6);
if ((CipherAlg == CIPHER_TKIP)
|| (CipherAlg == CIPHER_TKIP_NO_MIC)
|| (CipherAlg == CIPHER_AES))
IV4 |= 0x20; /* turn on extension bit means EIV existence */
RTMP_IO_WRITE8(pAd, offset + 3, IV4);
/* */
/* Write EIV */
/* */
offset += 4;
for (i = 0; i < 4; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
u32 tmpVal;
/* */
/* Write IV */
/* */
IV4 = (KeyIdx << 6);
if ((CipherAlg == CIPHER_TKIP)
|| (CipherAlg == CIPHER_TKIP_NO_MIC)
|| (CipherAlg == CIPHER_AES))
IV4 |= 0x20; /* turn on extension bit means EIV existence */
tmpVal =
pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) +
(pTxtsc[0] << 16) + (IV4 << 24);
RTMP_IO_WRITE32(pAd, offset, tmpVal);
/* */
/* Write EIV */
/* */
offset += 4;
RTMP_IO_WRITE32(pAd, offset, *(u32 *)& pCipherKey->TxTsc[2]);
#endif /* RTMP_MAC_USB // */
AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg,
bUsePairewiseKeyTable);
}
if (!bUsePairewiseKeyTable) {
/* */
/* Only update the shared key security mode */
/* */
RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2),
&csr1.word);
if ((BssIndex % 2) == 0) {
if (KeyIdx == 0)
csr1.field.Bss0Key0CipherAlg = CipherAlg;
else if (KeyIdx == 1)
csr1.field.Bss0Key1CipherAlg = CipherAlg;
else if (KeyIdx == 2)
csr1.field.Bss0Key2CipherAlg = CipherAlg;
else
csr1.field.Bss0Key3CipherAlg = CipherAlg;
} else {
if (KeyIdx == 0)
csr1.field.Bss1Key0CipherAlg = CipherAlg;
else if (KeyIdx == 1)
csr1.field.Bss1Key1CipherAlg = CipherAlg;
else if (KeyIdx == 2)
csr1.field.Bss1Key2CipherAlg = CipherAlg;
else
csr1.field.Bss1Key3CipherAlg = CipherAlg;
}
RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2),
csr1.word);
}
DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
}
/*
========================================================================
Description:
Add Pair-wise key material into ASIC.
Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
Return:
========================================================================
*/
void AsicAddPairwiseKeyEntry(struct rt_rtmp_adapter *pAd,
u8 *pAddr,
u8 WCID, struct rt_cipher_key *pCipherKey)
{
int i;
unsigned long offset;
u8 *pKey = pCipherKey->Key;
u8 *pTxMic = pCipherKey->TxMic;
u8 *pRxMic = pCipherKey->RxMic;
#ifdef DBG
u8 CipherAlg = pCipherKey->CipherAlg;
#endif /* DBG // */
/* EKEY */
offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
#ifdef RTMP_MAC_PCI
for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
#endif /* RTMP_MAC_USB // */
for (i = 0; i < MAX_LEN_OF_PEER_KEY; i += 4) {
u32 Value;
RTMP_IO_READ32(pAd, offset + i, &Value);
}
offset += MAX_LEN_OF_PEER_KEY;
/* MIC KEY */
if (pTxMic) {
#ifdef RTMP_MAC_PCI
for (i = 0; i < 8; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
#endif /* RTMP_MAC_USB // */
}
offset += 8;
if (pRxMic) {
#ifdef RTMP_MAC_PCI
for (i = 0; i < 8; i++) {
RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
#endif /* RTMP_MAC_USB // */
}
DBGPRINT(RT_DEBUG_TRACE,
("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n", WCID,
CipherName[CipherAlg]));
DBGPRINT(RT_DEBUG_TRACE,
(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pKey[0], pKey[1], pKey[2], pKey[3], pKey[4], pKey[5],
pKey[6], pKey[7], pKey[8], pKey[9], pKey[10], pKey[11],
pKey[12], pKey[13], pKey[14], pKey[15]));
if (pRxMic) {
DBGPRINT(RT_DEBUG_TRACE,
(" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3],
pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7]));
}
if (pTxMic) {
DBGPRINT(RT_DEBUG_TRACE,
(" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3],
pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7]));
}
}
/*
========================================================================
Description:
Remove Pair-wise key material from ASIC.
Return:
========================================================================
*/
void AsicRemovePairwiseKeyEntry(struct rt_rtmp_adapter *pAd,
u8 BssIdx, u8 Wcid)
{
unsigned long WCIDAttri;
u16 offset;
/* re-set the entry's WCID attribute as OPEN-NONE. */
offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
WCIDAttri = (BssIdx << 4) | PAIRWISEKEYTABLE;
RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
}
BOOLEAN AsicSendCommandToMcu(struct rt_rtmp_adapter *pAd,
u8 Command,
u8 Token, u8 Arg0, u8 Arg1)
{
if (pAd->chipOps.sendCommandToMcu)
pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1);
return TRUE;
}
void AsicSetRxAnt(struct rt_rtmp_adapter *pAd, u8 Ant)
{
#ifdef RT30xx
/* RT3572 ATE need not to do this. */
RT30xxSetRxAnt(pAd, Ant);
#endif /* RT30xx // */
}
void AsicTurnOffRFClk(struct rt_rtmp_adapter *pAd, u8 Channel)
{
if (pAd->chipOps.AsicRfTurnOff) {
pAd->chipOps.AsicRfTurnOff(pAd);
} else {
/* RF R2 bit 18 = 0 */
u32 R1 = 0, R2 = 0, R3 = 0;
u8 index;
struct rt_rtmp_rf_regs *RFRegTable;
RFRegTable = RF2850RegTable;
switch (pAd->RfIcType) {
case RFIC_2820:
case RFIC_2850:
case RFIC_2720:
case RFIC_2750:
for (index = 0; index < NUM_OF_2850_CHNL; index++) {
if (Channel == RFRegTable[index].Channel) {
R1 = RFRegTable[index].R1 & 0xffffdfff;
R2 = RFRegTable[index].R2 & 0xfffbffff;
R3 = RFRegTable[index].R3 & 0xfff3ffff;
RTMP_RF_IO_WRITE32(pAd, R1);
RTMP_RF_IO_WRITE32(pAd, R2);
/* Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. */
/* Set RF R2 bit18=0, R3 bit[18:19]=0 */
/*if (pAd->StaCfg.bRadio == FALSE) */
if (1) {
RTMP_RF_IO_WRITE32(pAd, R3);
DBGPRINT(RT_DEBUG_TRACE,
("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
Channel,
pAd->RfIcType, R2,
R3));
} else
DBGPRINT(RT_DEBUG_TRACE,
("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
Channel,
pAd->RfIcType, R2));
break;
}
}
break;
default:
break;
}
}
}
void AsicTurnOnRFClk(struct rt_rtmp_adapter *pAd, u8 Channel)
{
/* RF R2 bit 18 = 0 */
u32 R1 = 0, R2 = 0, R3 = 0;
u8 index;
struct rt_rtmp_rf_regs *RFRegTable;
#ifdef PCIE_PS_SUPPORT
/* The RF programming sequence is difference between 3xxx and 2xxx */
if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) {
return;
}
#endif /* PCIE_PS_SUPPORT // */
RFRegTable = RF2850RegTable;
switch (pAd->RfIcType) {
case RFIC_2820:
case RFIC_2850:
case RFIC_2720:
case RFIC_2750:
for (index = 0; index < NUM_OF_2850_CHNL; index++) {
if (Channel == RFRegTable[index].Channel) {
R3 = pAd->LatchRfRegs.R3;
R3 &= 0xfff3ffff;
R3 |= 0x00080000;
RTMP_RF_IO_WRITE32(pAd, R3);
R1 = RFRegTable[index].R1;
RTMP_RF_IO_WRITE32(pAd, R1);
R2 = RFRegTable[index].R2;
if (pAd->Antenna.field.TxPath == 1) {
R2 |= 0x4000; /* If TXpath is 1, bit 14 = 1; */
}
if (pAd->Antenna.field.RxPath == 2) {
R2 |= 0x40; /* write 1 to off Rxpath. */
} else if (pAd->Antenna.field.RxPath == 1) {
R2 |= 0x20040; /* write 1 to off RxPath */
}
RTMP_RF_IO_WRITE32(pAd, R2);
break;
}
}
break;
default:
break;
}
DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
Channel, pAd->RfIcType, R2));
}