1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 
16 #include "odm_precomp.h"
17 
18 #define ADAPTIVITY_VERSION "5.0"
19 
20 void odm_NHMCounterStatisticsInit(void *pDM_VOID)
21 {
22 	PDM_ODM_T		pDM_Odm = (PDM_ODM_T)pDM_VOID;
23 
24 	/* PHY parameters initialize for n series */
25 	rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x2710);	/* 0x894[31:16]= 0x2710	Time duration for NHM unit: 4us, 0x2710 =40ms */
26 	/* rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x4e20);	0x894[31:16]= 0x4e20	Time duration for NHM unit: 4us, 0x4e20 =80ms */
27 	rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff);	/* 0x890[31:16]= 0xffff	th_9, th_10 */
28 	/* rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c);	0x898 = 0xffffff5c		th_3, th_2, th_1, th_0 */
29 	rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52);	/* 0x898 = 0xffffff52		th_3, th_2, th_1, th_0 */
30 	rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff);	/* 0x89c = 0xffffffff		th_7, th_6, th_5, th_4 */
31 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff);		/* 0xe28[7:0]= 0xff		th_8 */
32 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7);	/* 0x890[9:8]=3			enable CCX */
33 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1);		/* 0xc0c[7]= 1			max power among all RX ants */
34 }
35 
36 void odm_NHMCounterStatistics(void *pDM_VOID)
37 {
38 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
39 
40 	/*  Get NHM report */
41 	odm_GetNHMCounterStatistics(pDM_Odm);
42 
43 	/*  Reset NHM counter */
44 	odm_NHMCounterStatisticsReset(pDM_Odm);
45 }
46 
47 void odm_GetNHMCounterStatistics(void *pDM_VOID)
48 {
49 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
50 	u32 value32 = 0;
51 
52 	value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_NHM_CNT_11N, bMaskDWord);
53 
54 	pDM_Odm->NHM_cnt_0 = (u8)(value32 & bMaskByte0);
55 }
56 
57 void odm_NHMCounterStatisticsReset(void *pDM_VOID)
58 {
59 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
60 
61 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0);
62 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1);
63 }
64 
65 void odm_NHMBBInit(void *pDM_VOID)
66 {
67 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
68 
69 	pDM_Odm->adaptivity_flag = 0;
70 	pDM_Odm->tolerance_cnt = 3;
71 	pDM_Odm->NHMLastTxOkcnt = 0;
72 	pDM_Odm->NHMLastRxOkcnt = 0;
73 	pDM_Odm->NHMCurTxOkcnt = 0;
74 	pDM_Odm->NHMCurRxOkcnt = 0;
75 }
76 
77 /*  */
78 void odm_NHMBB(void *pDM_VOID)
79 {
80 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
81 	/* u8 test_status; */
82 	/* Pfalse_ALARM_STATISTICS pFalseAlmCnt = &(pDM_Odm->FalseAlmCnt); */
83 
84 	pDM_Odm->NHMCurTxOkcnt =
85 		*(pDM_Odm->pNumTxBytesUnicast)-pDM_Odm->NHMLastTxOkcnt;
86 	pDM_Odm->NHMCurRxOkcnt =
87 		*(pDM_Odm->pNumRxBytesUnicast)-pDM_Odm->NHMLastRxOkcnt;
88 	pDM_Odm->NHMLastTxOkcnt =
89 		*(pDM_Odm->pNumTxBytesUnicast);
90 	pDM_Odm->NHMLastRxOkcnt =
91 		*(pDM_Odm->pNumRxBytesUnicast);
92 	ODM_RT_TRACE(
93 		pDM_Odm,
94 		ODM_COMP_DIG,
95 		ODM_DBG_LOUD,
96 		(
97 			"NHM_cnt_0 =%d, NHMCurTxOkcnt = %llu, NHMCurRxOkcnt = %llu\n",
98 			pDM_Odm->NHM_cnt_0,
99 			pDM_Odm->NHMCurTxOkcnt,
100 			pDM_Odm->NHMCurRxOkcnt
101 		)
102 	);
103 
104 
105 	if ((pDM_Odm->NHMCurTxOkcnt) + 1 > (u64)(pDM_Odm->NHMCurRxOkcnt<<2) + 1) { /* Tx > 4*Rx possible for adaptivity test */
106 		if (pDM_Odm->NHM_cnt_0 >= 190 || pDM_Odm->adaptivity_flag == true) {
107 			/* Enable EDCCA since it is possible running Adaptivity testing */
108 			/* test_status = 1; */
109 			pDM_Odm->adaptivity_flag = true;
110 			pDM_Odm->tolerance_cnt = 0;
111 		} else {
112 			if (pDM_Odm->tolerance_cnt < 3)
113 				pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
114 			else
115 				pDM_Odm->tolerance_cnt = 4;
116 			/* test_status = 5; */
117 			if (pDM_Odm->tolerance_cnt > 3) {
118 				/* test_status = 3; */
119 				pDM_Odm->adaptivity_flag = false;
120 			}
121 		}
122 	} else { /*  TX<RX */
123 		if (pDM_Odm->adaptivity_flag == true && pDM_Odm->NHM_cnt_0 <= 200) {
124 			/* test_status = 2; */
125 			pDM_Odm->tolerance_cnt = 0;
126 		} else {
127 			if (pDM_Odm->tolerance_cnt < 3)
128 				pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
129 			else
130 				pDM_Odm->tolerance_cnt = 4;
131 			/* test_status = 5; */
132 			if (pDM_Odm->tolerance_cnt > 3) {
133 				/* test_status = 4; */
134 				pDM_Odm->adaptivity_flag = false;
135 			}
136 		}
137 	}
138 
139 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("adaptivity_flag = %d\n ", pDM_Odm->adaptivity_flag));
140 }
141 
142 void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target)
143 {
144 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
145 	u32 value32 = 0;
146 	u8 cnt, IGI;
147 	bool bAdjust = true;
148 	s8 TH_L2H_dmc, TH_H2L_dmc;
149 	s8 Diff;
150 
151 	IGI = 0x50; /*  find H2L, L2H lower bound */
152 	ODM_Write_DIG(pDM_Odm, IGI);
153 
154 
155 	Diff = IGI_target-(s8)IGI;
156 	TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
157 	if (TH_L2H_dmc > 10)
158 		TH_L2H_dmc = 10;
159 	TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
160 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
161 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
162 
163 	mdelay(5);
164 
165 	while (bAdjust) {
166 		for (cnt = 0; cnt < 20; cnt++) {
167 			value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_RPT_11N, bMaskDWord);
168 
169 			if (value32 & BIT30)
170 				pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
171 			else if (value32 & BIT29)
172 				pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
173 			else
174 				pDM_Odm->txEdcca0 = pDM_Odm->txEdcca0 + 1;
175 		}
176 		/* DbgPrint("txEdcca1 = %d, txEdcca0 = %d\n", pDM_Odm->txEdcca1, pDM_Odm->txEdcca0); */
177 
178 		if (pDM_Odm->txEdcca1 > 5) {
179 			IGI = IGI-1;
180 			TH_L2H_dmc = TH_L2H_dmc + 1;
181 			if (TH_L2H_dmc > 10)
182 				TH_L2H_dmc = 10;
183 			TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
184 			PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
185 			PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
186 
187 			pDM_Odm->TxHangFlg = true;
188 			pDM_Odm->txEdcca1 = 0;
189 			pDM_Odm->txEdcca0 = 0;
190 
191 			if (TH_L2H_dmc == 10) {
192 				bAdjust = false;
193 				pDM_Odm->TxHangFlg = false;
194 				pDM_Odm->txEdcca1 = 0;
195 				pDM_Odm->txEdcca0 = 0;
196 				pDM_Odm->H2L_lb = TH_H2L_dmc;
197 				pDM_Odm->L2H_lb = TH_L2H_dmc;
198 				pDM_Odm->Adaptivity_IGI_upper = IGI;
199 			}
200 		} else {
201 			bAdjust = false;
202 			pDM_Odm->TxHangFlg = false;
203 			pDM_Odm->txEdcca1 = 0;
204 			pDM_Odm->txEdcca0 = 0;
205 			pDM_Odm->H2L_lb = TH_H2L_dmc;
206 			pDM_Odm->L2H_lb = TH_L2H_dmc;
207 			pDM_Odm->Adaptivity_IGI_upper = IGI;
208 		}
209 	}
210 
211 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("IGI = 0x%x, H2L_lb = 0x%x, L2H_lb = 0x%x\n", IGI, pDM_Odm->H2L_lb, pDM_Odm->L2H_lb));
212 }
213 
214 void odm_AdaptivityInit(void *pDM_VOID)
215 {
216 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
217 
218 	if (pDM_Odm->Carrier_Sense_enable == false)
219 		pDM_Odm->TH_L2H_ini = 0xf7; /*  -7 */
220 	else
221 		pDM_Odm->TH_L2H_ini = 0xa;
222 
223 	pDM_Odm->AdapEn_RSSI = 20;
224 	pDM_Odm->TH_EDCCA_HL_diff = 7;
225 
226 	pDM_Odm->IGI_Base = 0x32;
227 	pDM_Odm->IGI_target = 0x1c;
228 	pDM_Odm->ForceEDCCA = 0;
229 	pDM_Odm->NHM_disable = false;
230 	pDM_Odm->TxHangFlg = true;
231 	pDM_Odm->txEdcca0 = 0;
232 	pDM_Odm->txEdcca1 = 0;
233 	pDM_Odm->H2L_lb = 0;
234 	pDM_Odm->L2H_lb = 0;
235 	pDM_Odm->Adaptivity_IGI_upper = 0;
236 	odm_NHMBBInit(pDM_Odm);
237 
238 	PHY_SetBBReg(pDM_Odm->Adapter, REG_RD_CTRL, BIT11, 1); /*  stop counting if EDCCA is asserted */
239 }
240 
241 
242 void odm_Adaptivity(void *pDM_VOID, u8 IGI)
243 {
244 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
245 	s8 TH_L2H_dmc, TH_H2L_dmc;
246 	s8 Diff, IGI_target;
247 	bool EDCCA_State = false;
248 
249 	if (!(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY)) {
250 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Go to odm_DynamicEDCCA()\n"));
251 		return;
252 	}
253 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_Adaptivity() =====>\n"));
254 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("ForceEDCCA =%d, IGI_Base = 0x%x, TH_L2H_ini = %d, TH_EDCCA_HL_diff = %d, AdapEn_RSSI = %d\n",
255 		pDM_Odm->ForceEDCCA, pDM_Odm->IGI_Base, pDM_Odm->TH_L2H_ini, pDM_Odm->TH_EDCCA_HL_diff, pDM_Odm->AdapEn_RSSI));
256 
257 	if (*pDM_Odm->pBandWidth == ODM_BW20M) /* CHANNEL_WIDTH_20 */
258 		IGI_target = pDM_Odm->IGI_Base;
259 	else if (*pDM_Odm->pBandWidth == ODM_BW40M)
260 		IGI_target = pDM_Odm->IGI_Base + 2;
261 	else if (*pDM_Odm->pBandWidth == ODM_BW80M)
262 		IGI_target = pDM_Odm->IGI_Base + 2;
263 	else
264 		IGI_target = pDM_Odm->IGI_Base;
265 	pDM_Odm->IGI_target = (u8) IGI_target;
266 
267 	/* Search pwdB lower bound */
268 	if (pDM_Odm->TxHangFlg == true) {
269 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208);
270 		odm_SearchPwdBLowerBound(pDM_Odm, pDM_Odm->IGI_target);
271 	}
272 
273 	if ((!pDM_Odm->bLinked) || (*pDM_Odm->pChannel > 149)) { /*  Band4 doesn't need adaptivity */
274 		PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, 0x7f);
275 		PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, 0x7f);
276 		return;
277 	}
278 
279 	if (!pDM_Odm->ForceEDCCA) {
280 		if (pDM_Odm->RSSI_Min > pDM_Odm->AdapEn_RSSI)
281 			EDCCA_State = true;
282 		else if (pDM_Odm->RSSI_Min < (pDM_Odm->AdapEn_RSSI - 5))
283 			EDCCA_State = false;
284 	} else
285 		EDCCA_State = true;
286 
287 	if (
288 		pDM_Odm->bLinked &&
289 		pDM_Odm->Carrier_Sense_enable == false &&
290 		pDM_Odm->NHM_disable == false &&
291 		pDM_Odm->TxHangFlg == false
292 	)
293 		odm_NHMBB(pDM_Odm);
294 
295 	ODM_RT_TRACE(
296 		pDM_Odm,
297 		ODM_COMP_DIG,
298 		ODM_DBG_LOUD,
299 		(
300 			"BandWidth =%s, IGI_target = 0x%x, EDCCA_State =%d\n",
301 			(*pDM_Odm->pBandWidth == ODM_BW80M) ? "80M" :
302 			((*pDM_Odm->pBandWidth == ODM_BW40M) ? "40M" : "20M"),
303 			IGI_target,
304 			EDCCA_State
305 		)
306 	);
307 
308 	if (EDCCA_State) {
309 		Diff = IGI_target-(s8)IGI;
310 		TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
311 		if (TH_L2H_dmc > 10)
312 			TH_L2H_dmc = 10;
313 
314 		TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
315 
316 		/* replace lower bound to prevent EDCCA always equal  */
317 		if (TH_H2L_dmc < pDM_Odm->H2L_lb)
318 			TH_H2L_dmc = pDM_Odm->H2L_lb;
319 		if (TH_L2H_dmc < pDM_Odm->L2H_lb)
320 			TH_L2H_dmc = pDM_Odm->L2H_lb;
321 	} else {
322 		TH_L2H_dmc = 0x7f;
323 		TH_H2L_dmc = 0x7f;
324 	}
325 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("IGI = 0x%x, TH_L2H_dmc = %d, TH_H2L_dmc = %d\n",
326 		IGI, TH_L2H_dmc, TH_H2L_dmc));
327 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
328 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
329 }
330 
331 void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI)
332 {
333 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
334 	pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
335 
336 	if (pDM_DigTable->bStopDIG) {
337 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Stop Writing IGI\n"));
338 		return;
339 	}
340 
341 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("ODM_REG(IGI_A, pDM_Odm) = 0x%x, ODM_BIT(IGI, pDM_Odm) = 0x%x\n",
342 		ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm)));
343 
344 	if (pDM_DigTable->CurIGValue != CurrentIGI) {
345 		/* 1 Check initial gain by upper bound */
346 		if (!pDM_DigTable->bPSDInProgress) {
347 			if (CurrentIGI > pDM_DigTable->rx_gain_range_max) {
348 				ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("CurrentIGI(0x%02x) is larger than upper bound !!\n", pDM_DigTable->rx_gain_range_max));
349 				CurrentIGI = pDM_DigTable->rx_gain_range_max;
350 			}
351 
352 		}
353 
354 		/* 1 Set IGI value */
355 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
356 
357 		if (pDM_Odm->RFType > ODM_1T1R)
358 			PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
359 
360 		pDM_DigTable->CurIGValue = CurrentIGI;
361 	}
362 
363 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("CurrentIGI(0x%02x).\n", CurrentIGI));
364 
365 }
366 
367 void odm_PauseDIG(
368 	void *pDM_VOID,
369 	ODM_Pause_DIG_TYPE PauseType,
370 	u8 IGIValue
371 )
372 {
373 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
374 	pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
375 	static bool bPaused;
376 
377 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG() =========>\n"));
378 
379 	if (
380 		(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY) &&
381 		pDM_Odm->TxHangFlg == true
382 	) {
383 		ODM_RT_TRACE(
384 			pDM_Odm,
385 			ODM_COMP_DIG,
386 			ODM_DBG_LOUD,
387 			("odm_PauseDIG(): Dynamic adjust threshold in progress !!\n")
388 		);
389 		return;
390 	}
391 
392 	if (
393 		!bPaused && (!(pDM_Odm->SupportAbility & ODM_BB_DIG) ||
394 		!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
395 	){
396 		ODM_RT_TRACE(
397 			pDM_Odm,
398 			ODM_COMP_DIG,
399 			ODM_DBG_LOUD,
400 			("odm_PauseDIG(): Return: SupportAbility ODM_BB_DIG or ODM_BB_FA_CNT is disabled\n")
401 		);
402 		return;
403 	}
404 
405 	switch (PauseType) {
406 	/* 1 Pause DIG */
407 	case ODM_PAUSE_DIG:
408 		/* 2 Disable DIG */
409 		ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility & (~ODM_BB_DIG));
410 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Pause DIG !!\n"));
411 
412 		/* 2 Backup IGI value */
413 		if (!bPaused) {
414 			pDM_DigTable->IGIBackup = pDM_DigTable->CurIGValue;
415 			bPaused = true;
416 		}
417 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Backup IGI  = 0x%x\n", pDM_DigTable->IGIBackup));
418 
419 		/* 2 Write new IGI value */
420 		ODM_Write_DIG(pDM_Odm, IGIValue);
421 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Write new IGI = 0x%x\n", IGIValue));
422 		break;
423 
424 	/* 1 Resume DIG */
425 	case ODM_RESUME_DIG:
426 		if (bPaused) {
427 			/* 2 Write backup IGI value */
428 			ODM_Write_DIG(pDM_Odm, pDM_DigTable->IGIBackup);
429 			bPaused = false;
430 			ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Write original IGI = 0x%x\n", pDM_DigTable->IGIBackup));
431 
432 			/* 2 Enable DIG */
433 			ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility | ODM_BB_DIG);
434 			ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Resume DIG !!\n"));
435 		}
436 		break;
437 
438 	default:
439 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Wrong  type !!\n"));
440 		break;
441 	}
442 }
443 
444 bool odm_DigAbort(void *pDM_VOID)
445 {
446 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
447 
448 	/* SupportAbility */
449 	if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) {
450 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: SupportAbility ODM_BB_FA_CNT is disabled\n"));
451 		return	true;
452 	}
453 
454 	/* SupportAbility */
455 	if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) {
456 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: SupportAbility ODM_BB_DIG is disabled\n"));
457 		return	true;
458 	}
459 
460 	/* ScanInProcess */
461 	if (*(pDM_Odm->pbScanInProcess)) {
462 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: In Scan Progress\n"));
463 		return	true;
464 	}
465 
466 	/* add by Neil Chen to avoid PSD is processing */
467 	if (pDM_Odm->bDMInitialGainEnable == false) {
468 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: PSD is Processing\n"));
469 		return	true;
470 	}
471 
472 	return	false;
473 }
474 
475 void odm_DIGInit(void *pDM_VOID)
476 {
477 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
478 	pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
479 
480 	pDM_DigTable->bStopDIG = false;
481 	pDM_DigTable->bPSDInProgress = false;
482 	pDM_DigTable->CurIGValue = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
483 	pDM_DigTable->RssiLowThresh	= DM_DIG_THRESH_LOW;
484 	pDM_DigTable->RssiHighThresh	= DM_DIG_THRESH_HIGH;
485 	pDM_DigTable->FALowThresh	= DMfalseALARM_THRESH_LOW;
486 	pDM_DigTable->FAHighThresh	= DMfalseALARM_THRESH_HIGH;
487 	pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
488 	pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
489 	pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
490 	pDM_DigTable->PreCCK_CCAThres = 0xFF;
491 	pDM_DigTable->CurCCK_CCAThres = 0x83;
492 	pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
493 	pDM_DigTable->LargeFAHit = 0;
494 	pDM_DigTable->Recover_cnt = 0;
495 	pDM_DigTable->bMediaConnect_0 = false;
496 	pDM_DigTable->bMediaConnect_1 = false;
497 
498 	/* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
499 	pDM_Odm->bDMInitialGainEnable = true;
500 
501 	pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
502 	pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
503 
504 	/* To Initi BT30 IGI */
505 	pDM_DigTable->BT30_CurIGI = 0x32;
506 
507 	if (pDM_Odm->BoardType & (ODM_BOARD_EXT_PA|ODM_BOARD_EXT_LNA)) {
508 		pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
509 		pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
510 	} else {
511 		pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
512 		pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
513 	}
514 
515 }
516 
517 
518 void odm_DIG(void *pDM_VOID)
519 {
520 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
521 
522 	/*  Common parameters */
523 	pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
524 	Pfalse_ALARM_STATISTICS pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
525 	bool FirstConnect, FirstDisConnect;
526 	u8 DIG_MaxOfMin, DIG_Dynamic_MIN;
527 	u8 dm_dig_max, dm_dig_min;
528 	u8 CurrentIGI = pDM_DigTable->CurIGValue;
529 	u8 offset;
530 	u32 dm_FA_thres[3];
531 	u8 Adap_IGI_Upper = 0;
532 	u32 TxTp = 0, RxTp = 0;
533 	bool bDFSBand = false;
534 	bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false;
535 
536 	if (odm_DigAbort(pDM_Odm) == true)
537 		return;
538 
539 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG() ===========================>\n\n"));
540 
541 	if (pDM_Odm->adaptivity_flag == true)
542 		Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper;
543 
544 
545 	/* 1 Update status */
546 	DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
547 	FirstConnect = (pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == false);
548 	FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == true);
549 
550 	/* 1 Boundary Decision */
551 	/* 2 For WIN\CE */
552 	dm_dig_max = 0x5A;
553 	dm_dig_min = DM_DIG_MIN_NIC;
554 	DIG_MaxOfMin = DM_DIG_MAX_AP;
555 
556 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Absolutely upper bound = 0x%x, lower bound = 0x%x\n", dm_dig_max, dm_dig_min));
557 
558 	/* 1 Adjust boundary by RSSI */
559 	if (pDM_Odm->bLinked && bPerformance) {
560 		/* 2 Modify DIG upper bound */
561 		/* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */
562 		if (pDM_Odm->bBtLimitedDig == 1) {
563 			offset = 10;
564 			ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Coex. case: Force upper bound to RSSI + %d !!!!!!\n", offset));
565 		} else
566 			offset = 15;
567 
568 		if ((pDM_Odm->RSSI_Min + offset) > dm_dig_max)
569 			pDM_DigTable->rx_gain_range_max = dm_dig_max;
570 		else if ((pDM_Odm->RSSI_Min + offset) < dm_dig_min)
571 			pDM_DigTable->rx_gain_range_max = dm_dig_min;
572 		else
573 			pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + offset;
574 
575 		/* 2 Modify DIG lower bound */
576 		/* if (pDM_Odm->bOneEntryOnly) */
577 		{
578 			if (pDM_Odm->RSSI_Min < dm_dig_min)
579 				DIG_Dynamic_MIN = dm_dig_min;
580 			else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
581 				DIG_Dynamic_MIN = DIG_MaxOfMin;
582 			else
583 				DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
584 		}
585 	} else {
586 		pDM_DigTable->rx_gain_range_max = dm_dig_max;
587 		DIG_Dynamic_MIN = dm_dig_min;
588 	}
589 
590 	/* 1 Force Lower Bound for AntDiv */
591 	if (pDM_Odm->bLinked && !pDM_Odm->bOneEntryOnly) {
592 		if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
593 			if (
594 				pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV ||
595 				pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV ||
596 				pDM_Odm->AntDivType == S0S1_SW_ANTDIV
597 			) {
598 				if (pDM_DigTable->AntDiv_RSSI_max > DIG_MaxOfMin)
599 					DIG_Dynamic_MIN = DIG_MaxOfMin;
600 				else
601 					DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max;
602 				ODM_RT_TRACE(
603 					pDM_Odm,
604 					ODM_COMP_ANT_DIV,
605 					ODM_DBG_LOUD,
606 					(
607 						"odm_DIG(): Antenna diversity case: Force lower bound to 0x%x !!!!!!\n",
608 						DIG_Dynamic_MIN
609 					)
610 				);
611 				ODM_RT_TRACE(
612 					pDM_Odm,
613 					ODM_COMP_ANT_DIV,
614 					ODM_DBG_LOUD,
615 					(
616 						"odm_DIG(): Antenna diversity case: RSSI_max = 0x%x !!!!!!\n",
617 						pDM_DigTable->AntDiv_RSSI_max
618 					)
619 				);
620 			}
621 		}
622 	}
623 	ODM_RT_TRACE(
624 		pDM_Odm,
625 		ODM_COMP_DIG,
626 		ODM_DBG_LOUD,
627 		(
628 			"odm_DIG(): Adjust boundary by RSSI Upper bound = 0x%x, Lower bound = 0x%x\n",
629 			pDM_DigTable->rx_gain_range_max,
630 			DIG_Dynamic_MIN
631 		)
632 	);
633 	ODM_RT_TRACE(
634 		pDM_Odm,
635 		ODM_COMP_DIG,
636 		ODM_DBG_LOUD,
637 		(
638 			"odm_DIG(): Link status: bLinked = %d, RSSI = %d, bFirstConnect = %d, bFirsrDisConnect = %d\n\n",
639 			pDM_Odm->bLinked,
640 			pDM_Odm->RSSI_Min,
641 			FirstConnect,
642 			FirstDisConnect
643 		)
644 	);
645 
646 	/* 1 Modify DIG lower bound, deal with abnormal case */
647 	/* 2 Abnormal false alarm case */
648 	if (FirstDisConnect) {
649 		pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN;
650 		pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN;
651 	} else
652 		pDM_DigTable->rx_gain_range_min =
653 			odm_ForbiddenIGICheck(pDM_Odm, DIG_Dynamic_MIN, CurrentIGI);
654 
655 	if (pDM_Odm->bLinked && !FirstConnect) {
656 		if (
657 			(pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
658 			pDM_Odm->bsta_state
659 		) {
660 			pDM_DigTable->rx_gain_range_min = dm_dig_min;
661 			ODM_RT_TRACE(
662 				pDM_Odm,
663 				ODM_COMP_DIG,
664 				ODM_DBG_LOUD,
665 				(
666 					"odm_DIG(): Abnrormal #beacon (%d) case in STA mode: Force lower bound to 0x%x !!!!!!\n\n",
667 					pDM_Odm->PhyDbgInfo.NumQryBeaconPkt,
668 					pDM_DigTable->rx_gain_range_min
669 				)
670 			);
671 		}
672 	}
673 
674 	/* 2 Abnormal lower bound case */
675 	if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) {
676 		pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
677 		ODM_RT_TRACE(
678 			pDM_Odm,
679 			ODM_COMP_DIG,
680 			ODM_DBG_LOUD,
681 			(
682 				"odm_DIG(): Abnrormal lower bound case: Force lower bound to 0x%x !!!!!!\n\n",
683 				pDM_DigTable->rx_gain_range_min
684 			)
685 		);
686 	}
687 
688 
689 	/* 1 False alarm threshold decision */
690 	odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres);
691 	ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): False alarm threshold = %d, %d, %d\n\n", dm_FA_thres[0], dm_FA_thres[1], dm_FA_thres[2]));
692 
693 	/* 1 Adjust initial gain by false alarm */
694 	if (pDM_Odm->bLinked && bPerformance) {
695 		/* 2 After link */
696 		ODM_RT_TRACE(
697 			pDM_Odm,
698 			ODM_COMP_DIG,
699 			ODM_DBG_LOUD,
700 			("odm_DIG(): Adjust IGI after link\n")
701 		);
702 
703 		if (bFirstTpTarget || (FirstConnect && bPerformance)) {
704 			pDM_DigTable->LargeFAHit = 0;
705 
706 			if (pDM_Odm->RSSI_Min < DIG_MaxOfMin) {
707 				if (CurrentIGI < pDM_Odm->RSSI_Min)
708 					CurrentIGI = pDM_Odm->RSSI_Min;
709 			} else {
710 				if (CurrentIGI < DIG_MaxOfMin)
711 					CurrentIGI = DIG_MaxOfMin;
712 			}
713 
714 			ODM_RT_TRACE(
715 				pDM_Odm,
716 				ODM_COMP_DIG,
717 				ODM_DBG_LOUD,
718 				(
719 					"odm_DIG(): First connect case: IGI does on-shot to 0x%x\n",
720 					CurrentIGI
721 				)
722 			);
723 
724 		} else {
725 			if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
726 				CurrentIGI = CurrentIGI + 4;
727 			else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
728 				CurrentIGI = CurrentIGI + 2;
729 			else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
730 				CurrentIGI = CurrentIGI - 2;
731 
732 			if (
733 				(pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
734 				(pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH1) &&
735 				(pDM_Odm->bsta_state)
736 			) {
737 				CurrentIGI = pDM_DigTable->rx_gain_range_min;
738 				ODM_RT_TRACE(
739 					pDM_Odm,
740 					ODM_COMP_DIG,
741 					ODM_DBG_LOUD,
742 					(
743 						"odm_DIG(): Abnormal #beacon (%d) case: IGI does one-shot to 0x%x\n",
744 						pDM_Odm->PhyDbgInfo.NumQryBeaconPkt,
745 						CurrentIGI
746 					)
747 				);
748 			}
749 		}
750 	} else {
751 		/* 2 Before link */
752 		ODM_RT_TRACE(
753 			pDM_Odm,
754 			ODM_COMP_DIG,
755 			ODM_DBG_LOUD,
756 			("odm_DIG(): Adjust IGI before link\n")
757 		);
758 
759 		if (FirstDisConnect || bFirstCoverage) {
760 			CurrentIGI = dm_dig_min;
761 			ODM_RT_TRACE(
762 				pDM_Odm,
763 				ODM_COMP_DIG,
764 				ODM_DBG_LOUD,
765 				("odm_DIG(): First disconnect case: IGI does on-shot to lower bound\n")
766 			);
767 		} else {
768 			if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
769 				CurrentIGI = CurrentIGI + 4;
770 			else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
771 				CurrentIGI = CurrentIGI + 2;
772 			else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
773 				CurrentIGI = CurrentIGI - 2;
774 		}
775 	}
776 
777 	/* 1 Check initial gain by upper/lower bound */
778 	if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
779 		CurrentIGI = pDM_DigTable->rx_gain_range_min;
780 
781 	if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
782 		CurrentIGI = pDM_DigTable->rx_gain_range_max;
783 
784 	ODM_RT_TRACE(
785 		pDM_Odm,
786 		ODM_COMP_DIG,
787 		ODM_DBG_LOUD,
788 		(
789 			"odm_DIG(): CurIGValue = 0x%x, TotalFA = %d\n\n",
790 			CurrentIGI,
791 			pFalseAlmCnt->Cnt_all
792 		)
793 	);
794 
795 	/* 1 Force upper bound and lower bound for adaptivity */
796 	if (
797 		pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY &&
798 		pDM_Odm->adaptivity_flag == true
799 	) {
800 		if (CurrentIGI > Adap_IGI_Upper)
801 			CurrentIGI = Adap_IGI_Upper;
802 
803 		if (pDM_Odm->IGI_LowerBound != 0) {
804 			if (CurrentIGI < pDM_Odm->IGI_LowerBound)
805 				CurrentIGI = pDM_Odm->IGI_LowerBound;
806 		}
807 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Adaptivity case: Force upper bound to 0x%x !!!!!!\n", Adap_IGI_Upper));
808 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Adaptivity case: Force lower bound to 0x%x !!!!!!\n\n", pDM_Odm->IGI_LowerBound));
809 	}
810 
811 
812 	/* 1 Update status */
813 	if (pDM_Odm->bBtHsOperation) {
814 		if (pDM_Odm->bLinked) {
815 			if (pDM_DigTable->BT30_CurIGI > (CurrentIGI))
816 				ODM_Write_DIG(pDM_Odm, CurrentIGI);
817 			else
818 				ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);
819 
820 			pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
821 			pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
822 		} else {
823 			if (pDM_Odm->bLinkInProcess)
824 				ODM_Write_DIG(pDM_Odm, 0x1c);
825 			else if (pDM_Odm->bBtConnectProcess)
826 				ODM_Write_DIG(pDM_Odm, 0x28);
827 			else
828 				ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
829 		}
830 	} else { /*  BT is not using */
831 		ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
832 		pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
833 		pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
834 	}
835 }
836 
837 void odm_DIGbyRSSI_LPS(void *pDM_VOID)
838 {
839 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
840 	Pfalse_ALARM_STATISTICS pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
841 
842 	u8 RSSI_Lower = DM_DIG_MIN_NIC;   /* 0x1E or 0x1C */
843 	u8 CurrentIGI = pDM_Odm->RSSI_Min;
844 
845 	CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
846 
847 	ODM_RT_TRACE(
848 		pDM_Odm,
849 		ODM_COMP_DIG,
850 		ODM_DBG_LOUD,
851 		("odm_DIGbyRSSI_LPS() ==>\n")
852 	);
853 
854 	/*  Using FW PS mode to make IGI */
855 	/* Adjust by  FA in LPS MODE */
856 	if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
857 		CurrentIGI = CurrentIGI+4;
858 	else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
859 		CurrentIGI = CurrentIGI+2;
860 	else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
861 		CurrentIGI = CurrentIGI-2;
862 
863 
864 	/* Lower bound checking */
865 
866 	/* RSSI Lower bound check */
867 	if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC)
868 		RSSI_Lower = pDM_Odm->RSSI_Min-10;
869 	else
870 		RSSI_Lower = DM_DIG_MIN_NIC;
871 
872 	/* Upper and Lower Bound checking */
873 	if (CurrentIGI > DM_DIG_MAX_NIC)
874 		CurrentIGI = DM_DIG_MAX_NIC;
875 	else if (CurrentIGI < RSSI_Lower)
876 		CurrentIGI = RSSI_Lower;
877 
878 
879 	ODM_RT_TRACE(
880 		pDM_Odm,
881 		ODM_COMP_DIG,
882 		ODM_DBG_LOUD,
883 		("odm_DIGbyRSSI_LPS(): pFalseAlmCnt->Cnt_all = %d\n", pFalseAlmCnt->Cnt_all)
884 	);
885 	ODM_RT_TRACE(
886 		pDM_Odm,
887 		ODM_COMP_DIG,
888 		ODM_DBG_LOUD,
889 		("odm_DIGbyRSSI_LPS(): pDM_Odm->RSSI_Min = %d\n", pDM_Odm->RSSI_Min)
890 	);
891 	ODM_RT_TRACE(
892 		pDM_Odm,
893 		ODM_COMP_DIG,
894 		ODM_DBG_LOUD,
895 		("odm_DIGbyRSSI_LPS(): CurrentIGI = 0x%x\n", CurrentIGI)
896 	);
897 
898 	ODM_Write_DIG(pDM_Odm, CurrentIGI);
899 	/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
900 }
901 
902 /* 3 ============================================================ */
903 /* 3 FASLE ALARM CHECK */
904 /* 3 ============================================================ */
905 
906 void odm_FalseAlarmCounterStatistics(void *pDM_VOID)
907 {
908 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
909 	Pfalse_ALARM_STATISTICS FalseAlmCnt = &(pDM_Odm->FalseAlmCnt);
910 	u32 ret_value;
911 
912 	if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
913 		return;
914 
915 	/* hold ofdm counter */
916 	/* hold page C counter */
917 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1);
918 	/* hold page D counter */
919 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1);
920 
921 	ret_value = PHY_QueryBBReg(
922 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord
923 	);
924 	FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
925 	FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
926 
927 	ret_value = PHY_QueryBBReg(
928 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord
929 	);
930 	FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
931 	FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
932 
933 	ret_value = PHY_QueryBBReg(
934 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord
935 	);
936 	FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
937 	FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
938 
939 	ret_value = PHY_QueryBBReg(
940 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord
941 	);
942 	FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
943 
944 	FalseAlmCnt->Cnt_Ofdm_fail =
945 		FalseAlmCnt->Cnt_Parity_Fail +
946 		FalseAlmCnt->Cnt_Rate_Illegal +
947 		FalseAlmCnt->Cnt_Crc8_fail +
948 		FalseAlmCnt->Cnt_Mcs_fail +
949 		FalseAlmCnt->Cnt_Fast_Fsync +
950 		FalseAlmCnt->Cnt_SB_Search_fail;
951 
952 	{
953 		/* hold cck counter */
954 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
955 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
956 
957 		ret_value = PHY_QueryBBReg(
958 			pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0
959 		);
960 		FalseAlmCnt->Cnt_Cck_fail = ret_value;
961 
962 		ret_value = PHY_QueryBBReg(
963 			pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3
964 		);
965 		FalseAlmCnt->Cnt_Cck_fail += (ret_value&0xff)<<8;
966 
967 		ret_value = PHY_QueryBBReg(
968 			pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord
969 		);
970 		FalseAlmCnt->Cnt_CCK_CCA =
971 			((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
972 	}
973 
974 	FalseAlmCnt->Cnt_all = (
975 		FalseAlmCnt->Cnt_Fast_Fsync +
976 		FalseAlmCnt->Cnt_SB_Search_fail +
977 		FalseAlmCnt->Cnt_Parity_Fail +
978 		FalseAlmCnt->Cnt_Rate_Illegal +
979 		FalseAlmCnt->Cnt_Crc8_fail +
980 		FalseAlmCnt->Cnt_Mcs_fail +
981 		FalseAlmCnt->Cnt_Cck_fail
982 	);
983 
984 	FalseAlmCnt->Cnt_CCA_all =
985 		FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
986 
987 	ODM_RT_TRACE(
988 		pDM_Odm,
989 		ODM_COMP_FA_CNT,
990 		ODM_DBG_LOUD,
991 		("Enter odm_FalseAlarmCounterStatistics\n")
992 	);
993 	ODM_RT_TRACE(
994 		pDM_Odm,
995 		ODM_COMP_FA_CNT,
996 		ODM_DBG_LOUD,
997 		(
998 			"Cnt_Fast_Fsync =%d, Cnt_SB_Search_fail =%d\n",
999 			FalseAlmCnt->Cnt_Fast_Fsync,
1000 			FalseAlmCnt->Cnt_SB_Search_fail
1001 		)
1002 	);
1003 	ODM_RT_TRACE(
1004 		pDM_Odm,
1005 		ODM_COMP_FA_CNT,
1006 		ODM_DBG_LOUD,
1007 		(
1008 			"Cnt_Parity_Fail =%d, Cnt_Rate_Illegal =%d\n",
1009 			FalseAlmCnt->Cnt_Parity_Fail,
1010 			FalseAlmCnt->Cnt_Rate_Illegal
1011 		)
1012 	);
1013 	ODM_RT_TRACE(
1014 		pDM_Odm,
1015 		ODM_COMP_FA_CNT,
1016 		ODM_DBG_LOUD,
1017 		(
1018 			"Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n",
1019 			FalseAlmCnt->Cnt_Crc8_fail,
1020 			FalseAlmCnt->Cnt_Mcs_fail
1021 		)
1022 	);
1023 
1024 	ODM_RT_TRACE(
1025 		pDM_Odm,
1026 		ODM_COMP_FA_CNT,
1027 		ODM_DBG_LOUD,
1028 		("Cnt_OFDM_CCA =%d\n", FalseAlmCnt->Cnt_OFDM_CCA)
1029 	);
1030 	ODM_RT_TRACE(
1031 		pDM_Odm,
1032 		ODM_COMP_FA_CNT,
1033 		ODM_DBG_LOUD,
1034 		("Cnt_CCK_CCA =%d\n", FalseAlmCnt->Cnt_CCK_CCA)
1035 	);
1036 	ODM_RT_TRACE(
1037 		pDM_Odm,
1038 		ODM_COMP_FA_CNT,
1039 		ODM_DBG_LOUD,
1040 		("Cnt_CCA_all =%d\n", FalseAlmCnt->Cnt_CCA_all)
1041 	);
1042 	ODM_RT_TRACE(
1043 		pDM_Odm,
1044 		ODM_COMP_FA_CNT,
1045 		ODM_DBG_LOUD,
1046 		("Cnt_Ofdm_fail =%d\n",	FalseAlmCnt->Cnt_Ofdm_fail)
1047 	);
1048 	ODM_RT_TRACE(
1049 		pDM_Odm,
1050 		ODM_COMP_FA_CNT,
1051 		ODM_DBG_LOUD,
1052 		("Cnt_Cck_fail =%d\n",	FalseAlmCnt->Cnt_Cck_fail)
1053 	);
1054 	ODM_RT_TRACE(
1055 		pDM_Odm,
1056 		ODM_COMP_FA_CNT,
1057 		ODM_DBG_LOUD,
1058 		("Cnt_Ofdm_fail =%d\n",	FalseAlmCnt->Cnt_Ofdm_fail)
1059 	);
1060 	ODM_RT_TRACE(
1061 		pDM_Odm,
1062 		ODM_COMP_FA_CNT,
1063 		ODM_DBG_LOUD,
1064 		("Total False Alarm =%d\n",	FalseAlmCnt->Cnt_all)
1065 	);
1066 }
1067 
1068 
1069 void odm_FAThresholdCheck(
1070 	void *pDM_VOID,
1071 	bool bDFSBand,
1072 	bool bPerformance,
1073 	u32 RxTp,
1074 	u32 TxTp,
1075 	u32 *dm_FA_thres
1076 )
1077 {
1078 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
1079 
1080 	if (pDM_Odm->bLinked && (bPerformance || bDFSBand)) {
1081 		/*  For NIC */
1082 		dm_FA_thres[0] = DM_DIG_FA_TH0;
1083 		dm_FA_thres[1] = DM_DIG_FA_TH1;
1084 		dm_FA_thres[2] = DM_DIG_FA_TH2;
1085 	} else {
1086 		dm_FA_thres[0] = 2000;
1087 		dm_FA_thres[1] = 4000;
1088 		dm_FA_thres[2] = 5000;
1089 	}
1090 	return;
1091 }
1092 
1093 u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI)
1094 {
1095 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
1096 	pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
1097 	Pfalse_ALARM_STATISTICS pFalseAlmCnt = &(pDM_Odm->FalseAlmCnt);
1098 	u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min;
1099 
1100 	if (pFalseAlmCnt->Cnt_all > 10000) {
1101 		ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnormally false alarm case.\n"));
1102 
1103 		if (pDM_DigTable->LargeFAHit != 3)
1104 			pDM_DigTable->LargeFAHit++;
1105 
1106 		/* if (pDM_DigTable->ForbiddenIGI < pDM_DigTable->CurIGValue) */
1107 		if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
1108 			pDM_DigTable->ForbiddenIGI = CurrentIGI;
1109 			/* pDM_DigTable->ForbiddenIGI = pDM_DigTable->CurIGValue; */
1110 			pDM_DigTable->LargeFAHit = 1;
1111 		}
1112 
1113 		if (pDM_DigTable->LargeFAHit >= 3) {
1114 			if ((pDM_DigTable->ForbiddenIGI + 2) > pDM_DigTable->rx_gain_range_max)
1115 				rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
1116 			else
1117 				rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
1118 			pDM_DigTable->Recover_cnt = 1800;
1119 			ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnormally false alarm case: Recover_cnt = %d\n", pDM_DigTable->Recover_cnt));
1120 		}
1121 	} else {
1122 		if (pDM_DigTable->Recover_cnt != 0) {
1123 			pDM_DigTable->Recover_cnt--;
1124 			ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: Recover_cnt = %d\n", pDM_DigTable->Recover_cnt));
1125 		} else {
1126 			if (pDM_DigTable->LargeFAHit < 3) {
1127 				if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
1128 					pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
1129 					rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
1130 					ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: At Lower Bound\n"));
1131 				} else {
1132 					pDM_DigTable->ForbiddenIGI -= 2;
1133 					rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
1134 					ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: Approach Lower Bound\n"));
1135 				}
1136 			} else
1137 				pDM_DigTable->LargeFAHit = 0;
1138 		}
1139 	}
1140 
1141 	return rx_gain_range_min;
1142 
1143 }
1144 
1145 /* 3 ============================================================ */
1146 /* 3 CCK Packet Detect Threshold */
1147 /* 3 ============================================================ */
1148 
1149 void odm_CCKPacketDetectionThresh(void *pDM_VOID)
1150 {
1151 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
1152 	Pfalse_ALARM_STATISTICS FalseAlmCnt = &(pDM_Odm->FalseAlmCnt);
1153 	u8 CurCCK_CCAThres;
1154 
1155 
1156 	if (
1157 		!(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) ||
1158 		!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)
1159 	) {
1160 		ODM_RT_TRACE(
1161 			pDM_Odm,
1162 			ODM_COMP_CCK_PD,
1163 			ODM_DBG_LOUD,
1164 			("odm_CCKPacketDetectionThresh()  return ==========\n")
1165 		);
1166 		return;
1167 	}
1168 
1169 	if (pDM_Odm->ExtLNA)
1170 		return;
1171 
1172 	ODM_RT_TRACE(
1173 		pDM_Odm,
1174 		ODM_COMP_CCK_PD,
1175 		ODM_DBG_LOUD,
1176 		("odm_CCKPacketDetectionThresh()  ==========>\n")
1177 	);
1178 
1179 	if (pDM_Odm->bLinked) {
1180 		if (pDM_Odm->RSSI_Min > 25)
1181 			CurCCK_CCAThres = 0xcd;
1182 		else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10))
1183 			CurCCK_CCAThres = 0x83;
1184 		else {
1185 			if (FalseAlmCnt->Cnt_Cck_fail > 1000)
1186 				CurCCK_CCAThres = 0x83;
1187 			else
1188 				CurCCK_CCAThres = 0x40;
1189 		}
1190 	} else {
1191 		if (FalseAlmCnt->Cnt_Cck_fail > 1000)
1192 			CurCCK_CCAThres = 0x83;
1193 		else
1194 			CurCCK_CCAThres = 0x40;
1195 	}
1196 
1197 	ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
1198 
1199 	ODM_RT_TRACE(
1200 		pDM_Odm,
1201 		ODM_COMP_CCK_PD,
1202 		ODM_DBG_LOUD,
1203 		(
1204 			"odm_CCKPacketDetectionThresh()  CurCCK_CCAThres = 0x%x\n",
1205 			CurCCK_CCAThres
1206 		)
1207 	);
1208 }
1209 
1210 void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres)
1211 {
1212 	PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
1213 	pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
1214 
1215 	/* modify by Guo.Mingzhi 2012-01-03 */
1216 	if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
1217 		rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
1218 
1219 	pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
1220 	pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
1221 }
1222