2566 lines
76 KiB
C
2566 lines
76 KiB
C
/*
|
|
*************************************************************************
|
|
* 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));
|
|
}
|