/* ************************************************************************* * 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 #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"; } }