3340 lines
96 KiB
C
3340 lines
96 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:
|
|
ap_dfs.c
|
|
|
|
Abstract:
|
|
Support DFS function.
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- ---------- ----------------------------------------------
|
|
*/
|
|
|
|
#include "rt_config.h"
|
|
|
|
#ifdef DFS_SUPPORT
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
|
|
NewDFSValidRadar NewDFSValidTable[] =
|
|
{
|
|
/* FCC-1 && (Japan W53 Radar 1 / W56 Radar 2)*/
|
|
{
|
|
(NEW_DFS_FCC | NEW_DFS_JAP | NEW_DFS_JAP_W53),
|
|
7,
|
|
10, 1000,
|
|
0,
|
|
4,
|
|
0, 0,
|
|
28570 - 70,
|
|
150
|
|
},
|
|
/* FCC-2*/
|
|
{
|
|
(NEW_DFS_FCC | NEW_DFS_JAP),
|
|
7,
|
|
13, 1000,
|
|
0,
|
|
1,
|
|
3000, 4600 - 20,
|
|
0,
|
|
25
|
|
},
|
|
/* FCC-3 & FCC-4*/
|
|
{
|
|
(NEW_DFS_FCC | NEW_DFS_JAP),
|
|
7,
|
|
/*120, 200, FCC-3 */
|
|
/*220, 400, FCC-4*/
|
|
100, 1500,
|
|
0,
|
|
1,
|
|
4000, 10000 - 40,
|
|
0,
|
|
60
|
|
},
|
|
/* FCC-6*/
|
|
{
|
|
(NEW_DFS_FCC | NEW_DFS_JAP),
|
|
7,
|
|
12, 1000,
|
|
0,
|
|
1,
|
|
0, 0,
|
|
6660-10,
|
|
35
|
|
},
|
|
/* Japan W53 Radar 2*/
|
|
{
|
|
NEW_DFS_JAP_W53,
|
|
7,
|
|
40, 1000,
|
|
0,
|
|
1,
|
|
0, 0,
|
|
76923 - 30,
|
|
180
|
|
},
|
|
/* Japan W56 Radar 1*/
|
|
{
|
|
NEW_DFS_JAP,
|
|
7,
|
|
5, 500,
|
|
0,
|
|
2,
|
|
0, 0,
|
|
27777 - 30,
|
|
70
|
|
},
|
|
/* Japan W56 Radar 3*/
|
|
{
|
|
NEW_DFS_JAP,
|
|
7,
|
|
30, 1000,
|
|
0,
|
|
1,
|
|
0, 0,
|
|
80000 - 50,
|
|
200
|
|
},
|
|
|
|
/* CE Staggered radar*/
|
|
|
|
{
|
|
/* EN-1*/
|
|
/* width 0.8 - 5 us*/
|
|
/* PRF 200 - 1000 Hz*/
|
|
/* PRI 5000 - 1000 us (T: 20000 - 100000)*/
|
|
/* */
|
|
NEW_DFS_EU,
|
|
0xf,
|
|
10, 1000,
|
|
0,
|
|
1,
|
|
20000-15, 100000-70,
|
|
0,
|
|
120
|
|
},
|
|
/* EN-2*/
|
|
/* width 0.8 - 15 us*/
|
|
/* PRF 200 - 1600 Hz*/
|
|
/* PRI 5000 - 625 us (T: 12500 - 100000)*/
|
|
{
|
|
NEW_DFS_EU,
|
|
0xf,
|
|
10, 2000,
|
|
0,
|
|
1,
|
|
12500 - 10, 100000 - 70,
|
|
0,
|
|
120
|
|
},
|
|
|
|
/* EN-3*/
|
|
/* width 0.8 - 15 us*/
|
|
/* PRF 2300 - 4000 Hz*/
|
|
/* PRI 434 - 250 us (T: 5000 - 8695)*/
|
|
{
|
|
NEW_DFS_EU,
|
|
0xf,
|
|
21, 2000,
|
|
0,
|
|
1,
|
|
5000 - 4, 8695 - 7,
|
|
0,
|
|
50
|
|
},
|
|
/* EN-4*/
|
|
/* width 20 - 30 us*/
|
|
/* PRF 2000 - 4000 Hz*/
|
|
/* PRI 500 - 250 us (T: 5000 - 10000)*/
|
|
/* Note : with Chirp Modulation +- 2,5Mhz*/
|
|
{
|
|
NEW_DFS_EU,
|
|
0xf,
|
|
380, 3000,
|
|
0,
|
|
4,
|
|
5000 - 4, 10000 - 8,
|
|
0,
|
|
60
|
|
},
|
|
/* EN-5*/
|
|
/* width 0.8 - 2 us*/
|
|
/* PRF 300 - 400 Hz*/
|
|
/* PRI 3333 - 2500 us (T: 50000 - 66666)*/
|
|
/* Staggered PRF, 20 - 50 pps*/
|
|
{
|
|
NEW_DFS_EU,
|
|
0xf,
|
|
10, 800,
|
|
0,
|
|
1,
|
|
50000 - 35, 66666 + 50,
|
|
0,
|
|
30
|
|
},
|
|
/* EN-6*/
|
|
/* width 0.8 - 2 us*/
|
|
/* PRF 400 - 1200 Hz*/
|
|
/* PRI 2500 - 833 us (T: 16666 - 50000)*/
|
|
/* Staggered PRF, 80 - 400 pps*/
|
|
{
|
|
NEW_DFS_EU,
|
|
0xf,
|
|
10, 800,
|
|
0,
|
|
1,
|
|
16666 - 13, 50000 + 35,
|
|
0,
|
|
30
|
|
},
|
|
|
|
{
|
|
NEW_DFS_END,
|
|
0,
|
|
0, 0,
|
|
0,
|
|
0,
|
|
0, 0,
|
|
0,
|
|
0,
|
|
},
|
|
};
|
|
|
|
static NewDFSTable NewDFSTable1[] =
|
|
{
|
|
{
|
|
/* ch, mode(0~7), M(~511), el, eh(~4095), wl, wh(~4095), err_w, tl, th, err_t, bl, bh, ee, pj*/
|
|
NEW_DFS_FCC,
|
|
{
|
|
{0, 0, 10, 8, 16, 6, 2000, 5, 2900, 29000, 5, 0, 0, 0x1000000, 0},
|
|
{1, 0, 70, 42, 126, 20, 5000, 5, 2900, 29000, 10, 0, 0, 0x1000000, 0},
|
|
{2, 0, 100, 42, 160, 20, 5000, 25, 2900, 10100, 20, 0, 0, 0x1000000, 0},
|
|
{3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999, 0x10000000, 0},
|
|
}
|
|
},
|
|
|
|
{
|
|
NEW_DFS_EU,
|
|
{
|
|
{0, 0, 10, 10, 18, 4, 4095, 5, 7800, 101000, 5, 0, 0, 0x1000000, 0},
|
|
{1, 0, 70, 42, 90, 20, 4095, 3, 4900, 101000, 10, 0, 0, 0x1000000, 0},
|
|
{2, 0, 100, 42, 160, 20, 4095, 5, 4900, 101000, 20, 0, 0, 0x1000000, 0},
|
|
{3, 3, 200, 20, 150, 200, 4095, 100, 4900, 11000, 200, 0, 0, 0x1000000, 0},
|
|
{4, 8, 0, 8, 17, 7, 70, 2, 32500, 200500, 10, 0, 0, 0x1000000, 0},
|
|
/*{5, 1, 0, 12, 16, 8, 700, 5, 33000, 135000, 100, 0, 0, 0x1000000, 0},*/
|
|
}
|
|
},
|
|
|
|
{
|
|
NEW_DFS_JAP,
|
|
{
|
|
{0, 0, 10, 8, 16, 4, 2000, 5, 2900, 85000, 5, 0, 0, 0x1000000, 0},
|
|
{1, 0, 70, 48, 126, 20, 5000, 5, 2900, 85000, 10, 0, 0, 0x1000000, 0},
|
|
{2, 0, 100, 48, 160, 20, 5000, 25, 2900, 85000, 20, 0, 0, 0x1000000, 0},
|
|
{3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999, 0x10000000, 0},
|
|
}
|
|
},
|
|
|
|
{
|
|
NEW_DFS_JAP_W53,
|
|
{
|
|
{0, 0, 10, 8, 16, 8, 2000, 5, 28000, 85000, 10, 0x1000000, 0},
|
|
{1, 0, 32, 24, 64, 20, 2000, 5, 28000, 85000, 10, 0x1000000, 0},
|
|
{2, 0, 100, 42, 160, 20, 2000, 25, 28000, 85000, 10, 0x1000000, 0},
|
|
/*{3, 2, 200, 20, 150, 300, 2000, 50, 15000, 45000, 200},*/
|
|
}
|
|
},
|
|
};
|
|
|
|
/* for MT76x0 */
|
|
static NewDFSTable NewDFSTable2[] =
|
|
{
|
|
{
|
|
/* (0~9) (~511) (~4095) (~4095) */
|
|
/* ch, mode M EL, EH WL WH ErrW TL TH Err_T BL BH EE PJ*/
|
|
NEW_DFS_FCC,
|
|
{
|
|
{0, 0, 8, 2, 7, 106, 420, 30, 2900, 100096, 30, 0, 2147483647, 0x1400000, 0x12ee},
|
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
{2, 3, 20, 2, 18, 106, 420, 32, 2900, 100096, 32, 0, 2147483647, 0xe4e1c00, 0x12ee},
|
|
{3, 2, 60, 15, 48, 900, 2048, 32, 2900, 100096, 32, 0, 2147483647, 0x0e4e1c00, 0x12ee},
|
|
}
|
|
},
|
|
|
|
{
|
|
/* (0~9) (~511) (~4095) (~4095) */
|
|
/* ch, mode M EL, EH WL WH ErrW TL TH Err_T BL BH EE PJ*/
|
|
NEW_DFS_EU,
|
|
{
|
|
{0, 0, 8, 2, 7, 106, 420, 30, 2900, 100096, 30, 0, 2147483647, 0x1400000, 0x12ee},
|
|
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
{2, 3, 20, 2, 18, 106, 2048, 32, 2900, 100096, 32, 0, 2147483647, 0xe4e1c00, 0x12ee},
|
|
{3, 8, 8, 2, 7, 106, 200, 32, 2900, 296704, 32, 0, 2147483647, 0x1400000, 0x15ee},
|
|
}
|
|
},
|
|
};
|
|
|
|
static void dfs_sw_init(
|
|
IN PRTMP_ADAPTER pAd);
|
|
|
|
static BOOLEAN StagerRadarCheck(
|
|
IN PRTMP_ADAPTER pAd,
|
|
UINT8 dfs_channel);
|
|
|
|
static BOOLEAN ChirpRadarCheck(
|
|
IN PRTMP_ADAPTER pAd);
|
|
|
|
#ifdef MT76x0
|
|
static BOOLEAN MT7650DfsEventDataFetch(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PRADAR_DETECT_STRUCT pRadarDetect,
|
|
OUT PDFS_EVENT pDfsEvent);
|
|
#else
|
|
static BOOLEAN DfsEventDataFetch(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PRADAR_DETECT_STRUCT pRadarDetect,
|
|
OUT PDFS_EVENT pDfsEvent);
|
|
#endif /* MT76x0 */
|
|
|
|
static VOID DfsCheckBusyIdle(
|
|
IN PRTMP_ADAPTER pAd);
|
|
|
|
static BOOLEAN DfsChannelCheck(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DfsChannel);
|
|
|
|
static VOID ChannelSelectOnRadarDetection(
|
|
IN PRTMP_ADAPTER pAd);
|
|
|
|
static BOOLEAN DfsEventDrop(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PDFS_EVENT pDfsEvent);
|
|
|
|
static inline BOOLEAN NewRadarDetectionMcuStart(PRTMP_ADAPTER pAd)
|
|
{
|
|
/*
|
|
8051 firmware don't care parameter Token, Arg0 and Arg1
|
|
*/
|
|
return AsicSendCommandToMcu(pAd, DFS_ONOFF_MCU_CMD, 0xff, 0x01, 0x01, FALSE);
|
|
}
|
|
|
|
static inline BOOLEAN NewRadarDetectionMcuStop(PRTMP_ADAPTER pAd)
|
|
{
|
|
/*
|
|
8051 firmware don't care parameter Token, Arg0 and Arg1
|
|
*/
|
|
return AsicSendCommandToMcu(pAd, DFS_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
|
|
}
|
|
|
|
|
|
static inline VOID DfsHwDetectionStatusGet(PRTMP_ADAPTER pAd,
|
|
PUINT8 pDetectedChannels)
|
|
{
|
|
#if MT76x0
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R1, pDetectedChannels);
|
|
#else
|
|
RTMP_DFS_IO_READ8(pAd, 0x2, pDetectedChannels);
|
|
#endif /* MT76x0 */
|
|
}
|
|
|
|
static inline VOID DfsResetHwDetectionStatus(PRTMP_ADAPTER pAd)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
#if MT76x0
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask);
|
|
#else
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask);
|
|
#endif /* MT76x0 */
|
|
}
|
|
|
|
static inline VOID DfsCaptureModeControl(PRTMP_ADAPTER pAd,
|
|
BOOLEAN bEnable,
|
|
BOOLEAN bPowerUp,
|
|
BOOLEAN bCapLastEvents)
|
|
{
|
|
UINT8 bbp_val = 0;
|
|
|
|
bbp_val = (bEnable == TRUE) |
|
|
((bPowerUp == TRUE) <<1) |
|
|
((bCapLastEvents == TRUE) << 2);
|
|
|
|
#if MT76x0
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R36, (UINT32) bbp_val);
|
|
#else
|
|
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R126, bbp_val);
|
|
#endif /* MT76x0 */
|
|
}
|
|
|
|
static inline VOID DfsDetectionEnable(PRTMP_ADAPTER pAd)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
#if MT76x0
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R0, (pRadarDetect->EnabledChMask << 16));
|
|
#else
|
|
RTMP_DFS_IO_WRITE8(pAd, pRadarDetect->EnabledChMask, 1);
|
|
#endif /* MT76x0 */
|
|
}
|
|
|
|
static inline VOID DfsDetectionDisable(PRTMP_ADAPTER pAd)
|
|
{
|
|
#if MT76x0
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R0, 0);
|
|
#else
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x1, 0);
|
|
#endif /* MT76x0 */
|
|
}
|
|
|
|
static inline VOID StagerRadarGetPRIs(PRTMP_ADAPTER pAd,
|
|
UINT8 dfs_channel,
|
|
PUINT32 pT1,
|
|
PUINT32 pT2,
|
|
PUINT32 pT3)
|
|
{
|
|
UINT32 T_all = 0;
|
|
#if MT76x0
|
|
UINT32 bbp_val = 0;
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = \
|
|
&pAd->CommonCfg.RadarDetect.DfsProgramParam;
|
|
#else
|
|
UINT8 bbp_val = 0;
|
|
#endif /* MT76x0 */
|
|
|
|
#if MT76x0
|
|
/* select channel */
|
|
bbp_val = (pDfsProgramParam->ChEnable << 16) | dfs_channel;
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val);
|
|
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R19, &T_all);
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R22, pT1);
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R25, pT2);
|
|
#else
|
|
/* select channel */
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x0, dfs_channel);
|
|
|
|
/*0. Select dfs channel 4 and read out T1/T2/T3, 50 ns unit; 32bits */
|
|
RTMP_DFS_IO_READ8(pAd, 0x2d, &bbp_val);
|
|
T_all += bbp_val;
|
|
RTMP_DFS_IO_READ8(pAd, 0x2e, &bbp_val);
|
|
T_all += bbp_val<<8;
|
|
RTMP_DFS_IO_READ8(pAd, 0x2f, &bbp_val);
|
|
T_all += bbp_val<<16;
|
|
RTMP_DFS_IO_READ8(pAd, 0x30, &bbp_val);
|
|
T_all += bbp_val<<24;
|
|
|
|
RTMP_DFS_IO_READ8(pAd, 0x33, &bbp_val);
|
|
*pT1 += bbp_val;
|
|
RTMP_DFS_IO_READ8(pAd, 0x34, &bbp_val);
|
|
*pT1 += bbp_val<<8;
|
|
RTMP_DFS_IO_READ8(pAd, 0x35, &bbp_val);
|
|
*pT1 += bbp_val<<16;
|
|
RTMP_DFS_IO_READ8(pAd, 0x36, &bbp_val);
|
|
*pT1 += bbp_val<<24;
|
|
|
|
RTMP_DFS_IO_READ8(pAd, 0x3d, &bbp_val);
|
|
*pT2 += bbp_val;
|
|
RTMP_DFS_IO_READ8(pAd, 0x3e, &bbp_val);
|
|
*pT2 += bbp_val<<8;
|
|
RTMP_DFS_IO_READ8(pAd, 0x3f, &bbp_val);
|
|
*pT2 += bbp_val<<16;
|
|
RTMP_DFS_IO_READ8(pAd, 0x40, &bbp_val);
|
|
*pT2 += bbp_val<<24;
|
|
#endif /* MT76x0 */
|
|
|
|
*pT3 = T_all - *pT1 -*pT2;
|
|
}
|
|
|
|
static inline VOID DfsHwDetectionGetPulseInfo(PRTMP_ADAPTER pAd,
|
|
UINT8 ChannelIndex,
|
|
PUINT32 pPeriod,
|
|
PUINT32 pWidth1,
|
|
PUINT32 pWidth2,
|
|
PUINT32 pBurst)
|
|
{
|
|
#if MT76x0
|
|
UINT32 bbp_val = 0;
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = \
|
|
&pAd->CommonCfg.RadarDetect.DfsProgramParam;
|
|
#else
|
|
UINT8 bbp_val = 0;
|
|
#endif /* MT76x0 */
|
|
|
|
*pPeriod = *pWidth1 = *pWidth2 = *pBurst = 0;
|
|
|
|
#if MT76x0
|
|
/* select channel */
|
|
bbp_val = (pDfsProgramParam->ChEnable << 16) | ChannelIndex;
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val);
|
|
|
|
/* Read reports - Period */
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R19, pPeriod);
|
|
|
|
/* Read reports - Width */
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R20, pWidth1);
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R23, pWidth2);
|
|
|
|
/* Read reports - Burst Number */
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R22, pBurst);
|
|
#else
|
|
/* select channel*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x0, ChannelIndex);
|
|
|
|
/* Read reports - Period */
|
|
RTMP_DFS_IO_READ8(pAd, 0x2d, &bbp_val);
|
|
*pPeriod = bbp_val;
|
|
RTMP_DFS_IO_READ8(pAd, 0x2e, &bbp_val);
|
|
*pPeriod += (bbp_val << 8);
|
|
RTMP_DFS_IO_READ8(pAd, 0x2f, &bbp_val);
|
|
*pPeriod += (bbp_val << 16);
|
|
RTMP_DFS_IO_READ8(pAd, 0x30, &bbp_val);
|
|
*pPeriod += (bbp_val << 24);
|
|
|
|
/* Read reports - Width */
|
|
RTMP_DFS_IO_READ8(pAd, 0x31, &bbp_val);
|
|
*pWidth1 = bbp_val;
|
|
RTMP_DFS_IO_READ8(pAd, 0x32, &bbp_val);
|
|
*pWidth1 += (bbp_val << 8);
|
|
|
|
RTMP_DFS_IO_READ8(pAd, 0x37, &bbp_val);
|
|
*pWidth2 = bbp_val;
|
|
RTMP_DFS_IO_READ8(pAd, 0x38, &bbp_val);
|
|
*pWidth2 += (bbp_val << 8);
|
|
|
|
/* Read reports - Burst Number */
|
|
RTMP_DFS_IO_READ8(pAd, 0x33, &bbp_val);
|
|
*pBurst = bbp_val;
|
|
RTMP_DFS_IO_READ8(pAd, 0x34, &bbp_val);
|
|
*pBurst += (bbp_val << 8);
|
|
RTMP_DFS_IO_READ8(pAd, 0x35, &bbp_val);
|
|
*pBurst += (bbp_val << 16);
|
|
RTMP_DFS_IO_READ8(pAd, 0x36, &bbp_val);
|
|
*pBurst += (bbp_val << 24);
|
|
#endif /* MT76x0 */
|
|
}
|
|
|
|
static inline VOID DfsProgramBbpValues(PRTMP_ADAPTER pAd,
|
|
pNewDFSTable pDfsTable)
|
|
{
|
|
UINT8 idx, DfsInputControl;
|
|
UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
|
|
|
|
#ifdef MT76x0
|
|
{
|
|
UINT32 bbp_val = 0;
|
|
|
|
DfsInputControl = pDfsProgramParam->Symmetric_Round << 4;
|
|
|
|
/* Delta Delay*/
|
|
DfsInputControl |= (pDfsProgramParam->DeltaDelay & 0xf);
|
|
DBGPRINT(RT_DEBUG_TRACE,("R3 = 0x%x\n", DfsInputControl));
|
|
|
|
/* VGA Mask*/
|
|
DBGPRINT(RT_DEBUG_TRACE,("VGA_Mask = 0x%x\n", pDfsProgramParam->VGA_Mask));
|
|
|
|
/* Input Control 0 */
|
|
bbp_val = (pDfsProgramParam->VGA_Mask << 16) | (DfsInputControl);
|
|
|
|
bbp_val |= (pDfsProgramParam->PwrDown_Hold_Time << 8);
|
|
bbp_val |= (pDfsProgramParam->PwrGain_Offset << 12);
|
|
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R2, bbp_val);
|
|
|
|
/* packet end Mask*/
|
|
DBGPRINT(RT_DEBUG_TRACE,("Packet_End_Mask = 0x%x\n", pDfsProgramParam->Packet_End_Mask));
|
|
|
|
/* Rx PE Mask*/
|
|
DBGPRINT(RT_DEBUG_TRACE,("Rx_PE_Mask = 0x%x\n", pDfsProgramParam->Rx_PE_Mask));
|
|
|
|
/* Input Control 1 */
|
|
bbp_val = (pDfsProgramParam->Rx_PE_Mask << 16) | (pDfsProgramParam->Packet_End_Mask);
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R3, bbp_val);
|
|
|
|
/* AGC Input Control */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R32, 0x00040071);
|
|
#if 0
|
|
/*
|
|
2a7c=0x00xx0307
|
|
(2a7c[23:16] = (2310[21:16] + 2320[14:9] - 2320[5:3]), CR2320/2310 is from bring up result)
|
|
*/
|
|
/* AGC Input Control */
|
|
RTMP_BBP_IO_READ32(pAd, AGC1_R4, &bbp_val);
|
|
dfs_r31 = (bbp_val & 0x003f0000) >> 16;
|
|
RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val);
|
|
dfs_r31 += (bbp_val & 0x00007e00) >> 9;
|
|
RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val);
|
|
dfs_r31 -= (bbp_val & 0x00000038) >> 3;
|
|
dfs_r31 = (dfs_r31 << 16) | 0x00000307;
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R31, dfs_r31);
|
|
#else
|
|
MT7650_ADJUST_AGC(pAd);
|
|
MT7650_ADJUST_DFS_AGC(pAd);
|
|
#endif
|
|
/* program each channel*/
|
|
for (idx = 0; idx < DfsEngineNum; idx++)
|
|
{
|
|
if (IS_MT76x0(pAd) && (idx == 1))
|
|
continue;
|
|
|
|
/* select channel*/
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R0, idx);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("write DFS Channle[%d] configuration \n", idx));
|
|
|
|
/* Detection Mode */
|
|
bbp_val = (pDfsTable->entry[idx].mode & 0xf);
|
|
|
|
if (pAd->chipCap.DfsEngineNum > 4 && (idx==4 || idx==5))
|
|
bbp_val |= ((pDfsTable->entry[idx].avgLen & 0x3) << 28);
|
|
else
|
|
bbp_val |= ((pDfsTable->entry[idx].avgLen & 0x1ff) << 16);
|
|
|
|
/* DFS Mode */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R4, bbp_val);
|
|
|
|
/* DFS Energy */
|
|
bbp_val = ((pDfsTable->entry[idx].EHigh & 0x0fff) << 16) | (pDfsTable->entry[idx].ELow & 0x0fff);
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R5, bbp_val);
|
|
|
|
/* DFS Period Low */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R7, pDfsTable->entry[idx].TLow);
|
|
|
|
/* DFS Period High */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R9, pDfsTable->entry[idx].THigh);
|
|
|
|
/* DFS Burst Low */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R11, pDfsTable->entry[idx].BLow);
|
|
|
|
/* DFS Burst High */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R13, pDfsTable->entry[idx].BHigh);
|
|
|
|
/* DFS Width */
|
|
bbp_val = ((pDfsTable->entry[idx].WHigh & 0x0fff) << 16) | (pDfsTable->entry[idx].WLow & 0x0fff);
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R14, bbp_val);
|
|
|
|
|
|
/* DFS Measurement Uncertainty */
|
|
bbp_val = (pDfsTable->entry[idx].EpsilonW << 16) | (pDfsTable->entry[idx].EpsilonT);
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R15, bbp_val);
|
|
|
|
/* DFS Event Expiration */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R17, pDfsTable->entry[idx].EventExpiration);
|
|
|
|
/* DFS Power Jump */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R30, pDfsTable->entry[idx].PwrJump);
|
|
}
|
|
|
|
/* Reset status */
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask);
|
|
|
|
if (IS_MT76x0(pAd))
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R36, 0x00000003);
|
|
|
|
/* Enable detection*/
|
|
bbp_val = (pDfsProgramParam->ChEnable << 16);
|
|
RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val);
|
|
}
|
|
#else
|
|
DfsInputControl = pDfsProgramParam->Symmetric_Round << 4;
|
|
|
|
/* Full 40Mhz*/
|
|
if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
|
|
{
|
|
/* BW 40*/
|
|
DfsInputControl |= 0x80;
|
|
}
|
|
|
|
/* Delta Delay*/
|
|
DfsInputControl |= (pDfsProgramParam->DeltaDelay & 0xf);
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x3, DfsInputControl);
|
|
DBGPRINT(RT_DEBUG_TRACE,("R3 = 0x%x\n", DfsInputControl));
|
|
|
|
/* VGA Mask*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x4, pDfsProgramParam->VGA_Mask);
|
|
DBGPRINT(RT_DEBUG_TRACE,("VGA_Mask = 0x%x\n", pDfsProgramParam->VGA_Mask));
|
|
|
|
/* packet end Mask*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x5, pDfsProgramParam->Packet_End_Mask);
|
|
DBGPRINT(RT_DEBUG_TRACE,("Packet_End_Mask = 0x%x\n", pDfsProgramParam->Packet_End_Mask));
|
|
|
|
/* Rx PE Mask*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x6, pDfsProgramParam->Rx_PE_Mask);
|
|
DBGPRINT(RT_DEBUG_TRACE,("Rx_PE_Mask = 0x%x\n", pDfsProgramParam->Rx_PE_Mask));
|
|
|
|
/* program each channel*/
|
|
for (idx = 0; idx < DfsEngineNum; idx++)
|
|
{
|
|
/* select channel*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x0, idx);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("write DFS Channle[%d] configuration \n",idx));
|
|
/* start programing*/
|
|
|
|
/* reg 0x10, Detection Mode[2:0]*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x10, (pDfsTable->entry[idx].mode & 0xf));
|
|
|
|
/* reg 0x11~0x12, M[7:0] & M[8]*/
|
|
|
|
if (pAd->chipCap.DfsEngineNum > 4 &&
|
|
(idx==4 || idx==5))
|
|
{
|
|
/* Ch 4 and Ch5 use indirect M which taking the M value of another channel (one of 0~3) */
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x12, ((pDfsTable->entry[idx].avgLen << 4) & 0x30));
|
|
}
|
|
else
|
|
{
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x11, (pDfsTable->entry[idx].avgLen & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x12, ((pDfsTable->entry[idx].avgLen >> 8) & 0x1));
|
|
}
|
|
|
|
/* reg 0x13~0x14, Energy Low[7:0] & Energy Low[11:8]*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x13, (pDfsTable->entry[idx].ELow & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x14, ((pDfsTable->entry[idx].ELow >> 8) & 0xf));
|
|
|
|
|
|
/* reg 0x15~0x16, Energy High[7:0] & Energy High[11:8]*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x15, (pDfsTable->entry[idx].EHigh & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x16, ((pDfsTable->entry[idx].EHigh >> 8) & 0xf));
|
|
|
|
|
|
/* reg 0x28~0x29, Width Low[7:0] & Width Low[11:8]*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x28, (pDfsTable->entry[idx].WLow & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x29, ((pDfsTable->entry[idx].WLow >> 8) & 0xf));
|
|
|
|
/* reg 0x2a~0x2b, Width High[7:0] & Width High[11:8]*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x2a, (pDfsTable->entry[idx].WHigh & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x2b, ((pDfsTable->entry[idx].WHigh >> 8) & 0xf));
|
|
|
|
/* reg 0x2c, Width Delta[7:0], (Width Measurement Uncertainty)*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x2c, (pDfsTable->entry[idx].EpsilonW & 0xff));
|
|
|
|
/* reg 0x17~0x1a, Period Low[7:0] & Period Low[15:8] & Period Low[23:16] & Period Low[31:24]*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x17, (pDfsTable->entry[idx].TLow & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x18, ((pDfsTable->entry[idx].TLow >> 8) & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x19, ((pDfsTable->entry[idx].TLow >> 16) & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x1a, ((pDfsTable->entry[idx].TLow >> 24) & 0xff));
|
|
|
|
/* reg 0x1b~0x1e, Period High[7:0] & Period High[15:8] & Period High[23:16] & Period High[31:24]*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x1b, (pDfsTable->entry[idx].THigh & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x1c, ((pDfsTable->entry[idx].THigh >> 8) & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x1d, ((pDfsTable->entry[idx].THigh >> 16) & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x1e, ((pDfsTable->entry[idx].THigh >> 24) & 0xff));
|
|
|
|
/* reg 0x27, Period Delt[7:0], (Period Measurement Uncertainty)*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x27, (pDfsTable->entry[idx].EpsilonT & 0xff));
|
|
|
|
if (pDfsProgramParam->RadarEventExpire[idx] != 0)
|
|
{
|
|
RTMP_DFS_IO_WRITE8(pAd,0x39, (pDfsTable->entry[idx].EventExpiration & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd,0x3a, ((pDfsTable->entry[idx].EventExpiration >> 8) & 0xff) );
|
|
RTMP_DFS_IO_WRITE8(pAd,0x3b, ((pDfsTable->entry[idx].EventExpiration >> 16) & 0xff));
|
|
RTMP_DFS_IO_WRITE8(pAd,0x3c, ((pDfsTable->entry[idx].EventExpiration >> 24) & 0xff));
|
|
}
|
|
|
|
}
|
|
|
|
/* reset status */
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask);
|
|
/* Enable detection*/
|
|
RTMP_DFS_IO_WRITE8(pAd, 0x1, (pDfsProgramParam->ChEnable));
|
|
#endif /* MT76x0 */
|
|
}
|
|
|
|
#ifdef RTMP_MAC_PCI
|
|
static VOID SwCheckDfsEvent(
|
|
IN PRTMP_ADAPTER pAd);
|
|
#endif /* RTMP_MAC_PCI */
|
|
|
|
#ifdef RTMP_MAC_USB
|
|
static VOID SwCheckDfsEventWithFw(
|
|
IN PRTMP_ADAPTER pAd);
|
|
#endif /*RTMP_MAC_USB */
|
|
|
|
/*
|
|
========================================================================
|
|
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;
|
|
|
|
if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE)
|
|
pAd->Dot11_H.InServiceMonitorCount++;
|
|
|
|
for (i=0; i<pAd->ChannelListNum; i++)
|
|
{
|
|
if (pAd->ChannelList[i].RemainingTimeForUse > 0)
|
|
{
|
|
pAd->ChannelList[i].RemainingTimeForUse --;
|
|
if ((pAd->Mlme.PeriodicRound%5) == 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_INFO, ("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;
|
|
}
|
|
|
|
|
|
/* 0 = Switch Channel when Radar Hit (Normal mode)
|
|
1 = Don't Switch Channel when Radar Hit */
|
|
INT Set_RadarDebug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
pRadarDetect->McuRadarDebug = simple_strtol(arg, 0, 16);
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT)
|
|
printk("Show raw data of the event buffer.\n");
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT)
|
|
{
|
|
if (pRadarDetect->bDfsSwDisable == 1)
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s(): Warning!! DfsSwDisable is 1\n", __FUNCTION__));
|
|
printk("Show effective event\n");
|
|
}
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SILENCE)
|
|
printk("Silence\n");
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH)
|
|
printk("Dont Switch Channel\n");
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_BUSY)
|
|
printk("Dont Check Channel Busy\n");
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_RSSI)
|
|
printk("Dont Check RSSI\n");
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE)
|
|
printk("Simulate a radar detection\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_ResetRadarHwDetect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
DfsResetHwDetectionStatus(pAd);
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_DfsSwDisable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
pRadarDetect->bDfsSwDisable = simple_strtol(arg, 0, 10);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("pRadarDetect->bDfsSwDisable = %u\n", pRadarDetect->bDfsSwDisable));
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_DfsEnvtDropAdjTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
|
|
pDfsSwParam->EvtDropAdjTime = simple_strtol(arg, 0, 10);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("EventDropAdjTime = %u\n", pDfsSwParam->EvtDropAdjTime));
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_RadarStart_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam;
|
|
|
|
if (simple_strtol(arg, 0, 10) == 0)
|
|
{
|
|
NewRadarDetectionStart(pAd);
|
|
}
|
|
else if ((simple_strtol(arg, 0, 10) >= 1) && (simple_strtol(arg, 0, 10) <= pAd->CommonCfg.RadarDetect.EnabledChMask))
|
|
{
|
|
pDfsProgramParam->ChEnable = simple_strtol(arg, 0, 10);
|
|
printk("Ch Enable == 0x%x\n", pDfsProgramParam->ChEnable);
|
|
NewRadarDetectionStart(pAd);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_RadarStop_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
NewRadarDetectionStop(pAd);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
INT Set_RadarSetTbl1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PUCHAR p2 = arg;
|
|
ULONG idx, value;
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam;
|
|
|
|
while((*p2 != ':') && (*p2 != '\0'))
|
|
{
|
|
p2++;
|
|
}
|
|
|
|
if (*p2 == ':')
|
|
{
|
|
A2Dec(idx, arg);
|
|
A2Dec(value, p2+ 1);
|
|
if (idx == 0)
|
|
{
|
|
pDfsProgramParam->DeltaDelay = value;
|
|
printk("Delta_Delay = %d\n", pDfsProgramParam->DeltaDelay);
|
|
}
|
|
else
|
|
modify_table1(pAd, idx, value);
|
|
|
|
if (pAd->CommonCfg.RadarDetect.pDFSTable)
|
|
NewRadarDetectionProgram(pAd, pAd->CommonCfg.RadarDetect.pDFSTable);
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s(): Table not initialized.\n", __FUNCTION__));
|
|
}
|
|
else
|
|
printk("please enter iwpriv ra0 set RadarT1=xxx:yyy\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_RadarSetTbl2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PUCHAR p2 = arg;
|
|
ULONG idx, value;
|
|
|
|
while((*p2 != ':') && (*p2 != '\0'))
|
|
{
|
|
p2++;
|
|
}
|
|
|
|
if (*p2 == ':')
|
|
{
|
|
A2Dec(idx, arg);
|
|
A2Dec(value, p2+ 1);
|
|
modify_table2(pAd, idx, value);
|
|
}
|
|
else
|
|
printk("please enter iwpriv ra0 set RadarT2=xxx:yyy\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_PollTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
pRadarDetect->PollTime = simple_strtol(arg, 0, 10);
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_PrintBusyIdle_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
pRadarDetect->print_ch_busy_sta = simple_strtol(arg, 0, 10);
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_BusyIdleRatio_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
pRadarDetect->ch_busy_idle_ratio = simple_strtol(arg, 0, 10);
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_DfsRssiHigh_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
pRadarDetect->DfsRssiHigh = simple_strtol(arg, 0, 10);
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_DfsRssiLow_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
pRadarDetect->DfsRssiLow = simple_strtol(arg, 0, 10);
|
|
return TRUE;
|
|
}
|
|
|
|
INT Show_BlockCh_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<pAd->ChannelListNum; i++)
|
|
{
|
|
if (pAd->ChannelList[i].RemainingTimeForUse != 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("Ch%d: RemainingTimeForUse:%d sec;\n",
|
|
pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse));
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID DFSInit(PRTMP_ADAPTER pAd)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
|
|
|
|
pRadarDetect->ch_busy_countdown = -1;
|
|
pRadarDetect->EnabledChMask = ((1 << pAd->chipCap.DfsEngineNum) -1);
|
|
#ifdef MT76x0
|
|
if (IS_MT76x0(pAd))
|
|
{
|
|
#if 0
|
|
MT76x0_DFS_CR_Init(pAd);
|
|
#endif
|
|
/*
|
|
Do NOT enable Radar Channel 1. (MT7650 DFS programming guide_v2_20121012.docx)
|
|
*/
|
|
pRadarDetect->EnabledChMask = 0xD;
|
|
pRadarDetect->bAdjustDfsAgc = FALSE;
|
|
pDfsProgramParam->PwrDown_Hold_Time = 0xf;
|
|
pDfsProgramParam->PwrGain_Offset = 0x3;
|
|
}
|
|
#endif /* MT76x0 */
|
|
pRadarDetect->PollTime = 3;
|
|
pRadarDetect->DfsRssiHigh = -30;
|
|
pRadarDetect->DfsRssiLow = -90;
|
|
pRadarDetect->use_tasklet = 1;
|
|
pRadarDetect->McuRadarDebug = 0;
|
|
pRadarDetect->radarDeclared = 0;
|
|
pDfsProgramParam->ChEnable = pRadarDetect->EnabledChMask;
|
|
|
|
#ifdef MT76x0
|
|
if (IS_MT76x0(pAd))
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* Set mask to 0 due to ASIC bug */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
pDfsProgramParam->VGA_Mask = 0;
|
|
pDfsProgramParam->Packet_End_Mask = 0;
|
|
pDfsProgramParam->Rx_PE_Mask = 0;
|
|
pDfsProgramParam->DeltaDelay = 0x2;
|
|
pDfsProgramParam->Symmetric_Round = 0;
|
|
}
|
|
else
|
|
#endif /* MT76x0 */
|
|
{
|
|
pDfsProgramParam->VGA_Mask = 45;
|
|
pDfsProgramParam->Packet_End_Mask = 45;
|
|
pDfsProgramParam->Rx_PE_Mask = 45;
|
|
pDfsProgramParam->DeltaDelay = 0x3;
|
|
pDfsProgramParam->Symmetric_Round = 1;
|
|
}
|
|
/*
|
|
s/w detection needs event buffer.
|
|
*/
|
|
if (pAd->chipCap.DfsEngineNum > 4)
|
|
pRadarDetect->bDfsSwDisable = TRUE; /* Default close s/w detection for new DFS*/
|
|
|
|
dfs_sw_init(pAd);
|
|
}
|
|
|
|
void NewRadarDetectionStart(PRTMP_ADAPTER pAd)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
pNewDFSTable *ppDFSTable = &pRadarDetect->pDFSTable;
|
|
|
|
pRadarDetect->bDfsInit = FALSE;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("--->NewRadarDetectionStart()\n"));
|
|
|
|
DFSInit(pAd);
|
|
|
|
#ifdef RTMP_MAC_USB
|
|
INIT_DFS_EVENT_BUFF_SHARED_MEMORY(pAd, BBPR127TABLE_OFFSET, 8, 0xfe);
|
|
#endif /* RTMP_MAC_USB */
|
|
|
|
RTMP_CHIP_RADAR_GLRT_COMPENSATE(pAd);
|
|
|
|
if ((pAd->CommonCfg.RDDurRegion == CE) && RESTRICTION_BAND_1(pAd))
|
|
pAd->Dot11_H.ChMovingTime = 605;
|
|
else
|
|
pAd->Dot11_H.ChMovingTime = 65;
|
|
|
|
if (pAd->CommonCfg.RDDurRegion == FCC)
|
|
{
|
|
if (pRadarDetect->ch_busy_idle_ratio == 0)
|
|
pRadarDetect->ch_busy_idle_ratio = 2;
|
|
|
|
*ppDFSTable = &NewDFSTable1[0];
|
|
DBGPRINT(RT_DEBUG_TRACE,("DFS start, use FCC table\n"));
|
|
}
|
|
else if (pAd->CommonCfg.RDDurRegion == CE)
|
|
{
|
|
if (pRadarDetect->ch_busy_idle_ratio == 0)
|
|
pRadarDetect->ch_busy_idle_ratio = 3;
|
|
|
|
*ppDFSTable = &NewDFSTable1[1];
|
|
DBGPRINT(RT_DEBUG_TRACE,("DFS start, use CE table\n"));
|
|
}
|
|
else /* JAP*/
|
|
{
|
|
if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64))
|
|
{
|
|
*ppDFSTable = &NewDFSTable1[3];
|
|
|
|
if (pRadarDetect->ch_busy_idle_ratio == 0)
|
|
pRadarDetect->ch_busy_idle_ratio = 3;
|
|
}
|
|
else
|
|
{
|
|
*ppDFSTable = &NewDFSTable1[2];
|
|
|
|
if (pRadarDetect->ch_busy_idle_ratio == 0)
|
|
pRadarDetect->ch_busy_idle_ratio = 2;
|
|
}
|
|
DBGPRINT(RT_DEBUG_TRACE,("DFS start, use JAP table\n"));
|
|
}
|
|
|
|
#ifdef MT76x0
|
|
if (IS_MT7610E(pAd))
|
|
{
|
|
if (pAd->CommonCfg.RDDurRegion == CE)
|
|
*ppDFSTable = &NewDFSTable2[1];
|
|
else
|
|
*ppDFSTable = &NewDFSTable2[0];
|
|
}
|
|
#endif /* MT76x0 */
|
|
|
|
NewRadarDetectionProgram(pAd, (*ppDFSTable));
|
|
|
|
#ifdef RTMP_MAC_PCI
|
|
/* enable debug mode*/
|
|
DfsCaptureModeControl(pAd, TRUE, TRUE, FALSE);
|
|
|
|
RTMP_HW_TIMER_INT_SET(pAd, HW_TIMER_INTERVAL); /* 1ms Timer interrupt */
|
|
RTMP_HW_TIMER_INT_ENABLE(pAd);
|
|
#endif /* RTMP_MAC_PCI */
|
|
#ifdef RTMP_MAC_USB
|
|
if (NewRadarDetectionMcuStart(pAd) == FALSE)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("NewRadarDetectionMcuStart failed.\n"));
|
|
}
|
|
#endif /* RTMP_MAC_USB */
|
|
pRadarDetect->bDfsInit = TRUE;
|
|
DBGPRINT(RT_DEBUG_TRACE,("Poll Time=%d\n", pRadarDetect->PollTime));
|
|
}
|
|
|
|
|
|
VOID NewRadarDetectionStop(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("NewRadarDetectionStop\n"));
|
|
|
|
/* set init bit = false to prevent dfs rotines */
|
|
pRadarDetect->bDfsInit = FALSE;
|
|
pRadarDetect->radarDeclared = 0;
|
|
|
|
/* Disable detection*/
|
|
DfsDetectionDisable(pAd);
|
|
|
|
/* Clear status */
|
|
DfsResetHwDetectionStatus(pAd);
|
|
|
|
#ifdef RTMP_MAC_PCI
|
|
RTMP_HW_TIMER_INT_SET(pAd, 0);
|
|
RTMP_HW_TIMER_INT_DISABLE(pAd);
|
|
#endif /* RTMP_MAC_PCI */
|
|
#ifdef RTMP_MAC_USB
|
|
if (NewRadarDetectionMcuStop(pAd) == FALSE)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("NewRadarDetectionMcuStop failed.\n"));
|
|
}
|
|
#endif /* RTMP_MAC_USB */
|
|
|
|
}
|
|
|
|
|
|
/* the debug port have timestamp 22 digit, the max number is 0x3fffff, each unit is 25ns for 40Mhz mode and 50ns for 20Mhz mode*/
|
|
/* so a round of timestamp is about 25 * 0x3fffff / 1000 = 104857us (about 100ms) or*/
|
|
/* 50 * 0x3fffff / 1000 = 209715us (about 200ms) in 20Mhz mode*/
|
|
/* 3ms = 3000,000 ns / 25ns = 120000 -- a unit */
|
|
/* 0x3fffff/120000 = 34.9 ~= 35*/
|
|
/* CE Staggered radar check*/
|
|
/* At beginning, the goal is to detect staggered radar, now, we also detect regular radar with this function.*/
|
|
|
|
|
|
int SWRadarCheck(
|
|
IN PRTMP_ADAPTER pAd, USHORT id)
|
|
{
|
|
int i, j, start_idx, end_idx;
|
|
pNewDFSDebugPort pCurrent, p1, pEnd;
|
|
ULONG period;
|
|
int radar_detected = 0;
|
|
USHORT widthsum;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
|
|
/*ENTRY_PLUS could be replace by (pDfsSwParam->sw_idx[id]+1)%128*/
|
|
USHORT Total, SwIdxPlus = ENTRY_PLUS(pDfsSwParam->sw_idx[id], 1, NEW_DFS_DBG_PORT_ENT_NUM);
|
|
UCHAR CounterToCheck;
|
|
|
|
#ifdef MT76x0
|
|
/* only engine 0 and engine2 support event buffer */
|
|
if (id == 1)
|
|
return 0;
|
|
#endif /* MT76x0 */
|
|
|
|
if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) ||
|
|
(SwIdxPlus == pDfsSwParam->hw_idx[id])) /* no entry to process*/
|
|
return 0;
|
|
|
|
/* process how many entries?? total NEW_DFS_DBG_PORT_ENT_NUM*/
|
|
if (pDfsSwParam->hw_idx[id] > SwIdxPlus)
|
|
Total = pDfsSwParam->hw_idx[id] - SwIdxPlus;
|
|
else
|
|
Total = pDfsSwParam->hw_idx[id] + NEW_DFS_DBG_PORT_ENT_NUM - SwIdxPlus;
|
|
|
|
if (Total > NEW_DFS_DBG_PORT_ENT_NUM)
|
|
pDfsSwParam->pr_idx[id] = ENTRY_PLUS(pDfsSwParam->sw_idx[id], MAX_PROCESS_ENTRY, NEW_DFS_DBG_PORT_ENT_NUM);
|
|
else
|
|
pDfsSwParam->pr_idx[id] = ENTRY_PLUS(pDfsSwParam->sw_idx[id], Total, NEW_DFS_DBG_PORT_ENT_NUM);
|
|
|
|
|
|
start_idx = ENTRY_PLUS(pDfsSwParam->pr_idx[id], 1, NEW_DFS_DBG_PORT_ENT_NUM);
|
|
end_idx = pDfsSwParam->pr_idx[id];
|
|
|
|
pEnd = &pDfsSwParam->DFS_W[id][end_idx];
|
|
|
|
if (start_idx > end_idx)
|
|
end_idx += NEW_DFS_DBG_PORT_ENT_NUM;
|
|
|
|
|
|
pDfsSwParam->sw_idx[id] = pDfsSwParam->pr_idx[id];
|
|
|
|
/* FCC && Japan*/
|
|
|
|
if (pAd->CommonCfg.RDDurRegion != CE)
|
|
{
|
|
ULONG minPeriod = (3000 << 1);
|
|
/* Calculate how many counters to check*/
|
|
/* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/
|
|
/* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/
|
|
/* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/
|
|
/* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/
|
|
/* the max period to check for 40Mhz for FCC is 28650 * 2*/
|
|
/* the max period to check for 40Mhz for Japan is 80000 * 2*/
|
|
/* 0x40000 = 4194304 / 57129 = 73.xxx*/
|
|
/* 0x40000 = 4194304 / 160000 = 26.2144*/
|
|
/* 53/73 < 1 (1+1)*/
|
|
/* 53/26.2144 = 2.02... (2+1)*/
|
|
/* 27/26.2144 = 1.02... (1+1)*/
|
|
/* 20M should use the same value as 40Mhz mode*/
|
|
|
|
if (pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53)
|
|
{
|
|
minPeriod = 28500 << 1;
|
|
}
|
|
|
|
if (pAd->CommonCfg.RDDurRegion == FCC)
|
|
{
|
|
CounterToCheck = 1+1;
|
|
}
|
|
else /* if (pAd->CommonCfg.RDDurRegion == JAP)*/
|
|
{
|
|
if (pRadarDetect->PollTime <= 2)
|
|
CounterToCheck = 2+1;
|
|
else
|
|
CounterToCheck = 1+1;
|
|
}
|
|
|
|
/* First Loop for FCC/JAP*/
|
|
for (i = end_idx; i > start_idx; i--)
|
|
{
|
|
pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
|
|
|
|
/* we only handle entries has same counter with the last one*/
|
|
if (pCurrent->counter != pEnd->counter)
|
|
break;
|
|
|
|
pCurrent->start_idx = 0xffff;
|
|
|
|
/* calculate if any two pulse become a valid period, add it in period table,*/
|
|
for (j = i - 1; j > start_idx; j--)
|
|
{
|
|
p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK];
|
|
|
|
/* check period, must within max period*/
|
|
if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
|
|
{
|
|
if (p1->counter + CounterToCheck < pCurrent->counter)
|
|
break;
|
|
|
|
widthsum = p1->width + pCurrent->width;
|
|
if (id == 0)
|
|
{
|
|
if (widthsum < 600)
|
|
pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
|
|
else
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
|
|
}
|
|
else if (id == 1)
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift;
|
|
else if (id == 2)
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
|
|
|
|
if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
|
|
(PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
|
|
{
|
|
if (p1->timestamp >= pCurrent->timestamp)
|
|
period = 0x400000 + pCurrent->timestamp - p1->timestamp;
|
|
else
|
|
period = pCurrent->timestamp - p1->timestamp;
|
|
|
|
if ((period >= (minPeriod - 2)) && (period <= pDfsSwParam->dfs_max_period))
|
|
{
|
|
/* add in period table*/
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
|
|
|
|
if (pCurrent->start_idx == 0xffff)
|
|
pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
|
|
pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
|
|
|
|
pDfsSwParam->dfs_t_idx[id]++;
|
|
if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
|
|
pDfsSwParam->dfs_t_idx[id] = 0;
|
|
}
|
|
else if (period > pDfsSwParam->dfs_max_period)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p1->counter + CounterToCheck < pCurrent->counter)
|
|
break;
|
|
|
|
widthsum = p1->width + pCurrent->width;
|
|
if (id == 0)
|
|
{
|
|
if (widthsum < 600)
|
|
pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
|
|
else
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
|
|
}
|
|
else if (id == 1)
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift;
|
|
else if (id == 2)
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
|
|
|
|
|
|
if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
|
|
(PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
|
|
|
|
{
|
|
if (p1->timestamp >= pCurrent->timestamp)
|
|
period = 0x400000 + pCurrent->timestamp - p1->timestamp;
|
|
else
|
|
period = pCurrent->timestamp - p1->timestamp;
|
|
|
|
if ((period >= ((minPeriod >> 1) - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))
|
|
{
|
|
/* add in period table*/
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
|
|
|
|
if (pCurrent->start_idx == 0xffff)
|
|
pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
|
|
pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
|
|
|
|
pDfsSwParam->dfs_t_idx[id]++;
|
|
if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
|
|
pDfsSwParam->dfs_t_idx[id] = 0;
|
|
}
|
|
else if (period > (pDfsSwParam->dfs_max_period >> 1))
|
|
break;
|
|
}
|
|
}
|
|
} /* for (j = i - 1; j > start_idx; j--)*/
|
|
} /* for (i = end_idx; i > start_idx; i--)*/
|
|
|
|
/* Second Loop for FCC/JAP*/
|
|
for (i = end_idx; i > start_idx; i--)
|
|
{
|
|
pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
|
|
|
|
/* we only handle entries has same counter with the last one*/
|
|
if (pCurrent->counter != pEnd->counter)
|
|
break;
|
|
if (pCurrent->start_idx != 0xffff)
|
|
{
|
|
/*pNewDFSDebugPort p2, p3, p4, p5, p6;*/
|
|
pNewDFSDebugPort p2, p3;
|
|
pNewDFSMPeriod pCE_T;
|
|
ULONG idx[10], T[10];
|
|
|
|
for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)
|
|
{
|
|
pCE_T = &pDfsSwParam->DFS_T[id][idx[0]];
|
|
|
|
p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
|
|
|
|
if (p2->start_idx == 0xffff)
|
|
continue;
|
|
|
|
T[0] = pCE_T->period;
|
|
|
|
for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)
|
|
{
|
|
|
|
pCE_T = &pDfsSwParam->DFS_T[id][idx[1]];
|
|
|
|
p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
|
|
|
|
if (idx[0] == idx[1])
|
|
continue;
|
|
|
|
if (p3->start_idx == 0xffff)
|
|
continue;
|
|
|
|
T[1] = pCE_T->period;
|
|
|
|
if ( PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err))
|
|
{
|
|
if (id <= 2) /* && (id >= 0)*/
|
|
{
|
|
/*if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > minPeriod)) ||*/
|
|
/* ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > (minPeriod >> 1))) )*/
|
|
{
|
|
unsigned int loop, PeriodMatched = 0, idx1;
|
|
for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
|
|
{
|
|
idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop);
|
|
if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err))
|
|
PeriodMatched++;
|
|
}
|
|
|
|
if (PeriodMatched > pDfsSwParam->dfs_declare_thres)
|
|
{
|
|
{
|
|
pNewDFSValidRadar pDFSValidRadar;
|
|
ULONG T1 = (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)? (T[1]>>1) : T[1];
|
|
|
|
pDFSValidRadar = &NewDFSValidTable[0];
|
|
|
|
while (pDFSValidRadar->type != NEW_DFS_END)
|
|
{
|
|
if ((pDFSValidRadar->type & pRadarDetect->MCURadarRegion) == 0)
|
|
{
|
|
pDFSValidRadar++;
|
|
continue;
|
|
}
|
|
|
|
if (pDFSValidRadar->TLow)
|
|
{
|
|
if ( (T1 > (pDFSValidRadar->TLow - pDFSValidRadar->TMargin)) &&
|
|
(T1 < (pDFSValidRadar->THigh + pDFSValidRadar->TMargin)) )
|
|
{
|
|
radar_detected = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( (T1 > (pDFSValidRadar->T - pDFSValidRadar->TMargin)) &&
|
|
(T1 < (pDFSValidRadar->T + pDFSValidRadar->TMargin)) )
|
|
{
|
|
radar_detected = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pDFSValidRadar++;
|
|
}
|
|
if (radar_detected == 1)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched));
|
|
printk("SWRadarCheck: Radar Detected\n");
|
|
return radar_detected;
|
|
}
|
|
else if (pRadarDetect->MCURadarRegion != NEW_DFS_JAP_W53)
|
|
DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched));
|
|
}
|
|
}
|
|
}
|
|
} /* if (id <= 2) && (id >= 0)*/
|
|
}
|
|
} /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/
|
|
|
|
/* increase FCC-1 detection*/
|
|
if (id <= 2)
|
|
{
|
|
if (IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0]))
|
|
{
|
|
int loop, idx1, PeriodMatched_fcc1 = 0;
|
|
for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
|
|
{
|
|
idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop);
|
|
if ( IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) )
|
|
{
|
|
/*printk("%d %d %d\n", PeriodMatched_fcc1, pDfsSwParam->DFS_T[id][idx1].period, loop);*/
|
|
PeriodMatched_fcc1++;
|
|
}
|
|
}
|
|
|
|
if (PeriodMatched_fcc1 > 3)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_fcc1 = %d (%d)\n", PeriodMatched_fcc1, id));
|
|
radar_detected = 1;
|
|
return radar_detected;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* increase W56-3 detection*/
|
|
if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP) && (id <= 2))
|
|
{
|
|
if (IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0]))
|
|
{
|
|
int loop, idx1, PeriodMatched_w56_3 = 0;
|
|
for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
|
|
{
|
|
idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop);
|
|
if ( IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) )
|
|
{
|
|
/*printk("%d %d %d\n", PeriodMatched_w56_3, pDfsSwParam->DFS_T[id][idx1].period, loop);*/
|
|
PeriodMatched_w56_3++;
|
|
}
|
|
}
|
|
|
|
if (PeriodMatched_w56_3 > 3)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_w56_3 = %d (%d)\n", PeriodMatched_w56_3, id));
|
|
radar_detected = 1;
|
|
return radar_detected;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53) && (id <= 2) && IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0]))
|
|
{
|
|
int loop, idx1, PeriodMatched_W56_2 = 0;
|
|
|
|
for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
|
|
{
|
|
idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop);
|
|
if ( IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) )
|
|
{
|
|
/*printk("%d %d %d\n", PeriodMatched_W56_2, pDfsSwParam->DFS_T[id][idx1].period, loop);*/
|
|
PeriodMatched_W56_2++;
|
|
}
|
|
}
|
|
|
|
if (PeriodMatched_W56_2 >= 3)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_W56_2 = %d(%d)\n", PeriodMatched_W56_2, id));
|
|
radar_detected = 1;
|
|
return radar_detected;
|
|
}
|
|
}
|
|
} /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/
|
|
} /* if (pCurrent->start_idx != 0xffff)*/
|
|
} /* for (i = end_idx; i > start_idx; i--)*/
|
|
|
|
return radar_detected;
|
|
}
|
|
|
|
/* CE have staggered radar */
|
|
|
|
/* Calculate how many counters to check*/
|
|
/* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/
|
|
/* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/
|
|
/* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/
|
|
/* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/
|
|
/* if pRadarDetect->PollTime is 8ms, a round of timestamp is ?? for 20Mhz, 12 for 40Mhz*/
|
|
/* the max period to check for 40Mhz is 133333 + 125000 + 117647 = 375980*/
|
|
/* 0x40000 = 4194304 / 375980 = 11.1556*/
|
|
/* 53/11.1556 = 4.75...*/
|
|
/* 35/11.1556 = 3.1374, (4+1) is safe, (3+1) to save CPU power, but may lost some data*/
|
|
/* 27/11.1556 = 2.42, (3+1) is OK*/
|
|
/* 21/11.1556 = 1.88, (2+1) is OK*/
|
|
/* 20M should use the same value as 40Mhz mode*/
|
|
if (pRadarDetect->PollTime == 1)
|
|
CounterToCheck = 5+1;
|
|
else if (pRadarDetect->PollTime == 2)
|
|
CounterToCheck = 4+1;
|
|
else if (pRadarDetect->PollTime == 3)
|
|
CounterToCheck = 3+1;
|
|
else if (pRadarDetect->PollTime <= 8)
|
|
CounterToCheck = 2+1;
|
|
else
|
|
CounterToCheck = 1+1;
|
|
|
|
/* First Loop for CE*/
|
|
for (i = end_idx; i > start_idx; i--)
|
|
{
|
|
pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
|
|
|
|
/* we only handle entries has same counter with the last one*/
|
|
if (pCurrent->counter != pEnd->counter)
|
|
break;
|
|
|
|
pCurrent->start_idx = 0xffff;
|
|
|
|
/* calculate if any two pulse become a valid period, add it in period table,*/
|
|
for (j = i - 1; j > start_idx; j--)
|
|
{
|
|
p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK];
|
|
|
|
|
|
/* check period, must within 16666 ~ 66666*/
|
|
if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
|
|
{
|
|
if (p1->counter + CounterToCheck < pCurrent->counter)
|
|
break;
|
|
|
|
widthsum = p1->width + pCurrent->width;
|
|
#if 1
|
|
if (id == 0)
|
|
{
|
|
if (((p1->width > 310) && (pCurrent->width < 300)) || ((pCurrent->width > 310) && ((p1->width < 300))) )
|
|
continue;
|
|
if (widthsum < 620)
|
|
pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H;
|
|
else
|
|
pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
|
|
|
|
}
|
|
else if (id == 1)
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift;
|
|
else if (id == 2)
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
|
|
#else
|
|
pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff;
|
|
#endif
|
|
|
|
if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
|
|
(PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
|
|
{
|
|
if (p1->timestamp >= pCurrent->timestamp)
|
|
period = 0x400000 + pCurrent->timestamp - p1->timestamp;
|
|
else
|
|
period = pCurrent->timestamp - p1->timestamp;
|
|
|
|
/*if ((period >= (33333 - 20)) && (period <= (133333 + 20)))*/
|
|
if ((period >= (33333 - 20)) && (period <= pDfsSwParam->dfs_max_period))
|
|
//if ((period >= (10000 - 2)) && (period <= pDfsSwParam->dfs_max_period))
|
|
{
|
|
/* add in period table*/
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
|
|
|
|
if (pCurrent->start_idx == 0xffff)
|
|
pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
|
|
pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
|
|
|
|
pDfsSwParam->dfs_t_idx[id]++;
|
|
if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
|
|
pDfsSwParam->dfs_t_idx[id] = 0;
|
|
}
|
|
else if (period > pDfsSwParam->dfs_max_period) /* to allow miss a pulse*/
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (p1->counter + CounterToCheck < pCurrent->counter)
|
|
break;
|
|
|
|
widthsum = p1->width + pCurrent->width;
|
|
if (id == 0)
|
|
{
|
|
if (((p1->width > 300) && (pCurrent->width < 300)) || ((pCurrent->width > 300) && ((p1->width < 300))) )
|
|
continue;
|
|
if (widthsum < 620)
|
|
pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H;
|
|
else
|
|
pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
|
|
}
|
|
else if (id == 1)
|
|
{
|
|
pDfsSwParam->dfs_width_diff = widthsum >> 3; /* for 20M verified */
|
|
//printk("dfs_width_diff = %u\n",pDfsSwParam->dfs_width_diff);
|
|
}
|
|
else if (id == 2)
|
|
pDfsSwParam->dfs_width_diff = widthsum >> 6;
|
|
|
|
if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
|
|
(PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
|
|
|
|
{
|
|
if (p1->timestamp >= pCurrent->timestamp)
|
|
period = 0x400000 + pCurrent->timestamp - p1->timestamp;
|
|
else
|
|
period = pCurrent->timestamp - p1->timestamp;
|
|
|
|
//if ((period >= (5000 - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))
|
|
if ((period >= (16666 - 20)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))//neil modify for ce 5-1
|
|
{
|
|
/* add in period table*/
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
|
|
pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
|
|
|
|
if (pCurrent->start_idx == 0xffff)
|
|
pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
|
|
pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
|
|
|
|
pDfsSwParam->dfs_t_idx[id]++;
|
|
if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
|
|
pDfsSwParam->dfs_t_idx[id] = 0;
|
|
}
|
|
else if (period > (pDfsSwParam->dfs_max_period >> 1))
|
|
break;
|
|
}
|
|
}
|
|
} /* for (j = i - 1; j > start_idx; j--)*/
|
|
}
|
|
|
|
/* Second Loop for CE*/
|
|
for (i = end_idx; i > start_idx; i--)
|
|
{
|
|
pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
|
|
|
|
/* we only handle entries has same counter with the last one*/
|
|
if (pCurrent->counter != pEnd->counter)
|
|
break;
|
|
|
|
/* Check Staggered radar*/
|
|
if (pCurrent->start_idx != 0xffff)
|
|
{
|
|
pNewDFSDebugPort p2, p3;
|
|
pNewDFSMPeriod pCE_T;
|
|
ULONG idx[10], T[10];
|
|
|
|
/*printk("pCurrent=%d, idx=%d~%d\n", pCurrent->timestamp, pCurrent->start_idx, pCurrent->end_idx);*/
|
|
|
|
for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)
|
|
{
|
|
pCE_T = &pDfsSwParam->DFS_T[id][idx[0]];
|
|
|
|
p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
|
|
|
|
/*printk("idx[0]= %d, idx=%d p2=%d, idx=%d~%d\n", idx[0], pCE_T->idx2, p2->timestamp, p2->start_idx, p2->end_idx);*/
|
|
|
|
if (p2->start_idx == 0xffff)
|
|
continue;
|
|
|
|
T[0] = pCE_T->period;
|
|
|
|
|
|
for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)
|
|
{
|
|
|
|
pCE_T = &pDfsSwParam->DFS_T[id][idx[1]];
|
|
|
|
p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
|
|
|
|
/*printk("p3=%d, idx=%d~%d\n", p3->timestamp, p3->start_idx, p3->end_idx);*/
|
|
|
|
if (idx[0] == idx[1])
|
|
continue;
|
|
|
|
if (p3->start_idx == 0xffff)
|
|
continue;
|
|
|
|
|
|
|
|
T[1] = pCE_T->period;
|
|
|
|
|
|
if (PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err))
|
|
{
|
|
if (id <= 2) /* && (id >= 0)*/
|
|
{
|
|
|
|
|
|
if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > 66666)) ||
|
|
((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > 33333)) )
|
|
{
|
|
unsigned int loop, PeriodMatched = 0, idx1;
|
|
|
|
for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
|
|
{
|
|
idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop);
|
|
if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err))
|
|
{
|
|
/*printk("%d %d\n", loop, pDfsSwParam->DFS_T[id][idx[1]-loop].period);*/
|
|
PeriodMatched++;
|
|
}
|
|
}
|
|
|
|
if (PeriodMatched > pDfsSwParam->dfs_declare_thres)
|
|
{
|
|
printk("Radar Detected(CE), W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T[1], (unsigned int)id, PeriodMatched);
|
|
|
|
if (PeriodMatched > (pDfsSwParam->dfs_declare_thres + 1))
|
|
radar_detected = 1;
|
|
return radar_detected;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/
|
|
} /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/
|
|
}
|
|
} /* for (i = end_idx; i < start_idx; i--)*/
|
|
|
|
return radar_detected;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Recheck DFS radar of stager type.
|
|
Arguments:
|
|
pAdapter Pointer to our adapter
|
|
dfs_channel DFS detect channel
|
|
Return Value:
|
|
"TRUE" if check pass, "FALSE" otherwise.
|
|
Note:
|
|
==========================================================================
|
|
*/
|
|
static BOOLEAN StagerRadarCheck(IN PRTMP_ADAPTER pAd, UINT8 dfs_channel)
|
|
{
|
|
UINT T1=0, T2=0, T3=0, F1, F2, F3 = 0, Fmax = 0, freq_diff_min, freq_diff_max;
|
|
UINT8 dfs_stg2=0, dfs_typ5=0;
|
|
UINT F_MAX, F_MID, F_MIN;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("--->StagerRadarCheck()\n"));
|
|
StagerRadarGetPRIs(pAd, dfs_channel, &T1, &T2, &T3);
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* in field trial found possible RTL bug: T3=1 */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if (T3 < 5)
|
|
T3 = 0;
|
|
|
|
/*1. Check radar stagger2 or stagger3*/
|
|
if (T3 == 0 || ((T3 > (T1 + T2) ? (T3 - T1 - T2) : (T1 + T2 - T3)) < 25))
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("stg2 confirmed\n"));
|
|
dfs_stg2 =1;
|
|
F1 = 20000000/T1; /*hz*/
|
|
F2 = 20000000/T2;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("stg3 confirmed\n"));
|
|
F1 = 20000000/T1; /*hz*/
|
|
F2 = 20000000/T2;
|
|
F3 = 20000000/T3;
|
|
}
|
|
|
|
F_MAX = (F1 > F2) ? ( (F1 > F3) ? F1 : F3 ) : ( (F2 > F3) ? F2 : F3 );
|
|
F_MIN = (F1 < F2) ? ( (F1 < F3) ? F1 : F3 ) : ( (F2 < F3) ? F2 : F3 );
|
|
F_MID = (F1 > F2) ? ((F1 < F3) ? F1 : ( (F2 > F3) ? F2 : F3 )) : ( F2 < F3 ? F2 : ((F1 > F3) ? F1 :F3) );
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("F_MAX=%d F_MID=%d F_MIN=%d\n", F_MAX, F_MID, F_MIN));
|
|
|
|
F1 = F_MAX;
|
|
F2 = F_MID;
|
|
F3 = F_MIN;
|
|
|
|
Fmax = F1;
|
|
|
|
/*2. Check radar type 5 or type6*/
|
|
if (Fmax>295 && Fmax<=405)
|
|
{
|
|
dfs_typ5 = 1;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("type5 confirmed\n"));
|
|
freq_diff_min = 20;
|
|
freq_diff_max = 50;
|
|
}
|
|
else if (Fmax>405 && Fmax<=1205) /* tolerate more range for looser type6 */
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("type6 confirmed\n"));
|
|
freq_diff_min = 80;
|
|
freq_diff_max = 400;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, T1=%d, T2=%d, T3=%d\n", T1, T2, T3));
|
|
return FALSE;
|
|
}
|
|
|
|
/*3. According to decision of stagger and type do period check */
|
|
if (dfs_stg2 == 1)
|
|
{
|
|
#if 0
|
|
UINT freq_diff = (F1 > F2) ? (F1 - F2) : (F2 - F1);
|
|
#endif
|
|
UINT freq_diff = (F1 - F2);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck freq_diff_min=%d freq_diff_max=%d \n", freq_diff_min, freq_diff_max));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck dfs_stg2, dff=%d \n", freq_diff));
|
|
|
|
if ((freq_diff >= freq_diff_min) && (freq_diff <= freq_diff_max))
|
|
return TRUE; /* S/W check success */
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, F1=%d, F2=%d\n", F1, F2));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("stg2 fail on S/W Freq confirmed\n"));
|
|
return FALSE; /* S/W check fail */
|
|
}
|
|
}
|
|
else /* dfs_stg3 */
|
|
{
|
|
#if 0
|
|
UINT freq_diff_1 = (F1 > F2) ? (F1 - F2) : (F2 - F1);
|
|
UINT freq_diff_2 = (F2 > F3) ? (F2 - F3) : (F3 - F2);
|
|
UINT freq_diff_3 = (F1 > F3) ? (F1 - F3) : (F3 - F1);
|
|
#endif
|
|
UINT freq_diff_1 = (F1 - F2);
|
|
UINT freq_diff_2 = (F2 - F3);
|
|
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck freq_diff_min=%d freq_diff_max=%d \n", freq_diff_min, freq_diff_max));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck dfs_stg3, dff_1=%d, dff_2=%d \n", freq_diff_1, freq_diff_2));
|
|
|
|
|
|
if( (freq_diff_1 >= freq_diff_min) && (freq_diff_1 <= freq_diff_max) && (freq_diff_2 >= freq_diff_min) && (freq_diff_2 <= freq_diff_max) )
|
|
return TRUE; /* S/W check success */
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, F1=%d, F2=%d, F3=%d\n", F1, F2, F3));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("stg3 fail on S/W Freq confirmed\n"));
|
|
return FALSE; /* S/W check fail */
|
|
}
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<---StagerRadarCheck()\n"));
|
|
}
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Recheck DFS radar of chrp type.
|
|
Arguments:
|
|
pAdapter Pointer to our adapter
|
|
dfs_channel DFS detect channel
|
|
Return Value:
|
|
"TRUE" if check pass, "FALSE" otherwise.
|
|
Note:
|
|
==========================================================================
|
|
*/
|
|
static BOOLEAN ChirpRadarCheck(IN PRTMP_ADAPTER pAd)
|
|
{
|
|
UINT32 CurrentTime, delta;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/*
|
|
Ignore the tiny chance of the wrape around false detection: (12sec/50min)
|
|
ps. 32bit 1us counter ~= 50mins
|
|
*/
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
RTMP_IO_READ32(pAd, PBF_LIFE_TIMER, &CurrentTime);
|
|
delta = CurrentTime - pRadarDetect->TimeStamp;
|
|
pRadarDetect->TimeStamp = CurrentTime;
|
|
|
|
/* ChirpCheck = 0 means the very first detection since start up*/
|
|
if (pRadarDetect->ChirpCheck++ == 0)
|
|
return FALSE;
|
|
|
|
if (delta <= (12*(1<<20))) /* 12 sec */
|
|
{
|
|
if (pRadarDetect->ChirpCheck >= 2)
|
|
{
|
|
/* Anouce the radar on any mutiple detection within 12 sec*/
|
|
DBGPRINT(RT_DEBUG_TRACE, ("ChirpRadarCheck OK.\n"));
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("ChirpRadarCheck failed, discard previous detection.\n"));
|
|
pRadarDetect->ChirpCheck = 1;
|
|
return FALSE;
|
|
}
|
|
/* default */
|
|
return FALSE;
|
|
}
|
|
|
|
static VOID DfsCheckBusyIdle(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
int busy_delta, idle_delta;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
RTMP_IO_READ32(pAd, CH_IDLE_STA, &pRadarDetect->idle_time);
|
|
pRadarDetect->busy_time = AsicGetChBusyCnt(pAd, 0);
|
|
|
|
/*ch_busy_sta_index begining at 0.*/
|
|
busy_delta = pRadarDetect->busy_time - pRadarDetect->ch_busy_sta[pRadarDetect->ch_busy_sta_index];
|
|
idle_delta = pRadarDetect->idle_time - pRadarDetect->ch_idle_sta[pRadarDetect->ch_busy_sta_index];
|
|
|
|
if (busy_delta < 0)
|
|
{
|
|
busy_delta = ~busy_delta;
|
|
busy_delta = (busy_delta >> CH_BUSY_SAMPLE_POWER);
|
|
busy_delta = ~busy_delta;
|
|
}
|
|
else
|
|
busy_delta = busy_delta >> CH_BUSY_SAMPLE_POWER;
|
|
|
|
if (idle_delta < 0)
|
|
{
|
|
idle_delta = ~idle_delta;
|
|
idle_delta = idle_delta >> CH_BUSY_SAMPLE_POWER;
|
|
idle_delta = ~idle_delta;
|
|
}
|
|
else
|
|
idle_delta = idle_delta >> CH_BUSY_SAMPLE_POWER;
|
|
|
|
pRadarDetect->ch_busy_sum += busy_delta;
|
|
pRadarDetect->ch_idle_sum += idle_delta;
|
|
|
|
/* not sure if this is necessary??*/
|
|
if (pRadarDetect->ch_busy_sum < 0)
|
|
pRadarDetect->ch_busy_sum = 0;
|
|
if (pRadarDetect->ch_idle_sum < 0)
|
|
pRadarDetect->ch_idle_sum = 0;
|
|
|
|
pRadarDetect->ch_busy_sta[pRadarDetect->ch_busy_sta_index] = pRadarDetect->busy_time;
|
|
pRadarDetect->ch_idle_sta[pRadarDetect->ch_busy_sta_index] = pRadarDetect->idle_time;
|
|
|
|
pRadarDetect->ch_busy_sta_index++;
|
|
pRadarDetect->ch_busy_sta_index &= CH_BUSY_MASK;
|
|
|
|
if ((pRadarDetect->ch_idle_sum >> pRadarDetect->ch_busy_idle_ratio) < pRadarDetect->ch_busy_sum )
|
|
{
|
|
|
|
if (!(pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_BUSY))
|
|
pRadarDetect->ch_busy = 1;
|
|
}
|
|
else
|
|
{
|
|
if (!(pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_RSSI))
|
|
{
|
|
if ((pAd->ApCfg.RssiSample.AvgRssi[0]) && (pAd->ApCfg.RssiSample.AvgRssi[0] > pRadarDetect->DfsRssiHigh))
|
|
pRadarDetect->ch_busy = 2;
|
|
else if ((pAd->ApCfg.RssiSample.AvgRssi[0]) && (pAd->ApCfg.RssiSample.AvgRssi[0] < pRadarDetect->DfsRssiLow))
|
|
pRadarDetect->ch_busy = 3;
|
|
else
|
|
pRadarDetect->ch_busy = 0;
|
|
}
|
|
}
|
|
|
|
if (pRadarDetect->print_ch_busy_sta)
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%d %d %d %d\n", pRadarDetect->ch_idle_sum, pRadarDetect->ch_busy_sum, pAd->ApCfg.RssiSample.AvgRssi[0], pRadarDetect->ch_busy));
|
|
|
|
}
|
|
|
|
static BOOLEAN DfsChannelCheck(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DfsChannel)
|
|
{
|
|
pNewDFSTable pDFSTable;
|
|
UINT8 i;
|
|
UINT32 T, W, W2, B;
|
|
BOOLEAN radarDeclared = 0;
|
|
|
|
T = W = W2 = B = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("DFS HW check channel = 0x%x\n", DfsChannel));
|
|
/*Select the DFS table based on radar country region*/
|
|
if (pAd->CommonCfg.RDDurRegion == FCC)
|
|
pDFSTable = &NewDFSTable1[0];
|
|
else if (pAd->CommonCfg.RDDurRegion == CE)
|
|
{
|
|
pDFSTable = &NewDFSTable1[1];
|
|
}
|
|
else /* Japan*/
|
|
{
|
|
if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64))
|
|
{
|
|
pDFSTable = &NewDFSTable1[3];
|
|
}
|
|
else
|
|
{
|
|
pDFSTable = &NewDFSTable1[2];
|
|
}
|
|
}
|
|
/*check which channe(0~3) is detecting radar signals*/
|
|
for (i = 0; i < pAd->chipCap.DfsEngineNum; i++)
|
|
{
|
|
|
|
if (DfsChannel & (0x1 << i))
|
|
{
|
|
DfsHwDetectionGetPulseInfo(pAd, i, &T, &W, &W2, &B);
|
|
|
|
#ifdef MT76x0
|
|
if (IS_MT7610E(pAd) == FALSE)
|
|
#endif
|
|
if (DfsSwCheckOnHwDetection(pAd, pDFSTable, i, T, W) == FALSE)
|
|
continue;
|
|
|
|
DBGPRINT(RT_DEBUG_OFF, ("T = %u, W= %u detected by ch %d\n", T, W, i));
|
|
|
|
/*set this variable to 1 for announcing that we find the radar signals.*/
|
|
radarDeclared = 1;
|
|
|
|
if ( ((i == 3) || (i == 2)) && (pDFSTable->entry[i].mode != 0) )
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Burst = %u(0x%x)\n", B, B));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("The second Width = %u(0x%x)\n", W2, W2));
|
|
}
|
|
}
|
|
}
|
|
return radarDeclared;
|
|
}
|
|
|
|
|
|
#ifdef MT76x0
|
|
static BOOLEAN MT7650DfsEventDataFetch(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PRADAR_DETECT_STRUCT pRadarDetect,
|
|
OUT PDFS_EVENT pDfsEvent)
|
|
{
|
|
UINT8 idx;
|
|
UINT32 EventBuff[DFS_EVENT_SIZE] = {0};
|
|
UINT32 bbp_val;
|
|
|
|
/* Read a event from event buffer */
|
|
for (idx = 0; idx < DFS_EVENT_SIZE; idx++)
|
|
{
|
|
/*
|
|
1st read - DFS_R37[31] = 0(engine0)/1(engine2), if no events ==> DFS_R37[31:0] = 0xFFFF_FFFF
|
|
2nd read - DFS_R37[21:0] = pulse time
|
|
3rd read - DFS_R37[25:16] = phase, DFS_R37[11:0] = pulse width
|
|
4th read - DFS_R37[21:16] = power stable counter
|
|
DFS_R37[12:0] = current power
|
|
*/
|
|
RTMP_BBP_IO_READ32(pAd, DFS_R37, &bbp_val);
|
|
EventBuff[idx] = bbp_val;
|
|
}
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT)
|
|
{
|
|
MT7650_DFS_EVENT_BUFF_PRINT(0, EventBuff, DFS_EVENT_SIZE);
|
|
}
|
|
|
|
/* No events */
|
|
if (EventBuff[0] == 0xFFFFFFFF)
|
|
return FALSE;
|
|
|
|
/*
|
|
Total 64 events: 32 events for engine0 and 32 event2 for engine2.
|
|
*/
|
|
pDfsEvent->EngineId = (EventBuff[0] & 0x80000000) ? 2:0;
|
|
pDfsEvent->TimeStamp = EventBuff[1] & 0x003FFFFF;
|
|
pDfsEvent->Width = EventBuff[2] & 0x0FFF;
|
|
pDfsEvent->phase = (EventBuff[2] >> 16) & 0x03FF;
|
|
pDfsEvent->power_stable_counter = (EventBuff[3] >> 16) & 0x003F;
|
|
pDfsEvent->current_power = EventBuff[3] & 0x1FFF;
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("EngineId = %d\n", pDfsEvent->EngineId));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("TimeStamp = 0x%x\n", pDfsEvent->TimeStamp));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Width = 0x%x\n", pDfsEvent->Width));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("phase = 0x%x\n", pDfsEvent->phase));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("power_stable_counter = 0x%x\n", pDfsEvent->power_stable_counter));
|
|
DBGPRINT(RT_DEBUG_TRACE, ("current_power = 0x%x\n\n", pDfsEvent->current_power));
|
|
}
|
|
|
|
/* Check if event is valid */
|
|
if (!DFS_EVENT_SANITY_CHECK(pAd, *pDfsEvent))
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: This event is invalid\n", __FUNCTION__));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#else
|
|
static BOOLEAN DfsEventDataFetch(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PRADAR_DETECT_STRUCT pRadarDetect,
|
|
OUT PDFS_EVENT pDfsEvent)
|
|
{
|
|
UINT8 idx;
|
|
UINT8 EventBuff[DFS_EVENT_SIZE] = {0};
|
|
UINT32 bbp_val;
|
|
|
|
/* Read a event from event buffer */
|
|
for (idx = 0; idx < DFS_EVENT_SIZE; idx++)
|
|
{
|
|
RTMP_BBP_IO_READ32(pAd, BBP_R127, &bbp_val);
|
|
EventBuff[idx] = bbp_val;
|
|
}
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT)
|
|
{
|
|
DFS_EVENT_BUFF_PRINT(0, EventBuff, DFS_EVENT_SIZE);
|
|
}
|
|
|
|
pDfsEvent->EngineId = EventBuff[0];
|
|
if (pDfsEvent->EngineId == 0xff) /* end of event */
|
|
return FALSE;
|
|
|
|
pDfsEvent->TimeStamp = EventBuff[1];
|
|
pDfsEvent->TimeStamp |= (EventBuff[2] << 8);
|
|
pDfsEvent->TimeStamp |= (EventBuff[3] << 16);
|
|
|
|
pDfsEvent->Width = EventBuff[4];
|
|
pDfsEvent->Width |= (EventBuff[5] << 8);
|
|
|
|
/* Check if event is valid */
|
|
if (!DFS_EVENT_SANITY_CHECK(pAd, *pDfsEvent))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
#endif /* MT76x0 */
|
|
|
|
VOID NewRadarDetectionProgram(PRTMP_ADAPTER pAd, pNewDFSTable pDFSTable)
|
|
{
|
|
UINT8 idx, TalbeIdx;
|
|
UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/*
|
|
Set bDfsInit to "FALSE" to prevent collision with NewTimerCB
|
|
*/
|
|
#endif /* RELEASE_EXCLUDE */
|
|
pRadarDetect->bDfsInit = FALSE;
|
|
|
|
/* Get Table index*/
|
|
for (TalbeIdx = 0; !((1<<TalbeIdx) & pDFSTable->type); TalbeIdx++)
|
|
{
|
|
if (TalbeIdx > MAX_RD_REGION)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("Table index out of range.\n"));
|
|
return;
|
|
}
|
|
}
|
|
|
|
for(idx = 0; idx<DfsEngineNum; idx++)
|
|
{
|
|
if ((pRadarDetect->DFSParamFromConfig & (0x1<<idx)) && pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].valid)
|
|
{
|
|
pDFSTable->entry[idx].mode = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].mode;
|
|
pDFSTable->entry[idx].avgLen = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].avgLen;
|
|
pDFSTable->entry[idx].ELow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].ELow;
|
|
pDFSTable->entry[idx].EHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EHigh;
|
|
pDFSTable->entry[idx].WLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WLow;
|
|
pDFSTable->entry[idx].WHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WHigh;
|
|
pDFSTable->entry[idx].EpsilonW = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonW;
|
|
pDFSTable->entry[idx].TLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].TLow;
|
|
pDFSTable->entry[idx].THigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].THigh;
|
|
pDFSTable->entry[idx].EpsilonT = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonT;
|
|
pDFSTable->entry[idx].BLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BLow;
|
|
pDFSTable->entry[idx].BHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BHigh;
|
|
pDFSTable->entry[idx].EventExpiration= pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EventExpiration;
|
|
pDFSTable->entry[idx].PwrJump= pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].PwrJump;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("TalbeIdx = %d; idx = %d; DFSParam = %2d; %3d; %3d; %3d; %3d; %4d; %3d; %6lu; %7lu; %4d; %2lu; %2lu, %d, 0x%04x\n", TalbeIdx, idx,
|
|
pDFSTable->entry[idx].mode, pDFSTable->entry[idx].avgLen, pDFSTable->entry[idx].ELow,
|
|
pDFSTable->entry[idx].EHigh, pDFSTable->entry[idx].WLow, pDFSTable->entry[idx].WHigh,
|
|
pDFSTable->entry[idx].EpsilonW, pDFSTable->entry[idx].TLow, pDFSTable->entry[idx].THigh,
|
|
pDFSTable->entry[idx].EpsilonT, pDFSTable->entry[idx].BLow, pDFSTable->entry[idx].BHigh,
|
|
pDFSTable->entry[idx].EventExpiration, pDFSTable->entry[idx].PwrJump));
|
|
}
|
|
}
|
|
|
|
/* Symmetric round*/
|
|
if(pRadarDetect->SymRoundFromCfg != 0)
|
|
{
|
|
pDfsProgramParam->Symmetric_Round = pRadarDetect->SymRoundFromCfg;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Symmetric_Round = %d\n", pDfsProgramParam->Symmetric_Round));
|
|
}
|
|
|
|
/* BusyIdleRatio*/
|
|
if(pRadarDetect->BusyIdleFromCfg != 0)
|
|
{
|
|
pRadarDetect->ch_busy_idle_ratio = pRadarDetect->BusyIdleFromCfg;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("ch_busy_idle_ratio = %d\n", pRadarDetect->ch_busy_idle_ratio));
|
|
}
|
|
/* DfsRssiHigh*/
|
|
if(pRadarDetect->DfsRssiHighFromCfg != 0)
|
|
{
|
|
pRadarDetect->DfsRssiHigh = pRadarDetect->DfsRssiHighFromCfg;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiHigh = %d\n", pRadarDetect->DfsRssiHigh));
|
|
}
|
|
/* DfsRssiLow*/
|
|
if(pRadarDetect->DfsRssiLowFromCfg != 0)
|
|
{
|
|
pRadarDetect->DfsRssiLow = pRadarDetect->DfsRssiLowFromCfg;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiLow = %d\n", pRadarDetect->DfsRssiLow));
|
|
}
|
|
|
|
/*pRadarDetect->MCURadarRegion = pAd->CommonCfg.RDDurRegion;*/
|
|
pRadarDetect->MCURadarRegion = pDFSTable->type;
|
|
|
|
DfsProgramBbpValues(pAd, pDFSTable);
|
|
|
|
pRadarDetect->bDfsInit = TRUE;
|
|
|
|
}
|
|
|
|
BOOLEAN DfsSwCheckOnHwDetection(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN pNewDFSTable pDFSTable,
|
|
IN UINT8 DfsChannel,
|
|
IN ULONG RadarPeriod,
|
|
IN ULONG RadarWidth)
|
|
{
|
|
BOOLEAN bRadarCheck = TRUE;
|
|
#ifdef RELEASE_EXCLUDE
|
|
/*
|
|
if the dfs tables are chaned, these check should also be change accordingly.
|
|
*/
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if (!RadarPeriod || !RadarWidth)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Block eception on zero RadarPeriod or RadarWidth\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
if (pDFSTable->type == NEW_DFS_JAP)
|
|
{
|
|
/* Double check on pusle Width and Period*/
|
|
if (DfsChannel < 3)
|
|
{
|
|
/*check short pulse*/
|
|
if (RadarWidth < 375)
|
|
{
|
|
/* block the illegal period */
|
|
if ((RadarPeriod < 2800) ||
|
|
(RadarPeriod > 5000 && RadarPeriod < 6400) ||
|
|
(RadarPeriod > 6800 && RadarPeriod < 27560)||
|
|
(RadarPeriod > 27960 && RadarPeriod < 28360) ||
|
|
(RadarPeriod > 28700 && RadarPeriod < 79900) ||
|
|
(RadarPeriod > 80100))
|
|
{
|
|
/*(0~140), (250~320us), (340~1378us), (1398~1418), (1435~3995us) and (4005us~) according to the spec*/
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth));
|
|
bRadarCheck = FALSE;
|
|
}
|
|
}
|
|
else if (RadarWidth > 375)
|
|
{
|
|
if ((RadarPeriod<3500) || (RadarPeriod>10400))
|
|
{
|
|
/* block the illegal period */
|
|
/*(0~175) and (520us~) according to the spec*/
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth));
|
|
bRadarCheck = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (DfsChannel == 3)
|
|
{
|
|
bRadarCheck = ChirpRadarCheck(pAd);
|
|
}
|
|
}
|
|
else if (pDFSTable->type == NEW_DFS_EU)
|
|
{
|
|
/* Double check on pusle Width and Period*/
|
|
if (DfsChannel < 3)
|
|
{
|
|
|
|
/* block the illegal period */
|
|
if ((RadarPeriod < 4900) ||
|
|
(RadarPeriod > 8800 && RadarPeriod < 12400) ||
|
|
(RadarPeriod > 14000 && RadarPeriod < 15800) ||
|
|
(RadarPeriod > 100100))
|
|
{
|
|
/*(0~245), (440~620us), (5005us~) according to the spec*/
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth));
|
|
bRadarCheck = FALSE;
|
|
}
|
|
}
|
|
else if (DfsChannel == 4) /* to do: check dfs mode 8or9*/
|
|
{
|
|
if (StagerRadarCheck(pAd, DfsChannel) == FALSE)
|
|
bRadarCheck = FALSE;
|
|
}
|
|
}
|
|
else if (pDFSTable->type == FCC)
|
|
{
|
|
/* Double check on pusle Width and Period*/
|
|
if (DfsChannel < 3)
|
|
{
|
|
if (RadarWidth < 950)
|
|
{
|
|
/* block the illegal period */
|
|
if ((RadarPeriod < 2800) ||
|
|
(RadarPeriod > 10100 && RadarPeriod < 28360) || (RadarPeriod > 28700))
|
|
{
|
|
/*(0~140), (505~1418), (1435us~) according to the spec*/
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth));
|
|
bRadarCheck = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((RadarPeriod<2800) ||
|
|
(RadarPeriod > 10200 && RadarPeriod < 19800) ||
|
|
(RadarPeriod>40200))
|
|
{
|
|
/* block the illegal period */
|
|
/*(0~140) and (510us~990), (2010us~) according to the spec*/
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth));
|
|
bRadarCheck = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (DfsChannel == 3)
|
|
{
|
|
bRadarCheck = ChirpRadarCheck(pAd);
|
|
}
|
|
}
|
|
|
|
return bRadarCheck;
|
|
}
|
|
|
|
static VOID ChannelSelectOnRadarDetection(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
UINT i;
|
|
|
|
if (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)
|
|
return;
|
|
|
|
#ifdef DOT11_VHT_AC
|
|
if (pAd->CommonCfg.BBPCurrentBW == BW_80)
|
|
{
|
|
for (i=0; i<pAd->ChannelListNum; i++)
|
|
{
|
|
if ((pAd->CommonCfg.Channel >= 52 && pAd->CommonCfg.Channel <= 64) &&
|
|
(pAd->ChannelList[i].Channel >= 52 && pAd->ChannelList[i].Channel <= 64))
|
|
{
|
|
pAd->ChannelList[i].RemainingTimeForUse = 1800;
|
|
}
|
|
else if ((pAd->CommonCfg.Channel >= 100 && pAd->CommonCfg.Channel <= 112) &&
|
|
(pAd->ChannelList[i].Channel >= 100 && pAd->ChannelList[i].Channel <= 112))
|
|
{
|
|
pAd->ChannelList[i].RemainingTimeForUse = 1800;
|
|
}
|
|
else if ((pAd->CommonCfg.Channel >= 116 && pAd->CommonCfg.Channel <= 128) &&
|
|
(pAd->ChannelList[i].Channel >= 116 && pAd->ChannelList[i].Channel <= 128))
|
|
{
|
|
pAd->ChannelList[i].RemainingTimeForUse = 1800;
|
|
}
|
|
}
|
|
}
|
|
#endif /* DOT11_VHT_AC */
|
|
|
|
for (i=0; i<pAd->ChannelListNum; i++)
|
|
{
|
|
if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel)
|
|
{
|
|
if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
|
|
{
|
|
if ((pAd->ChannelList[i].Channel >> 2) & 1)
|
|
{
|
|
if ((pAd->ChannelList[i+1].Channel - pAd->ChannelList[i].Channel) == 4 )
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Find extend channel = %u\n", pAd->ChannelList[i+1].Channel));
|
|
pAd->ChannelList[i+1].RemainingTimeForUse = 1800;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((pAd->ChannelList[i].Channel - pAd->ChannelList[i-1].Channel) == 4 )
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Find extend channel = %u\n", pAd->ChannelList[i-1].Channel));
|
|
pAd->ChannelList[i-1].RemainingTimeForUse = 1800;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_TRACE, ("BW is not 40.\n"));
|
|
|
|
pAd->ChannelList[i].RemainingTimeForUse = 1800;/*30 min = 1800 sec*/
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*when find an radar, the ChMovingTime will be set to announce how many seconds to sending software radar detection time.*/
|
|
if ((pAd->CommonCfg.RDDurRegion == CE) && RESTRICTION_BAND_1(pAd))
|
|
pAd->Dot11_H.ChMovingTime = 605;
|
|
else
|
|
pAd->Dot11_H.ChMovingTime = 65;
|
|
|
|
/*if the Radar country region is JAP, we need find a new clear channel */
|
|
if (pAd->CommonCfg.RDDurRegion == JAP_W56)
|
|
{
|
|
for (i = 0; i < pAd->ChannelListNum ; i++)
|
|
{
|
|
pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE);
|
|
if ((pAd->CommonCfg.Channel >= 100) && (pAd->CommonCfg.Channel <= 140))
|
|
break;
|
|
}
|
|
}
|
|
else if (pAd->CommonCfg.RDDurRegion == JAP_W53)
|
|
{
|
|
for (i = 0; i < pAd->ChannelListNum ; i++)
|
|
{
|
|
pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE);
|
|
if ((pAd->CommonCfg.Channel >= 36) && (pAd->CommonCfg.Channel <= 60))
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE);
|
|
|
|
#ifdef DOT11_N_SUPPORT
|
|
N_ChannelCheck(pAd);
|
|
#endif /* DOT11_N_SUPPORT */
|
|
|
|
/*ApSelectChannelCheck(pAd);*/
|
|
if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE)
|
|
{
|
|
pAd->Dot11_H.RDMode = RD_SWITCHING_MODE;
|
|
/* Prepare a count-down for channel switching */
|
|
pAd->Dot11_H.CSCount = 0;
|
|
}
|
|
else if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE)
|
|
{
|
|
pAd->Dot11_H.RDMode = RD_SWITCHING_MODE;
|
|
/*set this flag to 1 and the AP will restart to switch into new channel */
|
|
pRadarDetect->DFSAPRestart = 1;
|
|
schedule_dfs_task(pAd);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error! Unexpected radar state.\n", __FUNCTION__));
|
|
}
|
|
pRadarDetect->radarDeclared = 0;
|
|
}
|
|
|
|
static BOOLEAN DfsEventDrop(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PDFS_EVENT pDfsEvent)
|
|
{
|
|
UINT32 TimeDiff = 0; /* unit: 50ns */
|
|
UINT16 PreEnvtWidth = 0;
|
|
BOOLEAN RetVal = FALSE;
|
|
PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
|
|
PDFS_EVENT pPreDfsEvent = &pDfsSwParam->PreDfsEvent;
|
|
|
|
if (pDfsEvent->EngineId != pPreDfsEvent->EngineId)
|
|
{
|
|
/* update prevoius event record then leave */
|
|
NdisCopyMemory(pPreDfsEvent, pDfsEvent, DFS_EVENT_SIZE);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pDfsEvent->EngineId == 0x01 || pDfsEvent->EngineId == 0x02)
|
|
{
|
|
if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
|
|
{
|
|
TimeDiff = ((pDfsEvent->TimeStamp - pPreDfsEvent->TimeStamp) >> 1); /* 25ns to 50ns*/
|
|
PreEnvtWidth = pPreDfsEvent->Width >> 1;
|
|
}
|
|
else
|
|
{
|
|
TimeDiff = (pDfsEvent->TimeStamp - pPreDfsEvent->TimeStamp);
|
|
PreEnvtWidth = pPreDfsEvent->Width;
|
|
}
|
|
|
|
if (TimeDiff < pDfsSwParam->EvtDropAdjTime &&
|
|
PreEnvtWidth >= 200)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s(): EngineId = %x, Width = %u, TimeStamp = %u\n",
|
|
__FUNCTION__,
|
|
pDfsEvent->EngineId,
|
|
pDfsEvent->Width,
|
|
pDfsEvent->TimeStamp));
|
|
RetVal = TRUE;
|
|
}
|
|
}
|
|
|
|
/* update prevoius event record */
|
|
NdisCopyMemory(pPreDfsEvent, pDfsEvent, DFS_EVENT_SIZE);
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
static void dfs_sw_init(PRTMP_ADAPTER pAd)
|
|
{
|
|
int j, k;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
|
|
|
|
pDfsSwParam->dfs_check_loop = DFS_SW_RADAR_CHECK_LOOP;
|
|
pDfsSwParam->dfs_width_diff_ch1_Shift = DFS_SW_RADAR_CH1_SHIFT;
|
|
pDfsSwParam->dfs_width_diff_ch2_Shift = DFS_SW_RADAR_CH2_SHIFT;
|
|
pDfsSwParam->PreDfsEvent.EngineId = 0xff;
|
|
pDfsSwParam->EvtDropAdjTime = 2000;
|
|
|
|
pDfsSwParam->dfs_width_ch0_err_L = DFS_SW_RADAR_CH0_ERR;
|
|
if (pAd->CommonCfg.RDDurRegion == CE)
|
|
pDfsSwParam->dfs_period_err = (DFS_SW_RADAR_PERIOD_ERR << 2);
|
|
else
|
|
pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR;
|
|
if (pAd->CommonCfg.RDDurRegion == CE)
|
|
{
|
|
pDfsSwParam->dfs_width_ch0_err_H = CE_STAGGERED_RADAR_CH0_H_ERR;
|
|
pDfsSwParam->dfs_declare_thres = CE_STAGGERED_RADAR_DECLARE_THRES;
|
|
pDfsSwParam->dfs_max_period = CE_STAGGERED_RADAR_PERIOD_MAX;
|
|
}
|
|
else
|
|
{
|
|
if (pAd->CommonCfg.RDDurRegion == FCC)
|
|
pDfsSwParam->dfs_max_period = FCC_RADAR_PERIOD_MAX;
|
|
else if (pAd->CommonCfg.RDDurRegion == JAP)
|
|
pDfsSwParam->dfs_max_period = JAP_RADAR_PERIOD_MAX;
|
|
}
|
|
|
|
pDfsSwParam->dfs_check_loop = DFS_SW_RADAR_CHECK_LOOP;
|
|
pDfsSwParam->dfs_width_diff_ch1_Shift = DFS_SW_RADAR_CH1_SHIFT;
|
|
pDfsSwParam->dfs_width_diff_ch2_Shift = DFS_SW_RADAR_CH2_SHIFT;
|
|
pDfsSwParam->dfs_width_ch0_err_L = DFS_SW_RADAR_CH0_ERR;
|
|
if (pAd->CommonCfg.RDDurRegion == CE)
|
|
pDfsSwParam->dfs_period_err = (DFS_SW_RADAR_PERIOD_ERR << 2);
|
|
else
|
|
pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR;
|
|
|
|
if (pAd->CommonCfg.RDDurRegion == CE)
|
|
{
|
|
pDfsSwParam->dfs_width_ch0_err_H = CE_STAGGERED_RADAR_CH0_H_ERR;
|
|
pDfsSwParam->dfs_declare_thres = CE_STAGGERED_RADAR_DECLARE_THRES;
|
|
pDfsSwParam->dfs_max_period = CE_STAGGERED_RADAR_PERIOD_MAX;
|
|
}
|
|
else
|
|
{
|
|
if (pAd->CommonCfg.RDDurRegion == FCC)
|
|
pDfsSwParam->dfs_max_period = FCC_RADAR_PERIOD_MAX;
|
|
else if (pAd->CommonCfg.RDDurRegion == JAP)
|
|
pDfsSwParam->dfs_max_period = JAP_RADAR_PERIOD_MAX;
|
|
}
|
|
|
|
if (pRadarDetect->use_tasklet)
|
|
pRadarDetect->PollTime = NEW_DFS_CHECK_TIME_TASKLET;
|
|
else
|
|
pRadarDetect->PollTime = NEW_DFS_CHECK_TIME;
|
|
|
|
for (k = 0; k < pAd->chipCap.DfsEngineNum; k++)
|
|
{
|
|
for (j = 0; j < NEW_DFS_DBG_PORT_ENT_NUM; j++)
|
|
{
|
|
pDfsSwParam->DFS_W[k][j].start_idx = 0xffff;
|
|
}
|
|
}
|
|
|
|
for (k = 0; k < pAd->chipCap.DfsEngineNum; k++)
|
|
{
|
|
pDfsSwParam->sw_idx[k] = NEW_DFS_DBG_PORT_ENT_NUM - 1;
|
|
pDfsSwParam->hw_idx[k] = 0;
|
|
}
|
|
|
|
NdisZeroMemory(pDfsSwParam->DFS_T, sizeof(pDfsSwParam->DFS_T));
|
|
NdisZeroMemory(pDfsSwParam->DFS_W, sizeof(pDfsSwParam->DFS_W));
|
|
}
|
|
|
|
void modify_table1(PRTMP_ADAPTER pAd, ULONG idx, ULONG value)
|
|
{
|
|
pNewDFSTable pDFSTable;
|
|
ULONG x, y;
|
|
UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
|
|
|
|
if (pAd->CommonCfg.RDDurRegion == FCC)
|
|
pDFSTable = &NewDFSTable1[0];
|
|
else if (pAd->CommonCfg.RDDurRegion == CE)
|
|
{
|
|
pDFSTable = &NewDFSTable1[1];
|
|
}
|
|
else /* Japan*/
|
|
{
|
|
if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64))
|
|
{
|
|
pDFSTable = &NewDFSTable1[3];
|
|
}
|
|
else
|
|
{
|
|
pDFSTable = &NewDFSTable1[2];
|
|
}
|
|
}
|
|
|
|
#ifdef MT76x0
|
|
if (IS_MT7610E(pAd))
|
|
{
|
|
if (pAd->CommonCfg.RDDurRegion == CE)
|
|
pDFSTable = &NewDFSTable2[1];
|
|
else
|
|
pDFSTable = &NewDFSTable2[0];
|
|
}
|
|
#endif /* MT76x0 */
|
|
|
|
if (idx == 0)
|
|
{
|
|
pDfsProgramParam->DeltaDelay = value;
|
|
}
|
|
else if (idx <= (DfsEngineNum*16))
|
|
{
|
|
x = idx / 16;
|
|
y = idx % 16;
|
|
pRadarDetect->DFSParamFromConfig = 0; /* to prevent table be loaded from config file again */
|
|
switch (y)
|
|
{
|
|
case 1:
|
|
pDFSTable->entry[x].mode = (UCHAR)value;
|
|
break;
|
|
case 2:
|
|
pDFSTable->entry[x].avgLen = (USHORT)value;
|
|
break;
|
|
case 3:
|
|
pDFSTable->entry[x].ELow = (USHORT)value;
|
|
break;
|
|
|
|
case 4:
|
|
pDFSTable->entry[x].EHigh = (USHORT)value;
|
|
break;
|
|
|
|
case 5:
|
|
pDFSTable->entry[x].WLow = (USHORT)value;
|
|
break;
|
|
|
|
case 6:
|
|
pDFSTable->entry[x].WHigh = (USHORT)value;
|
|
break;
|
|
|
|
case 7:
|
|
pDFSTable->entry[x].EpsilonW = (UCHAR)value;
|
|
break;
|
|
|
|
case 8:
|
|
pDFSTable->entry[x].TLow = (ULONG)value;
|
|
break;
|
|
|
|
case 9:
|
|
pDFSTable->entry[x].THigh = (ULONG)value;
|
|
break;
|
|
|
|
case 0xa:
|
|
pDFSTable->entry[x].EpsilonT = (UCHAR)value;
|
|
break;
|
|
|
|
case 0xb:
|
|
pDFSTable->entry[x].BLow= (ULONG)value;
|
|
break;
|
|
|
|
case 0xc:
|
|
pDFSTable->entry[x].BHigh = (ULONG)value;
|
|
break;
|
|
|
|
case 0xd:
|
|
pDFSTable->entry[x].EventExpiration= (UINT32)value;
|
|
break;
|
|
|
|
case 0xe:
|
|
pDFSTable->entry[x].PwrJump= (UINT16)value;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if (idx == (DfsEngineNum*16 +1))
|
|
{
|
|
pDfsProgramParam->Symmetric_Round = (UCHAR)value;
|
|
}
|
|
else if (idx == (DfsEngineNum*16 +2))
|
|
{
|
|
pDfsProgramParam->VGA_Mask = (UCHAR)value;
|
|
}
|
|
else if (idx == (DfsEngineNum*16 +3))
|
|
{
|
|
pDfsProgramParam->Packet_End_Mask = (UCHAR)value;
|
|
}
|
|
else if (idx == (DfsEngineNum*16 +4))
|
|
{
|
|
pDfsProgramParam->Rx_PE_Mask = (UCHAR)value;
|
|
}
|
|
|
|
printk("Delta_Delay(0) = %d\n", pDfsProgramParam->DeltaDelay);
|
|
|
|
for (x = 0; x < DfsEngineNum; x++)
|
|
{
|
|
printk("Channel %lu\n", x);
|
|
printk("\t\tmode(%02lu)=%d, M(%02lu)=%03d, EL(%02lu)=%03d EH(%02lu)=%03d, WL(%02lu)=%03d WH(%02lu)=%04d, eW(%02lu)=%02d\n"
|
|
"\t\tTL(%02lu)=%05u TH(%02lu)=%06u, eT(%02lu)=%03d, BL(%02lu)=%u, BH(%02lu)=%u\n"
|
|
"\t\tEE(%02lu) = %06u, PJ(%02lu) = 0x%02x\n",
|
|
(x*16+0x1), (unsigned int)pDFSTable->entry[x].mode,
|
|
(x*16+0x2), (unsigned int)pDFSTable->entry[x].avgLen,
|
|
(x*16+0x3), (unsigned int)pDFSTable->entry[x].ELow,
|
|
(x*16+0x4), (unsigned int)pDFSTable->entry[x].EHigh,
|
|
(x*16+0x5), (unsigned int)pDFSTable->entry[x].WLow,
|
|
(x*16+0x6), (unsigned int)pDFSTable->entry[x].WHigh,
|
|
(x*16+0x7), (unsigned int)pDFSTable->entry[x].EpsilonW,
|
|
(x*16+0x8), (unsigned int)pDFSTable->entry[x].TLow,
|
|
(x*16+0x9), (unsigned int)pDFSTable->entry[x].THigh,
|
|
(x*16+0xa), (unsigned int)pDFSTable->entry[x].EpsilonT,
|
|
(x*16+0xb), (unsigned int)pDFSTable->entry[x].BLow,
|
|
(x*16+0xc), (unsigned int)pDFSTable->entry[x].BHigh,
|
|
(x*16+0xd), (unsigned int)pDFSTable->entry[x].EventExpiration,
|
|
(x*16+0xe), (unsigned int)pDFSTable->entry[x].PwrJump );
|
|
}
|
|
|
|
printk("Symmetric_Round(%02d) = %d\n", (DfsEngineNum*16 +1), pDfsProgramParam->Symmetric_Round);
|
|
printk("VGA_Mask(%02d) = %d\n", (DfsEngineNum*16 +2), pDfsProgramParam->VGA_Mask);
|
|
printk("Packet_End_Mask(%02d) = %d\n", (DfsEngineNum*16 +3), pDfsProgramParam->Packet_End_Mask);
|
|
printk("Rx_PE_Mask(%02d) = %d\n", (DfsEngineNum*16 +4), pDfsProgramParam->Rx_PE_Mask);
|
|
|
|
}
|
|
|
|
|
|
void modify_table2(PRTMP_ADAPTER pAd, ULONG idx, ULONG value)
|
|
{
|
|
pNewDFSValidRadar pDFSValidRadar;
|
|
ULONG x, y;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
idx--;
|
|
|
|
x = idx / 17;
|
|
y = idx % 17;
|
|
|
|
pDFSValidRadar = &NewDFSValidTable[0];
|
|
|
|
while (pDFSValidRadar->type != NEW_DFS_END)
|
|
{
|
|
if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion)
|
|
{
|
|
if (x == 0)
|
|
break;
|
|
else
|
|
{
|
|
x--;
|
|
pDFSValidRadar++;
|
|
}
|
|
}
|
|
else
|
|
pDFSValidRadar++;
|
|
}
|
|
|
|
if (pDFSValidRadar->type == NEW_DFS_END)
|
|
{
|
|
printk("idx=%d exceed max number\n", (unsigned int)idx);
|
|
return;
|
|
}
|
|
switch(y)
|
|
{
|
|
case 0:
|
|
pDFSValidRadar->channel = value;
|
|
break;
|
|
case 1:
|
|
pDFSValidRadar->WLow = value;
|
|
break;
|
|
case 2:
|
|
pDFSValidRadar->WHigh = value;
|
|
break;
|
|
case 3:
|
|
pDFSValidRadar->W = value;
|
|
break;
|
|
case 8:
|
|
pDFSValidRadar->WMargin = value;
|
|
break;
|
|
case 9:
|
|
pDFSValidRadar->TLow = value;
|
|
break;
|
|
case 10:
|
|
pDFSValidRadar->THigh = value;
|
|
break;
|
|
case 11:
|
|
pDFSValidRadar->T = value;
|
|
break;
|
|
case 16:
|
|
pDFSValidRadar->TMargin = value;
|
|
break;
|
|
}
|
|
|
|
pDFSValidRadar = &NewDFSValidTable[0];
|
|
while (pDFSValidRadar->type != NEW_DFS_END)
|
|
{
|
|
if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion)
|
|
{
|
|
printk("ch = %x --- ", pDFSValidRadar->channel);
|
|
printk("wl:wh = %d:%d ", pDFSValidRadar->WLow, pDFSValidRadar->WHigh);
|
|
printk("W = %u --- ", pDFSValidRadar->W);
|
|
printk("W Margin = %d\n", pDFSValidRadar->WMargin);
|
|
printk("Tl:Th = %d:%d ", (unsigned int)pDFSValidRadar->TLow, (unsigned int)pDFSValidRadar->THigh);
|
|
printk("T = %lu --- ", pDFSValidRadar->T);
|
|
printk("T Margin = %d\n", pDFSValidRadar->TMargin);
|
|
}
|
|
pDFSValidRadar++;
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef RTMP_MAC_PCI
|
|
VOID NewTimerCB_Radar(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
UCHAR channel=0;
|
|
UCHAR radarDeclared = 0;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) ||
|
|
(pRadarDetect->PollTime == 0))
|
|
return;
|
|
|
|
/* to prevent possible re-entries*/
|
|
pRadarDetect->bDfsInit = FALSE;
|
|
|
|
pRadarDetect->RadarTimeStampLow++;
|
|
|
|
/*511ms*/
|
|
if ((pRadarDetect->RadarTimeStampLow & 0x3f) == 0)
|
|
DfsCheckBusyIdle(pAd);
|
|
#if 1
|
|
#ifdef MT76x0
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* H/W bug, certain traffic may disable radar detection */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if ((pRadarDetect->RadarTimeStampLow % DFS_RESET_INTERVAL) == 0)
|
|
{
|
|
DfsDetectionDisable(pAd);
|
|
DfsDetectionEnable(pAd);
|
|
}
|
|
else if (pRadarDetect->bAdjustDfsAgc == TRUE)
|
|
{
|
|
MT7650_ADJUST_AGC(pAd);
|
|
MT7650_ADJUST_DFS_AGC(pAd);
|
|
DfsDetectionDisable(pAd);
|
|
DfsDetectionEnable(pAd);
|
|
pRadarDetect->bAdjustDfsAgc = FALSE;
|
|
}
|
|
#endif
|
|
#endif
|
|
/*if ((pRadarDetect->McuRadarTick++ >= pRadarDetect->PollTime) &&*/
|
|
if ((pRadarDetect->McuRadarTick++ >= 3) && /* 30ms */
|
|
(!pRadarDetect->ch_busy) &&
|
|
(!pRadarDetect->bDfsSwDisable))
|
|
{
|
|
SwCheckDfsEvent(pAd);
|
|
}
|
|
|
|
/*The following codes is used to check if the hardware find the Radar Signal
|
|
* Read the 0~3 channel which had detected radar signals
|
|
*/
|
|
DfsHwDetectionStatusGet(pAd, &channel);
|
|
|
|
/*Check if any interrupt trigger by Radar Global Status(Radar Signals)*/
|
|
if ((channel & pRadarDetect->EnabledChMask) && (!pRadarDetect->ch_busy))
|
|
{
|
|
radarDeclared = DfsChannelCheck(pAd, channel);
|
|
}
|
|
|
|
/*reset the radar channel for new counting (Write clear) */
|
|
if (channel & pRadarDetect->EnabledChMask)
|
|
DfsResetHwDetectionStatus(pAd);
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE)
|
|
{
|
|
radarDeclared = 1;
|
|
pRadarDetect->McuRadarDebug &= ~RADAR_SIMULATE;
|
|
}
|
|
|
|
if ((radarDeclared || pRadarDetect->radarDeclared) && (pRadarDetect->ch_busy_countdown == -1))
|
|
pRadarDetect->ch_busy_countdown = 20;
|
|
else if(pRadarDetect->ch_busy_countdown >= 0)
|
|
pRadarDetect->ch_busy_countdown--;
|
|
|
|
/*Now, find an Radar signal*/
|
|
if ((!pRadarDetect->ch_busy) && (pRadarDetect->ch_busy_countdown == 0))
|
|
{
|
|
/* Radar found!!!*/
|
|
pRadarDetect->ch_busy_countdown = -1;
|
|
|
|
/*Announce that this channel could not use in 30 minutes if we need find a clear channel*/
|
|
if (!(pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH))
|
|
ChannelSelectOnRadarDetection(pAd);
|
|
else
|
|
pRadarDetect->radarDeclared = 0;
|
|
}
|
|
pRadarDetect->bDfsInit = TRUE;
|
|
}
|
|
|
|
#ifdef MT76x0
|
|
#define DFS_EVENT_DATA_FETCH(__pAd, __pRadarDetect, __DfsEvent) \
|
|
MT7650DfsEventDataFetch(__pAd, __pRadarDetect, &__DfsEvent)
|
|
#else
|
|
#define DFS_EVENT_DATA_FETCH(__pAd, __pRadarDetect, __DfsEvent) \
|
|
DfsEventDataFetch(__pAd, __pRadarDetect, &__DfsEvent)
|
|
#endif /* !MT76x0 */
|
|
|
|
static VOID SwCheckDfsEvent(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
INT k, limit = 64;
|
|
UCHAR id = 0;
|
|
DFS_EVENT DfsEvent;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
|
|
|
|
pRadarDetect->McuRadarTick = 0;
|
|
|
|
/* disable debug mode to read debug port */
|
|
DfsCaptureModeControl(pAd, FALSE, TRUE, FALSE);
|
|
|
|
pDfsSwParam->dfs_w_counter++;
|
|
|
|
for (k = 0; k < limit; k++)
|
|
{
|
|
/* fetch event data */
|
|
if (DFS_EVENT_DATA_FETCH(pAd, pRadarDetect, DfsEvent) == FALSE)
|
|
break;
|
|
|
|
if (DfsEventDrop(pAd, &DfsEvent) == TRUE)
|
|
continue;
|
|
|
|
if (pRadarDetect->use_tasklet)
|
|
{
|
|
id = DfsEvent.EngineId;
|
|
|
|
if (id < pAd->chipCap.DfsEngineNum)
|
|
{
|
|
pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].counter = pDfsSwParam->dfs_w_counter;
|
|
pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].timestamp = DfsEvent.TimeStamp;
|
|
pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].width = DfsEvent.Width;
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT)
|
|
{
|
|
printk("counter = %lu ", pDfsSwParam->dfs_w_counter);
|
|
DFS_EVENT_PRINT(DfsEvent);
|
|
}
|
|
|
|
pDfsSwParam->dfs_w_last_idx[id] = pDfsSwParam->dfs_w_idx[id];
|
|
pDfsSwParam->dfs_w_idx[id]++;
|
|
if (pDfsSwParam->dfs_w_idx[id] >= NEW_DFS_DBG_PORT_ENT_NUM)
|
|
pDfsSwParam->dfs_w_idx[id] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pRadarDetect->use_tasklet)
|
|
{
|
|
/* set hw_idx*/
|
|
pDfsSwParam->hw_idx[0] = pDfsSwParam->dfs_w_idx[0];
|
|
pDfsSwParam->hw_idx[1] = pDfsSwParam->dfs_w_idx[1];
|
|
pDfsSwParam->hw_idx[2] = pDfsSwParam->dfs_w_idx[2];
|
|
pDfsSwParam->hw_idx[3] = pDfsSwParam->dfs_w_idx[3];
|
|
/*dfs tasklet will call SWRadarCheck*/
|
|
schedule_dfs_task(pAd);
|
|
}
|
|
|
|
/* enable debug mode*/
|
|
DfsCaptureModeControl(pAd, TRUE, TRUE, FALSE);
|
|
}
|
|
#endif /* RTMP_MAC_PCI */
|
|
|
|
#ifdef RTMP_MAC_USB
|
|
VOID NewUsbTimerCB_Radar(
|
|
IN PRTMP_ADAPTER pAd)
|
|
|
|
{
|
|
UCHAR channel=0;
|
|
UCHAR radarDeclared = 0;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
|
|
#ifdef CONFIG_ATE
|
|
/* Nothing to do in ATE mode */
|
|
if (ATE_ON(pAd))
|
|
return;
|
|
#endif /* CONFIG_ATE */
|
|
|
|
if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) ||
|
|
(pRadarDetect->PollTime == 0))
|
|
return;
|
|
|
|
if (pRadarDetect->RadarTimeStampLow++ > 5)
|
|
pRadarDetect->RadarTimeStampLow = 0;
|
|
|
|
/*500ms*/
|
|
if ((pRadarDetect->RadarTimeStampLow % 5) == 0)
|
|
DfsCheckBusyIdle(pAd);
|
|
|
|
if (!pRadarDetect->bDfsSwDisable &&
|
|
(pRadarDetect->RadarTimeStampLow & 0x1) && /* 200ms */
|
|
!pRadarDetect->ch_busy)
|
|
SwCheckDfsEventWithFw(pAd);
|
|
|
|
/*
|
|
The following codes is used to check if the hardware find the Radar Signal
|
|
Read the 0~3 channel which had detected radar signals
|
|
Poll Status register
|
|
Set BBP_R140=0x02 and Read BBP_R141 to store at channel
|
|
*/
|
|
DfsHwDetectionStatusGet(pAd, &channel);
|
|
|
|
#if 0
|
|
if((channel & pRadarDetect->EnabledChMask) && pRadarDetect->ch_busy_countdown == -1)
|
|
{
|
|
pRadarDetect->busy_channel = channel;
|
|
pRadarDetect->ch_busy_countdown = 1;
|
|
}
|
|
else if(pRadarDetect->ch_busy_countdown == -1)
|
|
pRadarDetect->busy_channel = channel;
|
|
else if(pRadarDetect->ch_busy_countdown >= 0)
|
|
pRadarDetect->ch_busy_countdown--;
|
|
|
|
/* Check if any interrupt trigger by Radar Global Status(Radar Signals) */
|
|
if ((pRadarDetect->busy_channel & pRadarDetect->EnabledChMask)
|
|
&& (!pRadarDetect->ch_busy)
|
|
&& (pRadarDetect->ch_busy_countdown == -1))
|
|
#endif
|
|
if (channel & pRadarDetect->EnabledChMask)
|
|
{
|
|
radarDeclared = DfsChannelCheck(pAd, channel & pRadarDetect->EnabledChMask);
|
|
}
|
|
|
|
/* reset the radar channel for new counting */
|
|
DfsResetHwDetectionStatus(pAd);
|
|
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE)
|
|
{
|
|
radarDeclared = 1;
|
|
pRadarDetect->McuRadarDebug &= ~RADAR_SIMULATE;
|
|
}
|
|
|
|
/* Now, find an Radar signal */
|
|
if (radarDeclared || pRadarDetect->radarDeclared)
|
|
{
|
|
/*
|
|
Radar found!!!
|
|
Announce that this channel could not use in 30 minutes if we need find a clear channel
|
|
*/
|
|
if (!(pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH))
|
|
{
|
|
ChannelSelectOnRadarDetection(pAd);
|
|
}
|
|
else
|
|
pRadarDetect->radarDeclared = 0;
|
|
}
|
|
}
|
|
|
|
static VOID SwCheckDfsEventWithFw(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
int k, NumEvent = 64; /* event number per event buffer */
|
|
UCHAR id = 0;
|
|
UCHAR BBPR127_Table[DFS_EVENT_BUFFER_SIZE];
|
|
UCHAR BBPR127_OWERID;
|
|
UCHAR OwenerIDValue = 0;
|
|
UCHAR BBP127TableIdx = 0;
|
|
DFS_EVENT DfsEvent;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
|
|
|
|
/*pRadarDetect->McuRadarTick = 0;*/
|
|
|
|
for (BBP127TableIdx = 0; BBP127TableIdx < 6; BBP127TableIdx++)
|
|
{
|
|
RTUSBMultiRead(pAd, BBPR127TABLE_OWNERID + BBP127TableIdx, &BBPR127_OWERID, 1);
|
|
|
|
if (BBPR127_OWERID == 1)
|
|
continue;
|
|
|
|
NdisZeroMemory(BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* Firmware paging bound to 512 byes */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
RTUSBMultiRead(pAd, BBPR127TABLE_OFFSET + (BBP127TableIdx * 512), BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
|
|
|
|
OwenerIDValue = 0x01;
|
|
RTUSBMultiWrite_OneByte(pAd, BBPR127TABLE_OWNERID + BBP127TableIdx, &OwenerIDValue);
|
|
|
|
pDfsSwParam->dfs_w_counter++;
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("\n=============0x%02x==============\n", BBP127TableIdx));
|
|
if (IS_RT3572(pAd))
|
|
{
|
|
DFS_EVENT_BUFF_PRINT(1, BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
|
|
}
|
|
else
|
|
{
|
|
DFS_EVENT_BUFF_PRINT(0, BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
|
|
}
|
|
}
|
|
|
|
for (k = 0; k < NumEvent; k++)
|
|
{
|
|
PUCHAR pTableOffset = NULL;
|
|
if (IS_RT3572(pAd))
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* ignore the first byte */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
pTableOffset = (BBPR127_Table+1) + (DFS_EVENT_SIZE*k);
|
|
}
|
|
else
|
|
{
|
|
pTableOffset = BBPR127_Table + (DFS_EVENT_SIZE*k);
|
|
}
|
|
|
|
if (DfsEventDataFetch(pAd, pTableOffset, &DfsEvent) == FALSE)
|
|
break;
|
|
|
|
if (DfsEventDrop(pAd, &DfsEvent) == TRUE)
|
|
continue;
|
|
|
|
if (pRadarDetect->use_tasklet)
|
|
{
|
|
id = DfsEvent.EngineId;
|
|
|
|
if (id < pAd->chipCap.DfsEngineNum)
|
|
{
|
|
/*if (DfsEvent.TimeStamp != pDfsSwParam->DFS_W[id][((pDfsSwParam->dfs_w_idx[id] == 0)? (NEW_DFS_DBG_PORT_ENT_NUM-1):(pDfsSwParam->dfs_w_idx[id] - 1))].timestamp)*/
|
|
{
|
|
pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].counter = pDfsSwParam->dfs_w_counter;
|
|
pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].timestamp = DfsEvent.TimeStamp;
|
|
pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].width = DfsEvent.Width;
|
|
|
|
if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT)
|
|
{
|
|
printk("counter = %lu ", pDfsSwParam->dfs_w_counter);
|
|
DFS_EVENT_PRINT(DfsEvent);
|
|
}
|
|
|
|
pDfsSwParam->dfs_w_last_idx[id] = pDfsSwParam->dfs_w_idx[id];
|
|
pDfsSwParam->dfs_w_idx[id]++;
|
|
|
|
if (pDfsSwParam->dfs_w_idx[id] >= NEW_DFS_DBG_PORT_ENT_NUM)
|
|
pDfsSwParam->dfs_w_idx[id] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pRadarDetect->use_tasklet)
|
|
{
|
|
/* set hw_idx*/
|
|
pDfsSwParam->hw_idx[0] = pDfsSwParam->dfs_w_idx[0];
|
|
pDfsSwParam->hw_idx[1] = pDfsSwParam->dfs_w_idx[1];
|
|
pDfsSwParam->hw_idx[2] = pDfsSwParam->dfs_w_idx[2];
|
|
pDfsSwParam->hw_idx[3] = pDfsSwParam->dfs_w_idx[3];
|
|
|
|
/*dfs tasklet will call SWRadarCheck*/
|
|
schedule_dfs_task(pAd);
|
|
}
|
|
}
|
|
}
|
|
|
|
void schedule_dfs_task(PRTMP_ADAPTER pAd)
|
|
{
|
|
POS_COOKIE pObj;
|
|
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
|
|
PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
|
|
|
|
pObj = (POS_COOKIE) pAd->OS_Cookie;
|
|
|
|
if (pRadarDetect->DFSAPRestart == 1)
|
|
{
|
|
int i, j;
|
|
|
|
pDfsSwParam->dfs_w_counter += 10;
|
|
/* reset period table */
|
|
for (i = 0; i < pAd->chipCap.DfsEngineNum; i++)
|
|
{
|
|
for (j = 0; j < NEW_DFS_MPERIOD_ENT_NUM; j++)
|
|
{
|
|
pDfsSwParam->DFS_T[i][j].period = 0;
|
|
pDfsSwParam->DFS_T[i][j].idx = 0;
|
|
pDfsSwParam->DFS_T[i][j].idx2 = 0;
|
|
}
|
|
}
|
|
|
|
APStop(pAd);
|
|
APStartUp(pAd);
|
|
|
|
/* re-enable DFS engine */
|
|
DfsDetectionEnable(pAd);
|
|
|
|
pRadarDetect->DFSAPRestart = 0;
|
|
}
|
|
else
|
|
{
|
|
/*s/w check radar event buffer*/
|
|
int idx;
|
|
if (pRadarDetect->radarDeclared == 0)
|
|
{
|
|
for (idx = 0; idx < 4; idx++)
|
|
{
|
|
if (SWRadarCheck(pAd, idx) == 1)
|
|
{
|
|
/* radar signals found */
|
|
pRadarDetect->radarDeclared = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* RTMP_MAC_USB */
|
|
#endif /*CONFIG_AP_SUPPORT*/
|
|
#endif /* DFS_SUPPORT */
|
|
|