diff options
Diffstat (limited to 'network/wlan/WDI/COMMON/DFS.c')
| -rw-r--r-- | network/wlan/WDI/COMMON/DFS.c | 1176 |
1 files changed, 1176 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/DFS.c b/network/wlan/WDI/COMMON/DFS.c new file mode 100644 index 00000000..98a3e8ec --- /dev/null +++ b/network/wlan/WDI/COMMON/DFS.c @@ -0,0 +1,1176 @@ +/****************************************************************************** + + (c) Copyright 2010, RealTEK Technologies Inc. All Rights Reserved. + + Module: DFS.c (RTL8190 Source C File) + + Note: Declare some variable which will be used by any debug command. + + Function: + + Export: + + Abbrev: + + History: + Data Who Remark + + ??/??/2010 Cosa Create initial version. + 12/23/2010 MHC Gather the code from other source files. + +******************************************************************************/ +/* Header Files. */ +#include "Mp_Precomp.h" + +#if WPP_SOFTWARE_TRACE +#include "DFS.tmh" +#endif + + +extern VOID +AP_Restart( + IN PADAPTER Adapter + ); +extern VOID +Hal_PauseTx( + IN PADAPTER Adapter, + u1Byte type + ); + +#if (DFS_SUPPORT == 1) +//============================================ +// The following is for DFS local function, +// start with dfs_*() +//============================================ +VOID +dfs_StaDisableTx( + IN PADAPTER Adapter, + u1Byte type + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if(type == DFS_DISABLE_TX_ALL) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_StaDisableTx all!!\n")); + Hal_PauseTx(Adapter, HW_DISABLE_TX_ALL); + } + else if(type == DFS_DISABLE_TX_DATA) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_StaDisableTx data!!\n")); + Hal_PauseTx(Adapter, HW_DISABLE_TX_DATA); + //ReleaseDataFrameQueued(Adapter); + } + + // set flag to disable tx + pMgntDFS->staMode.bDisableTx = TRUE; +} + +VOID +dfs_StaEnableTx( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_StaEnableTx all!!\n")); + Hal_PauseTx(Adapter, HW_ENABLE_TX_ALL); + pMgntDFS->staMode.bDisableTx = FALSE; +} + +VOID +dfs_StaCsaWorkItemCallback( + IN PVOID Context + ) +{ + PADAPTER Adapter = (PADAPTER)Context; + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if(pMgntDFS->staMode.dfsState == DFS_STA_LISTEN) + { + pMgntDFS->staMode.dfsState = DFS_STA_SWITCH; + + dfs_StaDisableTx(Adapter, DFS_DISABLE_TX_DATA); + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_StaCsaWorkItemCallback(), switch chnl to %d\n", + pMgntDFS->staMode.dfsSwitchChannel)); + + pMgntDFS->staMode.dfsOldConnectedChannel = pMgntInfo->dot11CurrentChannelNumber; + + if(pMgntInfo->dot11CurrentChannelNumber != pMgntDFS->staMode.dfsSwitchChannel) + { + pMgntInfo->dot11CurrentChannelNumber = pMgntDFS->staMode.dfsSwitchChannel; + Mgnt_SwChnl(GetDefaultAdapter(Adapter) + ,pMgntInfo->dot11CurrentChannelNumber,2); + } + + pMgntDFS->staMode.dfsSwitchChannel = 0; + + if(DFS_5G_RADAR_CHANNEL(pMgntInfo->dot11CurrentChannelNumber)) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_StaCsaWorkItemCallback(), DFS_5G_RADAR_CHANNEL, need to monitor first!!\n")); + pMgntDFS->staMode.bMonitorAfterSwitch = TRUE; + pMgntDFS->staMode.bMonitorAfterSwitchIsDone = FALSE; + pMgntDFS->staMode.dfsMonitorStartTime = PlatformGetCurrentTime(); + } + else + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_StaCsaWorkItemCallback(), Non DFS_5G_RADAR_CHANNEL!!\n")); + dfs_StaEnableTx(Adapter); + } + + pMgntDFS->staMode.dfsState = DFS_STA_LISTEN; + } +} + + +u1Byte +dfs_ApConstructAvaChnlList( + IN PADAPTER Adapter, + OUT pu1Byte plist + ) +{ + PRT_CHANNEL_LIST pChanneList = NULL; + u1Byte total, AvailableNum=0, i; + + RtActChannelList(Adapter, RT_CHNL_LIST_ACTION_GET_CHANNEL_LIST, NULL, &pChanneList); + total = pChanneList->ChannelLen; + + for(i=0; i<total; i++) + { + if(!DFS_ApChnlLocked(Adapter, pChanneList->ChnlListEntry[i].ChannelNum)) + { + *plist = pChanneList->ChnlListEntry[i].ChannelNum; + plist++; + AvailableNum++; + } + } + return AvailableNum; +} + +VOID +dfs_ApRejectChnlListDump( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u1Byte i; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApRejectChnlListDump(), Radar channel list dump : \n")); + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[")); + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + if(pMgntDFS->apMode.dfsRadarChnl[i].radarChnl != 0) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("%d, ", pMgntDFS->apMode.dfsRadarChnl[i].radarChnl)); + } + } + RT_TRACE( COMP_DFS, DBG_LOUD, ("]\n")); +} + +VOID +dfs_ApInsertRejectChnl( + IN PADAPTER Adapter, + u1Byte Rejectchnl + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u1Byte i; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApInsertRejectChnl(), insert chnl %d to Radar channel list\n", + Rejectchnl)); + + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + if(pMgntDFS->apMode.dfsRadarChnl[i].radarChnl == 0) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApInsertRejectChnl(), find empty and insert chnl %d to Radar channel list\n", + Rejectchnl)); + pMgntDFS->apMode.dfsRadarChnl[i].radarChnl = Rejectchnl; + pMgntDFS->apMode.dfsRadarChnl[i].rejectTime = PlatformGetCurrentTime(); // in micro-second. + break; + } + else if(pMgntDFS->apMode.dfsRadarChnl[i].radarChnl == Rejectchnl) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApInsertRejectChnl(), chnl %d is already in, update time.\n", + Rejectchnl)); + pMgntDFS->apMode.dfsRadarChnl[i].rejectTime = PlatformGetCurrentTime(); // in micro-second. + break; + } + } + + dfs_ApRejectChnlListDump(Adapter); +} + +VOID +dfs_ApDisableTx( + IN PADAPTER Adapter, + u1Byte type + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if(type == DFS_DISABLE_TX_ALL) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApDisableTx all!!\n")); + Hal_PauseTx(Adapter, HW_DISABLE_TX_ALL); + } + else if(type == DFS_DISABLE_TX_DATA) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApDisableTx data!!\n")); + Hal_PauseTx(Adapter, HW_DISABLE_TX_DATA); + } + + // set flag to disable tx + pMgntDFS->apMode.bDisableTx = TRUE; +} + +VOID +dfs_ApResetRadarDetectCounterAndFlag( + IN PADAPTER Adapter + ) +{ +#if (DFS_TEST_ALARM == 0) + // Clear Radar Counter and Radar flag + PHY_SetBBReg(Adapter, 0xc84, BIT(25), 0); + PHY_SetBBReg(Adapter, 0xc84, BIT(25), 1); + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], After reset radar counter, 0xcf8 = 0x%x, 0xcf4 = 0x%x\n", + PHY_QueryBBReg(Adapter, 0xcf8, bMaskDWord), + PHY_QueryBBReg(Adapter, 0xcf4, bMaskDWord))); +#endif +} + +VOID +dfs_ApResetMonitorState( + IN PADAPTER Adapter, + BOOLEAN bNeedMonitor + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if(bNeedMonitor) + { + pMgntDFS->apMode.bMonitored = FALSE; + } + else + { + pMgntDFS->apMode.bMonitored = TRUE; + } + + pMgntDFS->apMode.monitorStartTime = 0; + pMgntDFS->apMode.dfsState = DFS_AP_DETECTING; + pMgntDFS->apMode.bRadarDetected = FALSE; + pMgntDFS->apMode.dfsSwitchChannel = 0; +} + +VOID +dfs_ApEnableTx( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApEnableTx all!!\n")); + Hal_PauseTx(Adapter, HW_ENABLE_TX_ALL); + pMgntDFS->apMode.bDisableTx = FALSE; +} + +VOID +dfs_ApSwitchChnl( + IN PVOID Context + ) +{ + PADAPTER Adapter = (PADAPTER)Context; + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApSwitchChnl(), switch chnl to %d\n", + pMgntDFS->apMode.dfsSwitchChannel)); + + dfs_ApDisableTx(Adapter, DFS_DISABLE_TX_ALL); + + MgntActSet_802_11_REG_20MHZ_CHANNEL_AND_SWITCH(Adapter, pMgntDFS->apMode.dfsSwitchChannel); + AP_Restart(Adapter); +} + +u1Byte +dfs_ApSelectChannel( + IN PADAPTER Adapter + ) +{ + u1Byte num, which_channel=36; + u1Byte aviChnl[MAX_CHANNEL_NUM]={0}; + u1Byte AviNum=0, i; + + AviNum = dfs_ApConstructAvaChnlList(Adapter, aviChnl); + if(AviNum) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], Avi chnl list = [ ")); + for(i=0; i<AviNum; i++) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("%d, ", aviChnl[i])); + } + RT_TRACE( COMP_DFS, DBG_LOUD, ("]\n")); + + num = (u1Byte)GetRandomNumber(0, AviNum); + which_channel = aviChnl[num]; + } + else + { + which_channel = 153; + } + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], dfs_ApSelectChannel to chnl-%d\n", which_channel)); + return which_channel; +} + +VOID +dfs_ApDetecting( + IN PADAPTER Adapter + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u4Byte radar_detect_val=0, radar_cnt=0; + u4Byte radar_type=0; + + if(!DFS_5G_RADAR_CHANNEL(pMgntInfo->dot11CurrentChannelNumber)) + return; + +#if (DFS_TEST_ALARM == 1)// Trigger one time every DFS_AP_TEST_ALARM_PERIOD + if(pMgntDFS->apMode.testcnt++ >= (DFS_AP_TEST_ALARM_PERIOD*10)) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS test alarm!!\n")); + pMgntDFS->apMode.testcnt = 0; + pMgntDFS->apMode.dfsTestAlert = 1; + pMgntDFS->apMode.bRadarDetected = TRUE; + } +#else + // Check radar detect flag. + radar_detect_val = PHY_QueryBBReg(Adapter, 0xcf8, bMaskDWord); + if( (radar_detect_val & BIT31) || + (radar_detect_val & BIT23) ) + { + radar_type = 1; + pMgntDFS->apMode.bRadarDetected = TRUE; + radar_cnt = PHY_QueryBBReg(Adapter, 0xcf4, bMaskDWord); + } +#endif + + if(pMgntDFS->apMode.bRadarDetected) + { + // Only display counters when real radar signal is detected + if(pMgntDFS->apMode.dfsTestAlert) + pMgntDFS->apMode.dfsTestAlert = 0; + + if(radar_type == 1) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], 0xcf8=0x%x, 0xcf4=0x%x !\n", + radar_detect_val, radar_cnt)); + } + + // Set DFS state to send notify beacon. + pMgntDFS->apMode.dfsState = DFS_AP_BECONING; + + dfs_ApDisableTx(Adapter, DFS_DISABLE_TX_DATA); + + ReleaseDataFrameQueued(Adapter); + + // Insert current channel to the reject list. + dfs_ApInsertRejectChnl(Adapter, pMgntInfo->dot11CurrentChannelNumber); + //select a non-DFS channel + pMgntDFS->apMode.dfsSwitchChannel = dfs_ApSelectChannel(Adapter); + + pMgntDFS->apMode.dfsSwitchChCountDown = 5; + + if (pMgntInfo->dot11DtimPeriod >= pMgntDFS->apMode.dfsSwitchChCountDown) + pMgntDFS->apMode.dfsSwitchChCountDown = pMgntInfo->dot11DtimPeriod+1; + + } + else + { // monitor to make sure the channel is available + u8Byte currTime, diffTime; + if(!pMgntDFS->apMode.bMonitored) + { + currTime = PlatformGetCurrentTime(); + if(pMgntDFS->apMode.monitorStartTime == 0) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS monitor started!!\n")); + dfs_ApDisableTx(Adapter, DFS_DISABLE_TX_ALL); + pMgntDFS->apMode.monitorStartTime = currTime; + } + else + { + diffTime = currTime-pMgntDFS->apMode.monitorStartTime; + if(PlatformDivision64(diffTime,1000000) >= DFS_AP_CHNL_MONITOR_TIME) + { + pMgntDFS->apMode.bMonitored = TRUE; + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS monitor finished, enable Tx!!\n")); + dfs_ApEnableTx(Adapter); + } + } + } + else + { + if(pMgntDFS->apMode.bDisableTx) + { + dfs_ApEnableTx(Adapter); + } + } + } +} + +VOID +dfs_ApInitialize( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u1Byte i; + + //============================ + // debug vars + //============================ + pMgntDFS->apMode.testcnt = 0; + pMgntDFS->apMode.dfsTestAlert = 0; + //============================ + + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + pMgntDFS->apMode.dfsRadarChnl[i].radarChnl = 0; + pMgntDFS->apMode.dfsRadarChnl[i].rejectTime = 0; + } + + pMgntDFS->apMode.bRadarDetected = FALSE; + pMgntDFS->apMode.bDisableTx = FALSE; + pMgntDFS->apMode.dfsSwitchChannel = 0; + pMgntDFS->apMode.dfsSwitchChCountDown = 5; + + pMgntDFS->apMode.bMonitored = FALSE; + pMgntDFS->apMode.monitorStartTime = 0; +} + +VOID +dfs_APDFSTimerWorkItemCallback( + IN PVOID Context + ) +{ + PADAPTER Adapter = (PADAPTER)Context; + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + switch(pMgntDFS->apMode.dfsState) + { + case DFS_AP_UNINITIALIZED: + RT_TRACE(COMP_DFS, DBG_LOUD, ("[DFS], Uninitialized state, initialize AP Mode!!\n")); + dfs_ApInitialize(Adapter); + pMgntDFS->apMode.dfsState = DFS_AP_INITIALIZED; + break; + + case DFS_AP_INITIALIZED: + RT_TRACE(COMP_DFS, DBG_LOUD, ("[DFS], AP start radar monitor!!\n")); + pMgntDFS->apMode.dfsState = DFS_AP_DETECTING; + break; + + case DFS_AP_DETECTING: + dfs_ApDetecting(Adapter); + break; + + case DFS_AP_BECONING: + // do nothing now. + break; + + case DFS_AP_SWITCH_CHNL: + RT_TRACE(COMP_DFS, DBG_LOUD, ("[DFS], AP switch channel!!\n")); + dfs_ApSwitchChnl(Adapter); + break; + + default: + RT_ASSERT(FALSE, ("AP Unknown state\n")); + break; + } +} + +VOID +dfs_ApDfsTimerCallback( + PRT_TIMER pTimer +) +{ + PADAPTER Adapter=(PADAPTER)pTimer->Adapter; + PMGNT_INFO pMgntInfo = &Adapter->MgntInfo; + + if(!ACTING_AS_AP(Adapter)) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], Warning!! dfs_ApDfsTimerCallback(): STA mode\n")); + return; + } + else + { + PlatformScheduleWorkItem(&(pMgntInfo->DFSMgnt.apMode.dfsTimerWorkItem)); + PlatformSetTimer( Adapter, &pMgntInfo->DFSMgnt.apMode.dfsTimer, 100); + } +} + + +//============================================ +// The following is for DFS Extern function, +// start with DFS_*() +//============================================ + +VOID +DFS_Init( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + BOOLEAN bSupportDFS = FALSE; + + Adapter->HalFunc.GetHalDefVarHandler(Adapter, HAL_DEF_SUPPORT_5G, (PBOOLEAN)&bSupportDFS); + if (bSupportDFS) + { + Adapter->DFSSupport = TRUE; +#if(DFS_SUPPORT_AP_MODE == 1) + pMgntDFS->apMode.bDisableDfs = FALSE; +#else + pMgntDFS->apMode.bDisableDfs = TRUE; +#endif + +#if(DFS_SUPPORT_STA_MODE == 1) + pMgntDFS->staMode.bDisableDfs = FALSE; +#else + pMgntDFS->staMode.bDisableDfs = TRUE; +#endif + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], Set support flag=TRUE!!\n")); + } + else + { + Adapter->DFSSupport = FALSE; + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], Set support flag=FALSE!!\n")); + } +} + + +VOID +DFS_TimerContrl( + IN PADAPTER Adapter, + IN UINT8 TimerCtrlType +) +{ + PMGNT_INFO pMgntInfo = &Adapter->MgntInfo; + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if(Adapter->DFSSupport == FALSE) + return; + + if(pMgntDFS->apMode.bDisableDfs) + return; + + // Comment out for compiler type cast warnning on Vista x64 + //RT_TRACE(COMP_DFS, DBG_LOUD, ("[DFS], DFS_TimerContrl(), Adapter=0x%x, type=", (u4Byte)Adapter)); + + switch(TimerCtrlType) + { + case DFS_TIMER_INIT: + RT_TRACE( COMP_DFS, DBG_LOUD, ("Timer initialization for AP mode!!\n")); + PlatformInitializeTimer(Adapter, &(pMgntInfo->DFSMgnt.apMode.dfsTimer), (RT_TIMER_CALL_BACK)dfs_ApDfsTimerCallback, NULL, "DFSTimer"); + break; + + case DFS_TIMER_SET: + RT_TRACE( COMP_DFS, DBG_LOUD, ("Set Timer for AP mode!!\n")); + PlatformSetTimer( Adapter, &pMgntInfo->DFSMgnt.apMode.dfsTimer, 100); + break; + + case DFS_TIMER_CANCEL: + RT_TRACE( COMP_DFS, DBG_LOUD, ("Cancel Timer for AP mode!!\n")); + PlatformCancelTimer(Adapter, &pMgntInfo->DFSMgnt.apMode.dfsTimer); + break; + + case DFS_TIMER_RELEASE: + RT_TRACE( COMP_DFS, DBG_LOUD, ("Release Timer for AP mode!!\n")); + PlatformReleaseTimer(Adapter, &pMgntInfo->DFSMgnt.apMode.dfsTimer); + break; + + default: + RT_ASSERT(FALSE, ("Unknown Action!!\n")); + break; + } +} + +// +// 2010/12/25 MH Gather DFS relative workitem control in the function. +// +VOID +DFS_WorkItemContrl( + IN PADAPTER Adapter, + IN UINT8 WorkItemCtrlType +) +{ + PMGNT_INFO pMgntInfo = &Adapter->MgntInfo; + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if(Adapter->DFSSupport == FALSE) + return; + + // Comment out for compiler type cast warnning on Vista x64 + //RT_TRACE(COMP_DFS, DBG_LOUD, ("[DFS], DFS_WorkItemContrl(), Adapter=0x%x, type=", (u4Byte)Adapter)); + + switch(WorkItemCtrlType) + { + case DFS_WORKITEM_INIT: + if(!pMgntDFS->apMode.bDisableDfs) + { + RT_TRACE(COMP_DFS, DBG_LOUD, ("Workitem initialization for AP mode!!\n")); + PlatformInitializeWorkItem( + Adapter, + &(pMgntInfo->DFSMgnt.apMode.dfsTimerWorkItem), + (RT_WORKITEM_CALL_BACK)dfs_APDFSTimerWorkItemCallback, + (PVOID)Adapter, + "AP_DFSTimerWorkItem"); + } + if(!pMgntDFS->staMode.bDisableDfs) + { + RT_TRACE(COMP_DFS, DBG_LOUD, ("Workitem initialization for STA mode!!\n")); + PlatformInitializeWorkItem( + Adapter, + &(pMgntInfo->DFSMgnt.staMode.csaWorkItem), + (RT_WORKITEM_CALL_BACK)dfs_StaCsaWorkItemCallback, + (PVOID)Adapter, + "DFS_CSAWorkItem"); + } + break; + + case DFS_WORKITEM_FREE: + if(!pMgntDFS->apMode.bDisableDfs) + { + RT_TRACE(COMP_DFS, DBG_LOUD, ("Free Workitem for AP mode!!\n")); + PlatformFreeWorkItem(&(pMgntInfo->DFSMgnt.apMode.dfsTimerWorkItem)); + } + if(!pMgntDFS->staMode.bDisableDfs) + { + RT_TRACE(COMP_DFS, DBG_LOUD, ("Free Workitem for STA mode!!\n")); + PlatformFreeWorkItem(&(pMgntInfo->DFSMgnt.staMode.csaWorkItem)); + } + break; + + default: + break; + } +} + +BOOLEAN +DFS_IsTxDisabled( + IN PADAPTER Adapter +) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if (Adapter->DFSSupport == FALSE) + return FALSE; + + if(ACTING_AS_AP(Adapter)) + { + if (!pMgntDFS->apMode.bDisableDfs && + pMgntDFS->apMode.bDisableTx) + { + //RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], N6usbSendNetBufferLists(): AP mode, DFS tx disabled!!!\n")); + return TRUE; + } + } + else + { + if (!pMgntDFS->staMode.bDisableDfs && + pMgntDFS->staMode.bDisableTx) + { + //RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], N6usbSendNetBufferLists(): STA mode, DFS tx disabled!!!\n")); + return TRUE; + } + } + return FALSE; +} + +BOOLEAN +DFS_ApChnlLocked( + IN PADAPTER Adapter, + u1Byte chnl + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u8Byte currTime, diffTime; + u1Byte i; + + if (Adapter->DFSSupport == FALSE) + return FALSE; + + if (pMgntDFS->apMode.bDisableDfs) + return FALSE; + + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + if((pMgntDFS->apMode.dfsRadarChnl[i].radarChnl == chnl)) + { + currTime = PlatformGetCurrentTime(); + diffTime = currTime - pMgntDFS->apMode.dfsRadarChnl[i].rejectTime; + if(PlatformDivision64(diffTime,1000000) > DFS_AP_NON_OCCUPANCY_PERIOD) + { + pMgntDFS->apMode.dfsRadarChnl[i].radarChnl = 0; + pMgntDFS->apMode.dfsRadarChnl[i].rejectTime = 0; + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_ApChnlLocked(), unlock chnl-%d!!\n", chnl)); + return FALSE; + } + else + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_ApChnlLocked(), chnl-%d is locked, choose another!!\n", chnl)); + return TRUE; + } + } + } + return FALSE; +} + + +VOID +DFS_ApIfNeedMonitorChnl( + IN PADAPTER Adapter + ) +{ + PMGNT_INFO pMgntInfo = &Adapter->MgntInfo; + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if (Adapter->DFSSupport == FALSE) + return; + + if (pMgntDFS->apMode.bDisableDfs) + return; + + if(!ACTING_AS_AP(Adapter)) + return; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_ApIfNeedMonitorChnl()!!\n")); + + dfs_ApResetRadarDetectCounterAndFlag(Adapter); + + if(DFS_5G_RADAR_CHANNEL(pMgntInfo->dot11CurrentChannelNumber)) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], chnl %d is a Radar channel, have to monitor first!!\n", + pMgntInfo->dot11CurrentChannelNumber)); + + dfs_ApResetMonitorState(Adapter, TRUE); + dfs_ApDisableTx(Adapter, DFS_DISABLE_TX_ALL); + } + else + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], chnl %d is Not a Radar channel!!\n", + pMgntInfo->dot11CurrentChannelNumber)); + + dfs_ApResetMonitorState(Adapter, FALSE); + dfs_ApEnableTx(Adapter); + } +} + +VOID +DFS_ApConstructBeaconIEcsa( + IN PADAPTER Adapter +) +{ + PMGNT_INFO pMgntInfo = &Adapter->MgntInfo; + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + OCTET_STRING ChlSwitchAnnounce; + u1Byte ChlSwitchAnnounceBuf[3]; + pu1Byte pbcn; + + if (Adapter->DFSSupport == FALSE) + return; + + if(pMgntDFS->apMode.bDisableDfs) + return; + + if(ACTING_AS_AP(Adapter)) + { + pbcn = pMgntInfo->beaconframe.Octet; + //RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], AP construct beacon!!\n")); + UNION_BEACON_PROBE_RSP_CAPABILITY_INFO(pbcn, cSpectrumMgnt); + + if (pMgntDFS->apMode.bRadarDetected && pMgntDFS->apMode.dfsSwitchChannel) + { + if (pMgntDFS->apMode.dfsSwitchChCountDown) + { + ChlSwitchAnnounceBuf[0] = 1; // channel switch mode + ChlSwitchAnnounceBuf[1] = pMgntDFS->apMode.dfsSwitchChannel; // new channel number + ChlSwitchAnnounceBuf[2] = pMgntDFS->apMode.dfsSwitchChCountDown; // channel switch count + + FillOctetString(ChlSwitchAnnounce, ChlSwitchAnnounceBuf, 3); + PacketMakeElement(&pMgntInfo->beaconframe, EID_ChlSwitchAnnounce, ChlSwitchAnnounce); + + pMgntDFS->apMode.dfsSwitchChCountDown--; + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS counting = %d\n", + pMgntDFS->apMode.dfsSwitchChCountDown)); + + if( pMgntDFS->apMode.dfsSwitchChCountDown == 0 && + pMgntDFS->apMode.dfsState == DFS_AP_BECONING ) + { + pMgntDFS->apMode.dfsState = DFS_AP_SWITCH_CHNL; + } + } + } + } +} + +VOID +DFS_StaInsertToRadarChnlList( + IN PADAPTER Adapter, + u1Byte Radarchnl + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u1Byte i; + + if(Adapter->DFSSupport == FALSE) + return; + + if(pMgntDFS->staMode.bDisableDfs) + return; + + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + if((pMgntDFS->staMode.dfsRadarChnl[i].radarChnl == 0)) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaInsertToRadarChnlList(), insert chnl %d to Radar channel list\n", + Radarchnl)); + pMgntDFS->staMode.dfsRadarChnl[i].radarChnl = Radarchnl; + pMgntDFS->staMode.dfsRadarChnl[i].rxBcnTime = 0; // in micro-second. + break; + } + } +} + +VOID +DFS_StaMgntResetVars( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u1Byte i; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaMgntResetVars()\n")); + + if(Adapter->DFSSupport == FALSE) + return; + + if(pMgntDFS->staMode.bDisableDfs) + return; + + pMgntDFS->staMode.dfsState = DFS_STA_LISTEN; + + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + pMgntDFS->staMode.dfsRadarChnl[i].radarChnl = 0; + pMgntDFS->staMode.dfsRadarChnl[i].rxBcnTime = 0; + } + + pMgntDFS->staMode.bDisableTx = FALSE; + pMgntDFS->staMode.dfsSwitchChannel = 0; + pMgntDFS->staMode.dfsSwitchChCountDown = 0; + pMgntDFS->staMode.bMonitorAfterSwitch = FALSE; + pMgntDFS->staMode.dfsMonitorStartTime = 0; +} + +VOID +DFS_StaCheckCsaInfo( + IN PADAPTER Adapter, + IN PRT_WLAN_BSS pBssDesc +) +{ + PMGNT_INFO pMgntInfo=&Adapter->MgntInfo; + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + + if (Adapter->DFSSupport == FALSE) + return; + + if(pMgntDFS->staMode.bDisableDfs) + return; + + if(pBssDesc->CSA.bWithCSA) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], OnBeacon_Bss(), CSA info, Mode/ Newchnl/ Cnt = %d/ %d/ %d !!!\n", + pBssDesc->CSA.channelSwtichMode, pBssDesc->CSA.NewChnlNum, pBssDesc->CSA.channelSwitchCnt)); + + if(pMgntDFS->staMode.dfsState == DFS_STA_LISTEN) + { + pMgntDFS->staMode.dfsSwitchChannel = pBssDesc->CSA.NewChnlNum; + pMgntDFS->staMode.dfsSwitchChCountDown = pBssDesc->CSA.channelSwitchCnt; + PlatformScheduleWorkItem(&(pMgntInfo->DFSMgnt.staMode.csaWorkItem)); + } + } +} + + +VOID +DFS_StaConstructAssociateReq( + IN PADAPTER Adapter, + IN u2Byte asocCap, + IN OCTET_STRING AsocReq +) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + OCTET_STRING PowerCap; + u1Byte PowerCapConnent[2]; + PRT_CHANNEL_LIST pChannelList; + OCTET_STRING SupportChannelIE; + u1Byte SupportChannelConnent[48]; + u1Byte i=0,j=0; + + if (Adapter->DFSSupport == FALSE) + return; + + if(pMgntDFS->staMode.bDisableDfs) + return; + + //for 11H, add Power Capability. + //For 11H,add Supported Channels element + if(asocCap & BIT8) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaConstructAssociateReq()\n")); + + PowerCapConnent[0]= 0; + PowerCapConnent[1] = 12; + PowerCap.Octet = PowerCapConnent; + PowerCap.Length = 2; + PacketMakeElement( &AsocReq, EID_PowerCap, PowerCap ); + + pChannelList = MgntActQuery_ChannelList(Adapter); + RT_TRACE(COMP_SCAN, DBG_LOUD, ("@@@Channel Plan: ")); + for(i = 0; i < pChannelList->ChannelLen; i ++) + RT_TRACE(COMP_SCAN, DBG_LOUD, (" %d ", pChannelList->ChnlListEntry[i].ChannelNum)); + RT_TRACE(COMP_SCAN, DBG_LOUD, ("\n")); + for(i=0;i < pChannelList->ChannelLen*2;i++) + { + if(i%2 == 0) + SupportChannelConnent[i] = pChannelList->ChnlListEntry[i/2].ChannelNum; + else + SupportChannelConnent[i] = 1; + } + + //FillOctetString(SupportChannelIE, SuppRatesContent, i*2); + SupportChannelIE.Octet = SupportChannelConnent; + SupportChannelIE.Length = i; + RT_TRACE(COMP_SCAN, DBG_LOUD, ("@@@SUpport channel IE: ")); + for(j = 0; j < SupportChannelIE.Length; j++) + RT_TRACE(COMP_SCAN, DBG_LOUD,(" %d",SupportChannelIE.Octet[j])); + RT_TRACE(COMP_SCAN, DBG_LOUD, ("\n")); + PacketMakeElement( &AsocReq, EID_SupportedChannels, SupportChannelIE ); + } + +} + + +VOID +DFS_StaGetValueFromBeacon( + IN PADAPTER Adapter, + IN OCTET_STRING mmpdu, + OUT RT_WLAN_BSS *bssDesc + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + OCTET_STRING ChlSwitchAnnounceInfo; + + if (Adapter->DFSSupport == FALSE) + return; + + if (pMgntDFS->staMode.bDisableDfs) + return; + + ChlSwitchAnnounceInfo = PacketGetElement(mmpdu, EID_ChlSwitchAnnounce, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE ); + if( ChlSwitchAnnounceInfo.Length != 0) + { + bssDesc->CSA.bWithCSA= TRUE; + bssDesc->CSA.channelSwitchCnt = EF1Byte(*(ChlSwitchAnnounceInfo.Octet+2)); + bssDesc->CSA.NewChnlNum= EF1Byte(*(ChlSwitchAnnounceInfo.Octet+1)); + bssDesc->CSA.channelSwtichMode = EF1Byte(*(ChlSwitchAnnounceInfo.Octet)); + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], GetValueFromBeaconOrProbeRsp(), CSA info, Mode/ Newchnl/ Cnt = %d/ %d/ %d !!!\n", + bssDesc->CSA.channelSwtichMode, bssDesc->CSA.NewChnlNum, bssDesc->CSA.channelSwitchCnt)); + } + else + { + bssDesc->CSA.bWithCSA= FALSE; + bssDesc->CSA.channelSwitchCnt = 0; + bssDesc->CSA.NewChnlNum= 0; + bssDesc->CSA.channelSwtichMode = 0; + } +} + +VOID +DFS_StaMonitor( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u8Byte currTime, diffTime; + + if (Adapter->DFSSupport == FALSE) + return; + + if (pMgntDFS->staMode.bDisableDfs) + return; + + if(ACTING_AS_AP(Adapter)) + return; + + if(pMgntDFS->staMode.bMonitorAfterSwitch) + { + currTime = PlatformGetCurrentTime(); + diffTime = currTime - pMgntDFS->staMode.dfsMonitorStartTime; + + if(PlatformDivision64(diffTime,1000000) <= 3) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaMonitor(), monitor started!!\n")); + } + + if(PlatformDivision64(diffTime,1000000) < DFS_STA_CHNL_MONITOR_TIME) + { + if( Adapter->MgntInfo.LinkDetectInfo.NumRecvBcnInPeriod==0 || + Adapter->MgntInfo.LinkDetectInfo.NumRecvDataInPeriod==0 ) + { + Adapter->MgntInfo.LinkDetectInfo.NumRecvBcnInPeriod = 1; + Adapter->MgntInfo.LinkDetectInfo.NumRecvDataInPeriod= 1; + } + } + else + { + pMgntDFS->staMode.bMonitorAfterSwitch = FALSE; + pMgntDFS->staMode.bMonitorAfterSwitchIsDone = TRUE; + dfs_StaEnableTx(Adapter); + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaMonitor(), monitor is finished, over %d seconds!!\n", + DFS_STA_CHNL_MONITOR_TIME)); + } + } +} + + + +VOID +DFS_StaCheckRadarChnl( + IN PADAPTER Adapter, + IN PRT_WLAN_BSS pbssdesc +) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + u1Byte i, chnl=0; + + if (Adapter->DFSSupport == FALSE) + return; + + if (pMgntDFS->staMode.bDisableDfs) + return; + +#if (DFS_CLIENT_PASSIVE_SCAN_ONLY == 1) + return; +#endif + + chnl = pbssdesc->ChannelNumber; + + if(!DFS_5G_RADAR_CHANNEL(chnl)) + return; + + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaCheckRadarChnl(), rx beacon, channel = %d!!\n", + pbssdesc->ChannelNumber)); + + if(pbssdesc->CSA.bWithCSA) + { + // Beacon with Channel Switch Annouence, set rx beacon time = 0. + // We take it as the Radar signal is detected in the channel. + // Update the rx beacon time. + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + if(pMgntDFS->staMode.dfsRadarChnl[i].radarChnl == chnl) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaCheckRadarChnl(), CSA beacon, set rx beacon time = 0 at channel = %d!!\n", + chnl)); + pMgntDFS->staMode.dfsRadarChnl[i].rxBcnTime = 0; + } + } + } + else + { + // Update the rx beacon time. + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + if(pMgntDFS->staMode.dfsRadarChnl[i].radarChnl == chnl) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaCheckRadarChnl(), update rx beacon time at channel = %d!!\n", + chnl)); + pMgntDFS->staMode.dfsRadarChnl[i].rxBcnTime = PlatformGetCurrentTime(); + } + } + } + +} + + +VOID +DFS_StaUpdateRadarChnlScanType( + IN PADAPTER Adapter + ) +{ + PDFS_MGNT pMgntDFS = &Adapter->MgntInfo.DFSMgnt; + PRT_CHANNEL_LIST pChanneList = NULL; + u8Byte currTime, diffTime; + u2Byte i, j; + u1Byte radarChnl, ch_idx=0xff; + + if (Adapter->DFSSupport == FALSE) + return; + + if (pMgntDFS->staMode.bDisableDfs) + return; + +#if (DFS_CLIENT_PASSIVE_SCAN_ONLY == 1) + return; +#endif + + RtActChannelList(Adapter, RT_CHNL_LIST_ACTION_GET_CHANNEL_LIST, NULL, &pChanneList); + + currTime = PlatformGetCurrentTime(); + for(i=0; i<DFS_MAX_RADAR_CHNL_NUM; i++) + { + if(pMgntDFS->staMode.dfsRadarChnl[i].rxBcnTime) + { + radarChnl = pMgntDFS->staMode.dfsRadarChnl[i].radarChnl; + diffTime = currTime - pMgntDFS->staMode.dfsRadarChnl[i].rxBcnTime; + + for(j=0; j<pChanneList->ChannelLen; j++) + { + if(pChanneList->ChnlListEntry[j].ChannelNum == radarChnl) + { + ch_idx = (u1Byte)j; + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaUpdateRadarChnlScanType(), find channel-%d in channel plan!!", + radarChnl)); + break; + } + } + if(ch_idx == 0xff) + { + RT_TRACE( COMP_DFS, DBG_LOUD, ("[DFS], DFS_StaUpdateRadarChnlScanType(), channel-%d NOT found in channel plan!!\n", + radarChnl)); + return; + } + + if(PlatformDivision64(diffTime,1000000) < DFS_STA_CHNL_SCAN_TYPE_MONITOR_TIME) + { + RT_TRACE( COMP_DFS, DBG_LOUD, (" and set to Active scan!!\n")); + pChanneList->ChnlListEntry[ch_idx].ScanType = SCAN_ACTIVE; + } + else + { + RT_TRACE( COMP_DFS, DBG_LOUD, (" and set to Passive scan!!\n")); + pChanneList->ChnlListEntry[ch_idx].ScanType = SCAN_PASSIVE; + } + } + } + +} + +#endif + +/* End of DFS.c */ + |
