blob: 25302e8363b95be73593732c4b7c31c66ca55ccb [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. *
* *
*************************************************************************
*/
#include <linux/sched.h>
#include "../rt_config.h"
/*
========================================================================
Routine Description:
Remove WPA Key process
Arguments:
pAd Pointer to our adapter
pBuf Pointer to the where the key stored
Return Value:
NDIS_SUCCESS Add key successfully
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
void RTMPSetDesiredRates(struct rt_rtmp_adapter *pAdapter, long Rates)
{
NDIS_802_11_RATES aryRates;
memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES));
switch (pAdapter->CommonCfg.PhyMode) {
case PHY_11A: /* A only */
switch (Rates) {
case 6000000: /*6M */
aryRates[0] = 0x0c; /* 6M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_0;
break;
case 9000000: /*9M */
aryRates[0] = 0x12; /* 9M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_1;
break;
case 12000000: /*12M */
aryRates[0] = 0x18; /* 12M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_2;
break;
case 18000000: /*18M */
aryRates[0] = 0x24; /* 18M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_3;
break;
case 24000000: /*24M */
aryRates[0] = 0x30; /* 24M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_4;
break;
case 36000000: /*36M */
aryRates[0] = 0x48; /* 36M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_5;
break;
case 48000000: /*48M */
aryRates[0] = 0x60; /* 48M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_6;
break;
case 54000000: /*54M */
aryRates[0] = 0x6c; /* 54M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_7;
break;
case -1: /*Auto */
default:
aryRates[0] = 0x6c; /* 54Mbps */
aryRates[1] = 0x60; /* 48Mbps */
aryRates[2] = 0x48; /* 36Mbps */
aryRates[3] = 0x30; /* 24Mbps */
aryRates[4] = 0x24; /* 18M */
aryRates[5] = 0x18; /* 12M */
aryRates[6] = 0x12; /* 9M */
aryRates[7] = 0x0c; /* 6M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_AUTO;
break;
}
break;
case PHY_11BG_MIXED: /* B/G Mixed */
case PHY_11B: /* B only */
case PHY_11ABG_MIXED: /* A/B/G Mixed */
default:
switch (Rates) {
case 1000000: /*1M */
aryRates[0] = 0x02;
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_0;
break;
case 2000000: /*2M */
aryRates[0] = 0x04;
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_1;
break;
case 5000000: /*5.5M */
aryRates[0] = 0x0b; /* 5.5M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_2;
break;
case 11000000: /*11M */
aryRates[0] = 0x16; /* 11M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_3;
break;
case 6000000: /*6M */
aryRates[0] = 0x0c; /* 6M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_0;
break;
case 9000000: /*9M */
aryRates[0] = 0x12; /* 9M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_1;
break;
case 12000000: /*12M */
aryRates[0] = 0x18; /* 12M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_2;
break;
case 18000000: /*18M */
aryRates[0] = 0x24; /* 18M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_3;
break;
case 24000000: /*24M */
aryRates[0] = 0x30; /* 24M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_4;
break;
case 36000000: /*36M */
aryRates[0] = 0x48; /* 36M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_5;
break;
case 48000000: /*48M */
aryRates[0] = 0x60; /* 48M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_6;
break;
case 54000000: /*54M */
aryRates[0] = 0x6c; /* 54M */
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_7;
break;
case -1: /*Auto */
default:
if (pAdapter->CommonCfg.PhyMode == PHY_11B) { /*B Only */
aryRates[0] = 0x16; /* 11Mbps */
aryRates[1] = 0x0b; /* 5.5Mbps */
aryRates[2] = 0x04; /* 2Mbps */
aryRates[3] = 0x02; /* 1Mbps */
} else { /*(B/G) Mixed or (A/B/G) Mixed */
aryRates[0] = 0x6c; /* 54Mbps */
aryRates[1] = 0x60; /* 48Mbps */
aryRates[2] = 0x48; /* 36Mbps */
aryRates[3] = 0x30; /* 24Mbps */
aryRates[4] = 0x16; /* 11Mbps */
aryRates[5] = 0x0b; /* 5.5Mbps */
aryRates[6] = 0x04; /* 2Mbps */
aryRates[7] = 0x02; /* 1Mbps */
}
pAdapter->StaCfg.DesiredTransmitSetting.field.MCS =
MCS_AUTO;
break;
}
break;
}
NdisZeroMemory(pAdapter->CommonCfg.DesireRate,
MAX_LEN_OF_SUPPORTED_RATES);
NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates,
sizeof(NDIS_802_11_RATES));
DBGPRINT(RT_DEBUG_TRACE,
(" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
pAdapter->CommonCfg.DesireRate[0],
pAdapter->CommonCfg.DesireRate[1],
pAdapter->CommonCfg.DesireRate[2],
pAdapter->CommonCfg.DesireRate[3],
pAdapter->CommonCfg.DesireRate[4],
pAdapter->CommonCfg.DesireRate[5],
pAdapter->CommonCfg.DesireRate[6],
pAdapter->CommonCfg.DesireRate[7]));
/* Changing DesiredRate may affect the MAX TX rate we used to TX frames out */
MlmeUpdateTxRates(pAdapter, FALSE, 0);
}
/*
========================================================================
Routine Description:
Remove All WPA Keys
Arguments:
pAd Pointer to our adapter
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
void RTMPWPARemoveAllKeys(struct rt_rtmp_adapter *pAd)
{
u8 i;
DBGPRINT(RT_DEBUG_TRACE,
("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n",
pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus));
RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
/* For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after */
/* Link up. And it will be replaced if user changed it. */
if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
return;
/* For WPA-None, there is no need to remove it, since WinXP won't set it again after */
/* Link up. And it will be replaced if user changed it. */
if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
return;
/* set BSSID wcid entry of the Pair-wise Key table as no-security mode */
AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID);
/* set all shared key mode as no-security. */
for (i = 0; i < SHARE_KEY_NUM; i++) {
DBGPRINT(RT_DEBUG_TRACE,
("remove %s key #%d\n",
CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i));
NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(struct rt_cipher_key));
AsicRemoveSharedKeyEntry(pAd, BSS0, i);
}
RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
}
/*
========================================================================
Routine Description:
As STA's BSSID is a WC too, it uses shared key table.
This function write correct unicast TX key to ASIC WCID.
And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey.
Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key)
Caller guarantee WEP calls this function when set Txkey, default key index=0~3.
Arguments:
pAd Pointer to our adapter
pKey Pointer to the where the key stored
Return Value:
NDIS_SUCCESS Add key successfully
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
/*
========================================================================
Routine Description:
Change NIC PHY mode. Re-association may be necessary. possible settings
include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED
Arguments:
pAd - Pointer to our adapter
phymode -
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
========================================================================
*/
void RTMPSetPhyMode(struct rt_rtmp_adapter *pAd, unsigned long phymode)
{
int i;
/* the selected phymode must be supported by the RF IC encoded in E2PROM */
/* if no change, do nothing */
/* bug fix
if (pAd->CommonCfg.PhyMode == phymode)
return;
*/
pAd->CommonCfg.PhyMode = (u8)phymode;
DBGPRINT(RT_DEBUG_TRACE,
("RTMPSetPhyMode : PhyMode=%d, channel=%d \n",
pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel));
BuildChannelList(pAd);
/* sanity check user setting */
for (i = 0; i < pAd->ChannelListNum; i++) {
if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel)
break;
}
if (i == pAd->ChannelListNum) {
pAd->CommonCfg.Channel = FirstChannel(pAd);
DBGPRINT(RT_DEBUG_ERROR,
("RTMPSetPhyMode: channel is out of range, use first channel=%d \n",
pAd->CommonCfg.Channel));
}
NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
switch (phymode) {
case PHY_11B:
pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRateLen = 4;
pAd->CommonCfg.ExtRateLen = 0;
pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps */
/*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use */
break;
case PHY_11G:
case PHY_11BG_MIXED:
case PHY_11ABG_MIXED:
case PHY_11N_2_4G:
case PHY_11ABGN_MIXED:
case PHY_11BGN_MIXED:
case PHY_11GN_MIXED:
pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[4] = 0x12; /* 9 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRate[5] = 0x24; /* 18 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRate[6] = 0x48; /* 36 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRateLen = 8;
pAd->CommonCfg.ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.ExtRate[1] = 0x18; /* 12 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.ExtRate[2] = 0x30; /* 24 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.ExtRate[3] = 0x60; /* 48 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.ExtRateLen = 4;
pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[4] = 12; /* 6 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[5] = 18; /* 9 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[6] = 24; /* 12 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[7] = 36; /* 18 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[8] = 48; /* 24 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[9] = 72; /* 36 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[10] = 96; /* 48 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[11] = 108; /* 54 mbps, in units of 0.5 Mbps */
break;
case PHY_11A:
case PHY_11AN_MIXED:
case PHY_11AGN_MIXED:
case PHY_11N_5G:
pAd->CommonCfg.SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */
pAd->CommonCfg.SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.SupRateLen = 8;
pAd->CommonCfg.ExtRateLen = 0;
pAd->CommonCfg.DesireRate[0] = 12; /* 6 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[1] = 18; /* 9 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[2] = 24; /* 12 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[3] = 36; /* 18 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[4] = 48; /* 24 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[5] = 72; /* 36 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[6] = 96; /* 48 mbps, in units of 0.5 Mbps */
pAd->CommonCfg.DesireRate[7] = 108; /* 54 mbps, in units of 0.5 Mbps */
/*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use */
break;
default:
break;
}
pAd->CommonCfg.BandState = UNKNOWN_BAND;
}
/*
========================================================================
Routine Description:
Caller ensures we has 802.11n support.
Calls at setting HT from AP/STASetinformation
Arguments:
pAd - Pointer to our adapter
phymode -
========================================================================
*/
void RTMPSetHT(struct rt_rtmp_adapter *pAd, struct rt_oid_set_ht_phymode *pHTPhyMode)
{
/*unsigned long *pmcs; */
u32 Value = 0;
u8 BBPValue = 0;
u8 BBP3Value = 0;
u8 RxStream = pAd->CommonCfg.RxStream;
DBGPRINT(RT_DEBUG_TRACE,
("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n",
pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, pHTPhyMode->MCS,
pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->SHORTGI));
/* Don't zero supportedHyPhy structure. */
RTMPZeroMemory(&pAd->CommonCfg.HtCapability,
sizeof(pAd->CommonCfg.HtCapability));
RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo,
sizeof(pAd->CommonCfg.AddHTInfo));
RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset,
sizeof(pAd->CommonCfg.NewExtChanOffset));
RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy,
sizeof(pAd->CommonCfg.DesiredHtPhy));
if (pAd->CommonCfg.bRdg) {
pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1;
pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1;
} else {
pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0;
pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0;
}
pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3;
pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3;
DBGPRINT(RT_DEBUG_TRACE,
("RTMPSetHT : RxBAWinLimit = %d\n",
pAd->CommonCfg.BACapability.field.RxBAWinLimit));
/* Mimo power save, A-MSDU size, */
pAd->CommonCfg.DesiredHtPhy.AmsduEnable =
(u16)pAd->CommonCfg.BACapability.field.AmsduEnable;
pAd->CommonCfg.DesiredHtPhy.AmsduSize =
(u8)pAd->CommonCfg.BACapability.field.AmsduSize;
pAd->CommonCfg.DesiredHtPhy.MimoPs =
(u8)pAd->CommonCfg.BACapability.field.MMPSmode;
pAd->CommonCfg.DesiredHtPhy.MpduDensity =
(u8)pAd->CommonCfg.BACapability.field.MpduDensity;
pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize =
(u16)pAd->CommonCfg.BACapability.field.AmsduSize;
pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs =
(u16)pAd->CommonCfg.BACapability.field.MMPSmode;
pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity =
(u8)pAd->CommonCfg.BACapability.field.MpduDensity;
DBGPRINT(RT_DEBUG_TRACE,
("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n",
pAd->CommonCfg.DesiredHtPhy.AmsduSize,
pAd->CommonCfg.DesiredHtPhy.MimoPs,
pAd->CommonCfg.DesiredHtPhy.MpduDensity,
pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor));
if (pHTPhyMode->HtMode == HTMODE_GF) {
pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1;
pAd->CommonCfg.DesiredHtPhy.GF = 1;
} else
pAd->CommonCfg.DesiredHtPhy.GF = 0;
/* Decide Rx MCSSet */
switch (RxStream) {
case 1:
pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff;
pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00;
break;
case 2:
pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff;
pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff;
break;
case 3: /* 3*3 */
pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff;
pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff;
pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff;
break;
}
if (pAd->CommonCfg.bForty_Mhz_Intolerant
&& (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40)) {
pHTPhyMode->BW = BW_20;
pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1;
}
if (pHTPhyMode->BW == BW_40) {
pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; /* MCS 32 */
pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1;
if (pAd->CommonCfg.Channel <= 14)
pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1;
pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1;
pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1;
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset =
(pHTPhyMode->ExtOffset ==
EXTCHA_BELOW) ? (EXTCHA_BELOW) : EXTCHA_ABOVE;
/* Set Regsiter for extension channel position. */
RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value);
if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) {
Value |= 0x1;
BBP3Value |= (0x20);
RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
} else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) {
Value &= 0xfe;
BBP3Value &= (~0x20);
RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
}
/* Turn on BBP 40MHz mode now only as AP . */
/* Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection. */
if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd)
) {
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
BBPValue &= (~0x18);
BBPValue |= 0x10;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value);
pAd->CommonCfg.BBPCurrentBW = BW_40;
}
} else {
pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0;
pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0;
pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE;
pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
/* Turn on BBP 20MHz mode by request here. */
{
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
BBPValue &= (~0x18);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
pAd->CommonCfg.BBPCurrentBW = BW_20;
}
}
if (pHTPhyMode->STBC == STBC_USE) {
pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1;
pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1;
pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1;
pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1;
} else {
pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0;
pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0;
}
if (pHTPhyMode->SHORTGI == GI_400) {
pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1;
pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1;
pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1;
pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1;
} else {
pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0;
pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0;
pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0;
pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0;
}
/* We support link adaptation for unsolicit MCS feedback, set to 2. */
pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; /*MCSFBK_UNSOLICIT; */
pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel;
/* 1, the extension channel above the control channel. */
/* EDCA parameters used for AP's own transmission */
if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) {
pAd->CommonCfg.APEdcaParm.bValid = TRUE;
pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6;
pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10;
pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
pAd->CommonCfg.APEdcaParm.Txop[2] = 94;
pAd->CommonCfg.APEdcaParm.Txop[3] = 47;
}
AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
{
RTMPSetIndividualHT(pAd, 0);
}
}
/*
========================================================================
Routine Description:
Caller ensures we has 802.11n support.
Calls at setting HT from AP/STASetinformation
Arguments:
pAd - Pointer to our adapter
phymode -
========================================================================
*/
void RTMPSetIndividualHT(struct rt_rtmp_adapter *pAd, u8 apidx)
{
struct rt_ht_phy_info *pDesired_ht_phy = NULL;
u8 TxStream = pAd->CommonCfg.TxStream;
u8 DesiredMcs = MCS_AUTO;
do {
{
pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo;
DesiredMcs =
pAd->StaCfg.DesiredTransmitSetting.field.MCS;
/*pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; */
break;
}
} while (FALSE);
if (pDesired_ht_phy == NULL) {
DBGPRINT(RT_DEBUG_ERROR,
("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx));
return;
}
RTMPZeroMemory(pDesired_ht_phy, sizeof(struct rt_ht_phy_info));
DBGPRINT(RT_DEBUG_TRACE,
("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs));
/* Check the validity of MCS */
if ((TxStream == 1)
&& ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) {
DBGPRINT(RT_DEBUG_WARN,
("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n",
DesiredMcs));
DesiredMcs = MCS_7;
}
if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20)
&& (DesiredMcs == MCS_32)) {
DBGPRINT(RT_DEBUG_WARN,
("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n"));
DesiredMcs = MCS_0;
}
pDesired_ht_phy->bHtEnable = TRUE;
/* Decide desired Tx MCS */
switch (TxStream) {
case 1:
if (DesiredMcs == MCS_AUTO) {
pDesired_ht_phy->MCSSet[0] = 0xff;
pDesired_ht_phy->MCSSet[1] = 0x00;
} else if (DesiredMcs <= MCS_7) {
pDesired_ht_phy->MCSSet[0] = 1 << DesiredMcs;
pDesired_ht_phy->MCSSet[1] = 0x00;
}
break;
case 2:
if (DesiredMcs == MCS_AUTO) {
pDesired_ht_phy->MCSSet[0] = 0xff;
pDesired_ht_phy->MCSSet[1] = 0xff;
} else if (DesiredMcs <= MCS_15) {
unsigned long mode;
mode = DesiredMcs / 8;
if (mode < 2)
pDesired_ht_phy->MCSSet[mode] =
(1 << (DesiredMcs - mode * 8));
}
break;
case 3: /* 3*3 */
if (DesiredMcs == MCS_AUTO) {
/* MCS0 ~ MCS23, 3 bytes */
pDesired_ht_phy->MCSSet[0] = 0xff;
pDesired_ht_phy->MCSSet[1] = 0xff;
pDesired_ht_phy->MCSSet[2] = 0xff;
} else if (DesiredMcs <= MCS_23) {
unsigned long mode;
mode = DesiredMcs / 8;
if (mode < 3)
pDesired_ht_phy->MCSSet[mode] =
(1 << (DesiredMcs - mode * 8));
}
break;
}
if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) {
if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32)
pDesired_ht_phy->MCSSet[4] = 0x1;
}
/* update HT Rate setting */
if (pAd->OpMode == OPMODE_STA)
MlmeUpdateHtTxRates(pAd, BSS0);
else
MlmeUpdateHtTxRates(pAd, apidx);
}
/*
========================================================================
Routine Description:
Update HT IE from our capability.
Arguments:
Send all HT IE in beacon/probe rsp/assoc rsp/action frame.
========================================================================
*/
void RTMPUpdateHTIE(struct rt_ht_capability *pRtHt,
u8 * pMcsSet,
struct rt_ht_capability_ie * pHtCapability,
struct rt_add_ht_info_ie * pAddHtInfo)
{
RTMPZeroMemory(pHtCapability, sizeof(struct rt_ht_capability_ie));
RTMPZeroMemory(pAddHtInfo, sizeof(struct rt_add_ht_info_ie));
pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth;
pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs;
pHtCapability->HtCapInfo.GF = pRtHt->GF;
pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20;
pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40;
pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC;
pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC;
pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize;
pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor;
pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity;
pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset;
pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth;
pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode;
pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent;
RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet */ pMcsSet, 4); /* rt2860 only support MCS max=32, no need to copy all 16 uchar. */
DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateHTIE <== \n"));
}
/*
========================================================================
Description:
Add Client security information into ASIC WCID table and IVEIV table.
Return:
========================================================================
*/
void RTMPAddWcidAttributeEntry(struct rt_rtmp_adapter *pAd,
u8 BssIdx,
u8 KeyIdx,
u8 CipherAlg, struct rt_mac_table_entry *pEntry)
{
u32 WCIDAttri = 0;
u16 offset;
u8 IVEIV = 0;
u16 Wcid = 0;
{
{
if (BssIdx > BSS0) {
DBGPRINT(RT_DEBUG_ERROR,
("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n",
BssIdx));
return;
}
/* 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. */
/* 2. In Infra mode, the AID:1 MUST be wcid of infra STA. */
/* the AID:2~ assign to mesh link entry. */
if (pEntry)
Wcid = pEntry->Aid;
else
Wcid = MCAST_WCID;
}
}
/* Update WCID attribute table */
offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
{
if (pEntry && pEntry->ValidAsMesh)
WCIDAttri = (CipherAlg << 1) | PAIRWISEKEYTABLE;
else
WCIDAttri = (CipherAlg << 1) | SHAREDKEYTABLE;
}
RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
/* Update IV/EIV table */
offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE);
/* WPA mode */
if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC)
|| (CipherAlg == CIPHER_AES)) {
/* Eiv bit on. keyid always is 0 for pairwise key */
IVEIV = (KeyIdx << 6) | 0x20;
} else {
/* WEP KeyIdx is default tx key. */
IVEIV = (KeyIdx << 6);
}
/* For key index and ext IV bit, so only need to update the position(offset+3). */
#ifdef RTMP_MAC_PCI
RTMP_IO_WRITE8(pAd, offset + 3, IVEIV);
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
RTUSBMultiWrite_OneByte(pAd, offset + 3, &IVEIV);
#endif /* RTMP_MAC_USB // */
DBGPRINT(RT_DEBUG_TRACE,
("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",
Wcid, KeyIdx, CipherName[CipherAlg]));
DBGPRINT(RT_DEBUG_TRACE, (" WCIDAttri = 0x%x \n", WCIDAttri));
}
/*
==========================================================================
Description:
Parse encryption type
Arguments:
pAdapter Pointer to our adapter
wrq Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
char *GetEncryptType(char enc)
{
if (enc == Ndis802_11WEPDisabled)
return "NONE";
if (enc == Ndis802_11WEPEnabled)
return "WEP";
if (enc == Ndis802_11Encryption2Enabled)
return "TKIP";
if (enc == Ndis802_11Encryption3Enabled)
return "AES";
if (enc == Ndis802_11Encryption4Enabled)
return "TKIPAES";
else
return "UNKNOW";
}
char *GetAuthMode(char auth)
{
if (auth == Ndis802_11AuthModeOpen)
return "OPEN";
if (auth == Ndis802_11AuthModeShared)
return "SHARED";
if (auth == Ndis802_11AuthModeAutoSwitch)
return "AUTOWEP";
if (auth == Ndis802_11AuthModeWPA)
return "WPA";
if (auth == Ndis802_11AuthModeWPAPSK)
return "WPAPSK";
if (auth == Ndis802_11AuthModeWPANone)
return "WPANONE";
if (auth == Ndis802_11AuthModeWPA2)
return "WPA2";
if (auth == Ndis802_11AuthModeWPA2PSK)
return "WPA2PSK";
if (auth == Ndis802_11AuthModeWPA1WPA2)
return "WPA1WPA2";
if (auth == Ndis802_11AuthModeWPA1PSKWPA2PSK)
return "WPA1PSKWPA2PSK";
return "UNKNOW";
}
int SetCommonHT(struct rt_rtmp_adapter *pAd)
{
struct rt_oid_set_ht_phymode SetHT;
if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED)
return FALSE;
SetHT.PhyMode = pAd->CommonCfg.PhyMode;
SetHT.TransmitNo = ((u8)pAd->Antenna.field.TxPath);
SetHT.HtMode = (u8)pAd->CommonCfg.RegTransmitSetting.field.HTMODE;
SetHT.ExtOffset =
(u8)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
SetHT.MCS = MCS_AUTO;
SetHT.BW = (u8)pAd->CommonCfg.RegTransmitSetting.field.BW;
SetHT.STBC = (u8)pAd->CommonCfg.RegTransmitSetting.field.STBC;
SetHT.SHORTGI = (u8)pAd->CommonCfg.RegTransmitSetting.field.ShortGI;
RTMPSetHT(pAd, &SetHT);
return TRUE;
}
char *RTMPGetRalinkEncryModeStr(u16 encryMode)
{
switch (encryMode) {
case Ndis802_11WEPDisabled:
return "NONE";
case Ndis802_11WEPEnabled:
return "WEP";
case Ndis802_11Encryption2Enabled:
return "TKIP";
case Ndis802_11Encryption3Enabled:
return "AES";
case Ndis802_11Encryption4Enabled:
return "TKIPAES";
default:
return "UNKNOW";
}
}