MT7601u/src/common/cmm_sync.c
Murat Demirtas 612db32659 FIXED
2016-10-30 14:40:00 +00:00

529 lines
15 KiB
C

/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_sync.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 2004-09-01 modified for rt2561/2661
*/
#include "rt_config.h"
/*BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8.*/
UCHAR BaSizeArray[4] = {8,16,32,64};
#ifdef P2P_SUPPORT
extern UCHAR WILDP2PSSID[];
extern UCHAR WILDP2PSSIDLEN;
#endif /* P2P_SUPPORT */
extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_2GHZ[];
extern UINT16 const Country_Region_GroupNum_2GHZ;
extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_5GHZ[];
extern UINT16 const Country_Region_GroupNum_5GHZ;
/*
==========================================================================
Description:
Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type,
and 3) PHY-mode user selected.
The outcome is used by driver when doing site survey.
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID BuildChannelList(
IN PRTMP_ADAPTER pAd)
{
UCHAR i, j, index=0, num=0;
PCH_DESC pChDesc = NULL;
BOOLEAN bRegionFound = FALSE;
PUCHAR pChannelList;
PUCHAR pChannelListFlag;
NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER));
/* if not 11a-only mode, channel list starts from 2.4Ghz band*/
if (!WMODE_5G_ONLY(pAd->CommonCfg.PhyMode))
{
for (i = 0; i < Country_Region_GroupNum_2GHZ; i++)
{
if ((pAd->CommonCfg.CountryRegion & 0x7f) ==
Country_Region_ChDesc_2GHZ[i].RegionIndex)
{
pChDesc = Country_Region_ChDesc_2GHZ[i].pChDesc;
num = TotalChNum(pChDesc);
bRegionFound = TRUE;
break;
}
}
if (!bRegionFound)
{
DBGPRINT(RT_DEBUG_ERROR,("CountryRegion=%d not support", pAd->CommonCfg.CountryRegion));
return;
}
if (num > 0)
{
os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR));
if (!pChannelList)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__));
return;
}
os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR));
if (!pChannelListFlag)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__));
os_free_mem(NULL, pChannelList);
return;
}
for (i = 0; i < num; i++)
{
pChannelList[i] = GetChannel_2GHZ(pChDesc, i);
pChannelListFlag[i] = GetChannelFlag(pChDesc, i);
}
for (i = 0; i < num; i++)
{
for (j = 0; j < MAX_NUM_OF_CHANNELS; j++)
{
if (pChannelList[i] == pAd->TxPower[j].Channel)
NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
pAd->ChannelList[index + i].Flags = pChannelListFlag[i];
}
#ifdef DOT11_N_SUPPORT
if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel))
pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP;
#endif /* DOT11_N_SUPPORT */
pAd->ChannelList[index+i].MaxTxPwr = 20;
}
index += num;
os_free_mem(NULL, pChannelList);
os_free_mem(NULL, pChannelListFlag);
}
bRegionFound = FALSE;
num = 0;
}
if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
{
for (i = 0; i < Country_Region_GroupNum_5GHZ; i++)
{
if ((pAd->CommonCfg.CountryRegionForABand & 0x7f) ==
Country_Region_ChDesc_5GHZ[i].RegionIndex)
{
pChDesc = Country_Region_ChDesc_5GHZ[i].pChDesc;
num = TotalChNum(pChDesc);
bRegionFound = TRUE;
break;
}
}
if (!bRegionFound)
{
DBGPRINT(RT_DEBUG_ERROR,("CountryRegionABand=%d not support", pAd->CommonCfg.CountryRegionForABand));
return;
}
if (num > 0)
{
UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
#ifdef CONFIG_AP_SUPPORT
UCHAR q=0;
#endif /* CONFIG_AP_SUPPORT */
os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR));
if (!pChannelList)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__));
return;
}
os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR));
if (!pChannelListFlag)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__));
os_free_mem(NULL, pChannelList);
return;
}
for (i = 0; i < num; i++)
{
pChannelList[i] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[i] = GetChannelFlag(pChDesc, i);
}
#ifdef CONFIG_AP_SUPPORT
for (i = 0; i < num; i++)
{
if((pAd->CommonCfg.bIEEE80211H == 0)|| ((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RDDurRegion != FCC)))
{
pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
q++;
}
/*Based on the requiremnt of FCC, some channles could not be used anymore when test DFS function.*/
else if ((pAd->CommonCfg.bIEEE80211H == 1) &&
(pAd->CommonCfg.RDDurRegion == FCC) &&
(pAd->Dot11_H.bDFSIndoor == 1))
{
if((GetChannel_5GHZ(pChDesc, i) < 116) || (GetChannel_5GHZ(pChDesc, i) > 128))
{
pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
q++;
}
}
else if ((pAd->CommonCfg.bIEEE80211H == 1) &&
(pAd->CommonCfg.RDDurRegion == FCC) &&
(pAd->Dot11_H.bDFSIndoor == 0))
{
if((GetChannel_5GHZ(pChDesc, i) < 100) || (GetChannel_5GHZ(pChDesc, i) > 140) )
{
pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
q++;
}
}
}
num = q;
#endif /* CONFIG_AP_SUPPORT */
for (i=0; i<num; i++)
{
for (j=0; j<MAX_NUM_OF_CHANNELS; j++)
{
if (pChannelList[i] == pAd->TxPower[j].Channel)
NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
pAd->ChannelList[index + i].Flags = pChannelListFlag[i];
}
#ifdef DOT11_N_SUPPORT
if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel))
pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP;
#endif /* DOT11_N_SUPPORT */
for (j=0; j<15; j++)
{
if (pChannelList[i] == RadarCh[j])
pAd->ChannelList[index+i].DfsReq = TRUE;
}
pAd->ChannelList[index+i].MaxTxPwr = 20;
}
index += num;
os_free_mem(NULL, pChannelList);
os_free_mem(NULL, pChannelListFlag);
}
}
pAd->ChannelListNum = index;
DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n",
pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum));
#ifdef RT_CFG80211_SUPPORT
for (i=0;i<pAd->ChannelListNum;i++)
{
CFG80211OS_ChanInfoInit(
pAd->pCfg80211_CB,
i,
pAd->ChannelList[i].Channel,
pAd->ChannelList[i].MaxTxPwr,
WMODE_CAP_N(pAd->CommonCfg.PhyMode),
(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20));
}
#endif /* RT_CFG80211_SUPPORT */
#ifdef DBG
for (i=0;i<pAd->ChannelListNum;i++)
{
DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, Flags = %x\n ",
pAd->ChannelList[i].Channel,
pAd->ChannelList[i].Power,
pAd->ChannelList[i].Power2,
pAd->ChannelList[i].Flags));
}
#endif
}
/*
==========================================================================
Description:
This routine return the first channel number according to the country
code selection and RF IC selection (signal band or dual band). It is called
whenever driver need to start a site survey of all supported channels.
Return:
ch - the first channel number of current country code setting
IRQL = PASSIVE_LEVEL
==========================================================================
*/
UCHAR FirstChannel(
IN PRTMP_ADAPTER pAd)
{
return pAd->ChannelList[0].Channel;
}
/*
==========================================================================
Description:
This routine returns the next channel number. This routine is called
during driver need to start a site survey of all supported channels.
Return:
next_channel - the next channel number valid in current country code setting.
Note:
return 0 if no more next channel
==========================================================================
*/
UCHAR NextChannel(
IN PRTMP_ADAPTER pAd,
IN UCHAR channel)
{
int i;
UCHAR next_channel = 0;
#ifdef P2P_SUPPORT
UCHAR CurrentChannel = channel;
if (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH)
{
if (IS_P2P_LISTEN(pAd))
{
DBGPRINT(RT_DEBUG_ERROR, ("Error !! P2P Discovery state machine has change to Listen state during scanning !\n"));
return next_channel;
}
for (i = 0; i < (pAd->P2pCfg.P2pProprietary.ListenChanelCount - 1); i++)
{
if (CurrentChannel == pAd->P2pCfg.P2pProprietary.ListenChanel[i])
next_channel = pAd->P2pCfg.P2pProprietary.ListenChanel[i+1];
}
P2P_INC_CHA_INDEX(pAd->P2pCfg.P2pProprietary.ListenChanelIndex, pAd->P2pCfg.P2pProprietary.ListenChanelCount);
if (next_channel == CurrentChannel)
{
DBGPRINT(RT_DEBUG_INFO, ("SYNC - next_channel equals to CurrentChannel= %d\n", next_channel));
DBGPRINT(RT_DEBUG_INFO, ("SYNC - ListenChannel List : %d %d %d\n", pAd->P2pCfg.P2pProprietary.ListenChanel[0], pAd->P2pCfg.P2pProprietary.ListenChanel[1], pAd->P2pCfg.P2pProprietary.ListenChanel[2]));
next_channel = 0;
}
DBGPRINT(RT_DEBUG_INFO, ("SYNC - P2P Scan return channel = %d. Listen Channel = %d.\n", next_channel, pAd->CommonCfg.Channel));
return next_channel;
}
#endif /* P2P_SUPPORT */
for (i = 0; i < (pAd->ChannelListNum - 1); i++)
{
if (channel == pAd->ChannelList[i].Channel)
{
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
/* Only scan effected channel if this is a SCAN_2040_BSS_COEXIST*/
/* 2009 PF#2: Nee to handle the second channel of AP fall into affected channel range.*/
if ((pAd->MlmeAux.ScanType == SCAN_2040_BSS_COEXIST) && (pAd->ChannelList[i+1].Channel >14))
{
channel = pAd->ChannelList[i+1].Channel;
continue;
}
else
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
{
/* Record this channel's idx in ChannelList array.*/
next_channel = pAd->ChannelList[i+1].Channel;
break;
}
}
}
return next_channel;
}
/*
==========================================================================
Description:
This routine is for Cisco Compatible Extensions 2.X
Spec31. AP Control of Client Transmit Power
Return:
None
Note:
Required by Aironet dBm(mW)
0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW),
17dBm(50mw), 20dBm(100mW)
We supported
3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%),
14dBm(75%), 15dBm(100%)
The client station's actual transmit power shall be within +/- 5dB of
the minimum value or next lower value.
==========================================================================
*/
VOID ChangeToCellPowerLimit(
IN PRTMP_ADAPTER pAd,
IN UCHAR AironetCellPowerLimit)
{
/*
valud 0xFF means that hasn't found power limit information
from the AP's Beacon/Probe response
*/
if (AironetCellPowerLimit == 0xFF)
return;
if (AironetCellPowerLimit < 6) /*Used Lowest Power Percentage.*/
pAd->CommonCfg.TxPowerPercentage = 6;
else if (AironetCellPowerLimit < 9)
pAd->CommonCfg.TxPowerPercentage = 10;
else if (AironetCellPowerLimit < 12)
pAd->CommonCfg.TxPowerPercentage = 25;
else if (AironetCellPowerLimit < 14)
pAd->CommonCfg.TxPowerPercentage = 50;
else if (AironetCellPowerLimit < 15)
pAd->CommonCfg.TxPowerPercentage = 75;
else
pAd->CommonCfg.TxPowerPercentage = 100; /*else used maximum*/
if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault)
pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
}
CHAR ConvertToRssi(RTMP_ADAPTER *pAd, CHAR Rssi, UCHAR rssi_idx, UCHAR AntSel, UCHAR BW)
{
UCHAR RssiOffset, LNAGain;
/* Rssi equals to zero or rssi_idx larger than 3 should be an invalid value*/
if (Rssi == 0 || rssi_idx >= 3)
return -99;
LNAGain = GET_LNA_GAIN(pAd);
if (pAd->LatchRfRegs.Channel > 14)
RssiOffset = pAd->ARssiOffset[rssi_idx];
else
RssiOffset = pAd->BGRssiOffset[rssi_idx];
#ifdef RT65xx
if (IS_RT65XX(pAd))
return (Rssi - LNAGain - RssiOffset);
else
#endif /* RT65xx */
#ifdef MT7601
if ( IS_MT7601(pAd) )
{
CHAR LNA, RSSI;
PCHAR LNATable;
/*
CHAR MainBW40LNA[] = { 1, 18, 35 };
CHAR MainBW20LNA[] = { 1, 18, 36 };
CHAR AuxBW40LNA[] = { 1, 23, 42 };
CHAR AuxBW20LNA[] = { 1, 23, 42 };
*/
CHAR MainBW40LNA[] = { 0, 16, 34 };
CHAR MainBW20LNA[] = { -2, 15, 33 };
CHAR AuxBW40LNA[] = { -2, 16, 34 };
CHAR AuxBW20LNA[] = { -2, 15, 33 };
LNA = (Rssi >> 6) & 0x3;
RSSI = Rssi & 0x3F;
if ( (AntSel >> 7) == 0 )
{
if (BW == BW_40)
LNATable = MainBW40LNA;
else
LNATable = MainBW20LNA;
}
else
{
if (BW == BW_40)
LNATable = AuxBW40LNA;
else
LNATable = AuxBW20LNA;
}
if ( LNA == 3 )
LNA = LNATable[2];
else if ( LNA == 2 )
LNA = LNATable[1];
else
LNA = LNATable[0];
return ( 8 - LNA - RSSI - LNAGain - RssiOffset );
}
else
#endif /* MT7601 */
return (-12 - RssiOffset - LNAGain - Rssi);
}
CHAR ConvertToSnr(RTMP_ADAPTER *pAd, UCHAR Snr)
{
if (pAd->chipCap.SnrFormula == SNR_FORMULA2)
return (Snr * 3 + 8) >> 4;
else if (pAd->chipCap.SnrFormula == SNR_FORMULA3)
return (Snr * 3 / 16 ); /* * 0.1881 */
else
return ((0xeb - Snr) * 3) / 16 ;
}
#ifdef CONFIG_AP_SUPPORT
#ifdef DOT11_N_SUPPORT
extern int DetectOverlappingPeriodicRound;
VOID Handle_BSS_Width_Trigger_Events(
IN PRTMP_ADAPTER pAd)
{
ULONG Now32;
if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
(pAd->CommonCfg.Channel <=14))
{
DBGPRINT(RT_DEBUG_TRACE, ("Rcv BSS Width Trigger Event: 40Mhz --> 20Mhz \n"));
NdisGetSystemUpTime(&Now32);
pAd->CommonCfg.LastRcvBSSWidthTriggerEventsTime = Now32;
pAd->CommonCfg.bRcvBSSWidthTriggerEvents = TRUE;
pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0;
DetectOverlappingPeriodicRound = 31;
}
}
#endif /* DOT11_N_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */