/* ************************************************************************* * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, * Hsinchu County 302, * Taiwan, R.O.C. * * (c) Copyright 2002-2007, Ralink Technology, Inc. * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* Module Name: ap_dfs.c Abstract: Support DFS function. Revision History: Who When What -------- ---------- ---------------------------------------------- Fonchi 03-12-2007 created */ #include "../rt_config.h" typedef struct _RADAR_DURATION_TABLE { ULONG RDDurRegion; ULONG RadarSignalDuration; ULONG Tolerance; } RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE; static UCHAR RdIdleTimeTable[MAX_RD_REGION][4] = { {9, 250, 250, 250}, // CE {4, 250, 250, 250}, // FCC {4, 250, 250, 250}, // JAP {15, 250, 250, 250}, // JAP_W53 {4, 250, 250, 250} // JAP_W56 }; /* ======================================================================== Routine Description: Bbp Radar detection routine Arguments: pAd Pointer to our adapter Return Value: ======================================================================== */ VOID BbpRadarDetectionStart( IN PRTMP_ADAPTER pAd) { UINT8 RadarPeriod; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff); #if 0 // toggle Rx enable bit for radar detection. // it's Andy's recommand. { UINT32 Value; RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); Value |= (0x1 << 3); RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); Value &= ~(0x1 << 3); RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); } #endif RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ? (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250; RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); RTMP_IO_WRITE8(pAd, 0x7021, 0x40); RadarDetectionStart(pAd, 0, RadarPeriod); return; } /* ======================================================================== Routine Description: Bbp Radar detection routine Arguments: pAd Pointer to our adapter Return Value: ======================================================================== */ VOID BbpRadarDetectionStop( IN PRTMP_ADAPTER pAd) { RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); RTMP_IO_WRITE8(pAd, 0x7021, 0x60); RadarDetectionStop(pAd); return; } /* ======================================================================== Routine Description: Radar detection routine Arguments: pAd Pointer to our adapter Return Value: ======================================================================== */ VOID RadarDetectionStart( IN PRTMP_ADAPTER pAd, IN BOOLEAN CTSProtect, IN UINT8 CTSPeriod) { UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f); UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect. if (CTSProtect != 0) { switch(pAd->CommonCfg.RadarDetect.RDDurRegion) { case FCC: case JAP_W56: CtsProtect = 0x03; break; case CE: case JAP_W53: default: CtsProtect = 0x02; break; } } else CtsProtect = 0x01; // send start-RD with CTS protection command to MCU // highbyte [7] reserve // highbyte [6:5] 0x: stop Carrier/Radar detection // highbyte [10]: Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection // highbyte [4:0] Radar/carrier detection duration. In 1ms. // lowbyte [7:0] Radar/carrier detection period, in 1ms. AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5)); //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0); return; } /* ======================================================================== Routine Description: Radar detection routine Arguments: pAd Pointer to our adapter Return Value: TRUE Found radar signal FALSE Not found radar signal ======================================================================== */ VOID RadarDetectionStop( IN PRTMP_ADAPTER pAd) { DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n")); AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send start-RD with CTS protection command to MCU return; } /* ======================================================================== Routine Description: Radar channel check routine Arguments: pAd Pointer to our adapter Return Value: TRUE need to do radar detect FALSE need not to do radar detect ======================================================================== */ BOOLEAN RadarChannelCheck( IN PRTMP_ADAPTER pAd, IN UCHAR Ch) { #if 1 INT i; BOOLEAN result = FALSE; for (i=0; iChannelListNum; i++) { if (Ch == pAd->ChannelList[i].Channel) { result = pAd->ChannelList[i].DfsReq; break; } } return result; #else INT i; UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; for (i=0; i<15; i++) { if (Ch == Channel[i]) { break; } } if (i != 15) return TRUE; else return FALSE; #endif } ULONG JapRadarType( IN PRTMP_ADAPTER pAd) { ULONG i; const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP) { return pAd->CommonCfg.RadarDetect.RDDurRegion; } for (i=0; i<15; i++) { if (pAd->CommonCfg.Channel == Channel[i]) { break; } } if (i < 4) return JAP_W53; else if (i < 15) return JAP_W56; else return JAP; // W52 } ULONG RTMPBbpReadRadarDuration( IN PRTMP_ADAPTER pAd) { UINT8 byteValue = 0; ULONG result; BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue); result = 0; switch (byteValue) { case 1: // radar signal detected by pulse mode. case 2: // radar signal detected by width mode. result = RTMPReadRadarDuration(pAd); break; case 0: // No radar signal. default: result = 0; break; } return result; } ULONG RTMPReadRadarDuration( IN PRTMP_ADAPTER pAd) { ULONG result = 0; #ifdef DFS_SUPPORT UINT8 duration1 = 0, duration2 = 0, duration3 = 0; BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1); BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2); BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3); result = (duration1 << 16) + (duration2 << 8) + duration3; #endif // DFS_SUPPORT // return result; } VOID RTMPCleanRadarDuration( IN PRTMP_ADAPTER pAd) { return; } /* ======================================================================== Routine Description: Radar wave detection. The API should be invoke each second. Arguments: pAd - Adapter pointer Return Value: None ======================================================================== */ VOID ApRadarDetectPeriodic( IN PRTMP_ADAPTER pAd) { INT i; pAd->CommonCfg.RadarDetect.InServiceMonitorCount++; for (i=0; iChannelListNum; i++) { if (pAd->ChannelList[i].RemainingTimeForUse > 0) { pAd->ChannelList[i].RemainingTimeForUse --; if ((pAd->Mlme.PeriodicRound%5) == 0) { DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); } } } //radar detect if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) { RadarDetectPeriodic(pAd); } return; } // Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt() // Before switch channel, driver needs doing channel switch announcement. VOID RadarDetectPeriodic( IN PRTMP_ADAPTER pAd) { // need to check channel availability, after switch channel if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE) return; // channel availability check time is 60sec, use 65 for assurance if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime) { DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n")); BbpRadarDetectionStop(pAd); AsicEnableBssSync(pAd); pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; return; } return; } /* ========================================================================== Description: change channel moving time for DFS testing. Arguments: pAdapter Pointer to our adapter wrq Pointer to the ioctl argument Return Value: None Note: Usage: 1.) iwpriv ra0 set ChMovTime=[value] ========================================================================== */ INT Set_ChMovingTime_Proc( IN PRTMP_ADAPTER pAd, IN PUCHAR arg) { UINT8 Value; Value = simple_strtol(arg, 0, 10); pAd->CommonCfg.RadarDetect.ChMovingTime = Value; DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__, pAd->CommonCfg.RadarDetect.ChMovingTime)); return TRUE; } INT Set_LongPulseRadarTh_Proc( IN PRTMP_ADAPTER pAd, IN PUCHAR arg) { UINT8 Value; Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10); pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value; DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__, pAd->CommonCfg.RadarDetect.LongPulseRadarTh)); return TRUE; }