GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / otus / hal / hpani.c
blob21464ecb3e5536a0587d60a4b276fb49bb7040cc
1 /*
2 * Copyright (c) 2007-2008 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #include "../80211core/cprecomp.h"
17 #include "hpani.h"
18 #include "hpusb.h"
21 extern u16_t zfDelayWriteInternalReg(zdev_t *dev, u32_t addr, u32_t val);
22 extern u16_t zfFlushDelayWrite(zdev_t *dev);
25 * Anti noise immunity support. We track phy errors and react
26 * to excessive errors by adjusting the noise immunity parameters.
29 /******************************************************************************
31 * New Ani Algorithm for Station side only
33 *****************************************************************************/
35 #define ZM_HAL_NOISE_IMMUNE_MAX 4 /* Max noise immunity level */
36 #define ZM_HAL_SPUR_IMMUNE_MAX 7 /* Max spur immunity level */
37 #define ZM_HAL_FIRST_STEP_MAX 2 /* Max first step level */
39 #define ZM_HAL_ANI_OFDM_TRIG_HIGH 500
40 #define ZM_HAL_ANI_OFDM_TRIG_LOW 200
41 #define ZM_HAL_ANI_CCK_TRIG_HIGH 200
42 #define ZM_HAL_ANI_CCK_TRIG_LOW 100
43 #define ZM_HAL_ANI_NOISE_IMMUNE_LVL 4
44 #define ZM_HAL_ANI_USE_OFDM_WEAK_SIG TRUE
45 #define ZM_HAL_ANI_CCK_WEAK_SIG_THR FALSE
46 #define ZM_HAL_ANI_SPUR_IMMUNE_LVL 7
47 #define ZM_HAL_ANI_FIRSTEP_LVL 0
48 #define ZM_HAL_ANI_RSSI_THR_HIGH 40
49 #define ZM_HAL_ANI_RSSI_THR_LOW 7
50 #define ZM_HAL_ANI_PERIOD 100
52 #define ZM_HAL_EP_RND(x, mul) \
53 ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
55 s32_t BEACON_RSSI(zdev_t *dev)
57 s32_t rssi;
58 struct zsHpPriv *HpPriv;
60 zmw_get_wlan_dev(dev);
61 HpPriv = (struct zsHpPriv *)wd->hpPrivate;
63 rssi = ZM_HAL_EP_RND(HpPriv->stats.ast_nodestats.ns_avgbrssi, ZM_HAL_RSSI_EP_MULTIPLIER);
65 return rssi;
69 * Setup ANI handling. Sets all thresholds and levels to default level AND
70 * resets the channel statistics
73 void zfHpAniAttach(zdev_t *dev)
75 u32_t i;
76 struct zsHpPriv *HpPriv;
78 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
79 const int coarseHigh[] = { -14, -14, -14, -14, -12 };
80 const int coarseLow[] = { -64, -64, -64, -64, -70 };
81 const int firpwr[] = { -78, -78, -78, -78, -80 };
83 zmw_get_wlan_dev(dev);
84 HpPriv = (struct zsHpPriv *)wd->hpPrivate;
86 for (i = 0; i < 5; i++) {
87 HpPriv->totalSizeDesired[i] = totalSizeDesired[i];
88 HpPriv->coarseHigh[i] = coarseHigh[i];
89 HpPriv->coarseLow[i] = coarseLow[i];
90 HpPriv->firpwr[i] = firpwr[i];
93 /* owl has phy counters */
94 HpPriv->hasHwPhyCounters = 1;
96 memset((char *)&HpPriv->ani, 0, sizeof(HpPriv->ani));
97 for (i = 0; i < ARRAY_SIZE(HpPriv->ani); i++) {
98 /* New ANI stuff */
99 HpPriv->ani[i].ofdmTrigHigh = ZM_HAL_ANI_OFDM_TRIG_HIGH;
100 HpPriv->ani[i].ofdmTrigLow = ZM_HAL_ANI_OFDM_TRIG_LOW;
101 HpPriv->ani[i].cckTrigHigh = ZM_HAL_ANI_CCK_TRIG_HIGH;
102 HpPriv->ani[i].cckTrigLow = ZM_HAL_ANI_CCK_TRIG_LOW;
103 HpPriv->ani[i].rssiThrHigh = ZM_HAL_ANI_RSSI_THR_HIGH;
104 HpPriv->ani[i].rssiThrLow = ZM_HAL_ANI_RSSI_THR_LOW;
105 HpPriv->ani[i].ofdmWeakSigDetectOff = !ZM_HAL_ANI_USE_OFDM_WEAK_SIG;
106 HpPriv->ani[i].cckWeakSigThreshold = ZM_HAL_ANI_CCK_WEAK_SIG_THR;
107 HpPriv->ani[i].spurImmunityLevel = ZM_HAL_ANI_SPUR_IMMUNE_LVL;
108 HpPriv->ani[i].firstepLevel = ZM_HAL_ANI_FIRSTEP_LVL;
109 if (HpPriv->hasHwPhyCounters) {
110 HpPriv->ani[i].ofdmPhyErrBase = 0;//AR_PHY_COUNTMAX - ZM_HAL_ANI_OFDM_TRIG_HIGH;
111 HpPriv->ani[i].cckPhyErrBase = 0;//AR_PHY_COUNTMAX - ZM_HAL_ANI_CCK_TRIG_HIGH;
114 if (HpPriv->hasHwPhyCounters) {
115 //zm_debug_msg2("Setting OfdmErrBase = 0x", HpPriv->ani[0].ofdmPhyErrBase);
116 //zm_debug_msg2("Setting cckErrBase = 0x", HpPriv->ani[0].cckPhyErrBase);
117 //OS_REG_WRITE(ah, AR_PHY_ERR_1, HpPriv->ani[0].ofdmPhyErrBase);
118 //OS_REG_WRITE(ah, AR_PHY_ERR_2, HpPriv->ani[0].cckPhyErrBase);
120 HpPriv->aniPeriod = ZM_HAL_ANI_PERIOD;
121 //if (ath_hal_enableANI)
122 HpPriv->procPhyErr |= ZM_HAL_PROCESS_ANI;
124 HpPriv->stats.ast_nodestats.ns_avgbrssi = ZM_RSSI_DUMMY_MARKER;
125 HpPriv->stats.ast_nodestats.ns_avgrssi = ZM_RSSI_DUMMY_MARKER;
126 HpPriv->stats.ast_nodestats.ns_avgtxrssi = ZM_RSSI_DUMMY_MARKER;
130 * Control Adaptive Noise Immunity Parameters
132 u8_t zfHpAniControl(zdev_t *dev, ZM_HAL_ANI_CMD cmd, int param)
134 typedef s32_t TABLE[];
135 struct zsHpPriv *HpPriv;
136 struct zsAniState *aniState;
138 zmw_get_wlan_dev(dev);
139 HpPriv = (struct zsHpPriv *)wd->hpPrivate;
140 aniState = HpPriv->curani;
142 switch (cmd)
144 case ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL:
146 u32_t level = param;
148 if (level >= ARRAY_SIZE(HpPriv->totalSizeDesired)) {
149 zm_debug_msg1("level out of range, desired level : ", level);
150 zm_debug_msg1("max level : ", ARRAY_SIZE(HpPriv->totalSizeDesired));
151 return FALSE;
154 zfDelayWriteInternalReg(dev, AR_PHY_DESIRED_SZ,
155 (HpPriv->regPHYDesiredSZ & ~AR_PHY_DESIRED_SZ_TOT_DES)
156 | ((HpPriv->totalSizeDesired[level] << AR_PHY_DESIRED_SZ_TOT_DES_S)
157 & AR_PHY_DESIRED_SZ_TOT_DES));
158 zfDelayWriteInternalReg(dev, AR_PHY_AGC_CTL1,
159 (HpPriv->regPHYAgcCtl1 & ~AR_PHY_AGC_CTL1_COARSE_LOW)
160 | ((HpPriv->coarseLow[level] << AR_PHY_AGC_CTL1_COARSE_LOW_S)
161 & AR_PHY_AGC_CTL1_COARSE_LOW));
162 zfDelayWriteInternalReg(dev, AR_PHY_AGC_CTL1,
163 (HpPriv->regPHYAgcCtl1 & ~AR_PHY_AGC_CTL1_COARSE_HIGH)
164 | ((HpPriv->coarseHigh[level] << AR_PHY_AGC_CTL1_COARSE_HIGH_S)
165 & AR_PHY_AGC_CTL1_COARSE_HIGH));
166 zfDelayWriteInternalReg(dev, AR_PHY_FIND_SIG,
167 (HpPriv->regPHYFindSig & ~AR_PHY_FIND_SIG_FIRPWR)
168 | ((HpPriv->firpwr[level] << AR_PHY_FIND_SIG_FIRPWR_S)
169 & AR_PHY_FIND_SIG_FIRPWR));
170 zfFlushDelayWrite(dev);
172 if (level > aniState->noiseImmunityLevel)
173 HpPriv->stats.ast_ani_niup++;
174 else if (level < aniState->noiseImmunityLevel)
175 HpPriv->stats.ast_ani_nidown++;
176 aniState->noiseImmunityLevel = (u8_t)level;
177 break;
179 case ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION:
181 const TABLE m1ThreshLow = { 127, 50 };
182 const TABLE m2ThreshLow = { 127, 40 };
183 const TABLE m1Thresh = { 127, 0x4d };
184 const TABLE m2Thresh = { 127, 0x40 };
185 const TABLE m2CountThr = { 31, 16 };
186 const TABLE m2CountThrLow = { 63, 48 };
187 u32_t on = param ? 1 : 0;
189 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
190 (HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_M1_THRESH_LOW)
191 | ((m1ThreshLow[on] << AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S)
192 & AR_PHY_SFCORR_LOW_M1_THRESH_LOW));
193 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
194 (HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_M2_THRESH_LOW)
195 | ((m2ThreshLow[on] << AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S)
196 & AR_PHY_SFCORR_LOW_M2_THRESH_LOW));
197 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR,
198 (HpPriv->regPHYSfcorr & ~AR_PHY_SFCORR_M1_THRESH)
199 | ((m1Thresh[on] << AR_PHY_SFCORR_M1_THRESH_S)
200 & AR_PHY_SFCORR_M1_THRESH));
201 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR,
202 (HpPriv->regPHYSfcorr & ~AR_PHY_SFCORR_M2_THRESH)
203 | ((m2Thresh[on] << AR_PHY_SFCORR_M2_THRESH_S)
204 & AR_PHY_SFCORR_M2_THRESH));
205 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR,
206 (HpPriv->regPHYSfcorr & ~AR_PHY_SFCORR_M2COUNT_THR)
207 | ((m2CountThr[on] << AR_PHY_SFCORR_M2COUNT_THR_S)
208 & AR_PHY_SFCORR_M2COUNT_THR));
209 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
210 (HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW)
211 | ((m2CountThrLow[on] << AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S)
212 & AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW));
214 if (on)
216 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
217 HpPriv->regPHYSfcorrLow | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
219 else
221 zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
222 HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
224 zfFlushDelayWrite(dev);
225 if (!on != aniState->ofdmWeakSigDetectOff)
227 if (on)
228 HpPriv->stats.ast_ani_ofdmon++;
229 else
230 HpPriv->stats.ast_ani_ofdmoff++;
231 aniState->ofdmWeakSigDetectOff = !on;
233 break;
235 case ZM_HAL_ANI_CCK_WEAK_SIGNAL_THR:
237 const TABLE weakSigThrCck = { 8, 6 };
238 u32_t high = param ? 1 : 0;
240 zfDelayWriteInternalReg(dev, AR_PHY_CCK_DETECT,
241 (HpPriv->regPHYCckDetect & ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK)
242 | ((weakSigThrCck[high] << AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S)
243 & AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK));
244 zfFlushDelayWrite(dev);
245 if (high != aniState->cckWeakSigThreshold)
247 if (high)
248 HpPriv->stats.ast_ani_cckhigh++;
249 else
250 HpPriv->stats.ast_ani_ccklow++;
251 aniState->cckWeakSigThreshold = (u8_t)high;
253 break;
255 case ZM_HAL_ANI_FIRSTEP_LEVEL:
257 const TABLE firstep = { 0, 4, 8 };
258 u32_t level = param;
260 if (level >= ARRAY_SIZE(firstep))
262 zm_debug_msg1("level out of range, desired level : ", level);
263 zm_debug_msg1("max level : ", ARRAY_SIZE(firstep));
264 return FALSE;
266 zfDelayWriteInternalReg(dev, AR_PHY_FIND_SIG,
267 (HpPriv->regPHYFindSig & ~AR_PHY_FIND_SIG_FIRSTEP)
268 | ((firstep[level] << AR_PHY_FIND_SIG_FIRSTEP_S)
269 & AR_PHY_FIND_SIG_FIRSTEP));
270 zfFlushDelayWrite(dev);
271 if (level > aniState->firstepLevel)
272 HpPriv->stats.ast_ani_stepup++;
273 else if (level < aniState->firstepLevel)
274 HpPriv->stats.ast_ani_stepdown++;
275 aniState->firstepLevel = (u8_t)level;
276 break;
278 case ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL:
280 const TABLE cycpwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 };
281 u32_t level = param;
283 if (level >= ARRAY_SIZE(cycpwrThr1))
285 zm_debug_msg1("level out of range, desired level : ", level);
286 zm_debug_msg1("max level : ", ARRAY_SIZE(cycpwrThr1));
287 return FALSE;
289 zfDelayWriteInternalReg(dev, AR_PHY_TIMING5,
290 (HpPriv->regPHYTiming5 & ~AR_PHY_TIMING5_CYCPWR_THR1)
291 | ((cycpwrThr1[level] << AR_PHY_TIMING5_CYCPWR_THR1_S)
292 & AR_PHY_TIMING5_CYCPWR_THR1));
293 zfFlushDelayWrite(dev);
294 if (level > aniState->spurImmunityLevel)
295 HpPriv->stats.ast_ani_spurup++;
296 else if (level < aniState->spurImmunityLevel)
297 HpPriv->stats.ast_ani_spurdown++;
298 aniState->spurImmunityLevel = (u8_t)level;
299 break;
301 case ZM_HAL_ANI_PRESENT:
302 break;
303 #ifdef AH_PRIVATE_DIAG
304 case ZM_HAL_ANI_MODE:
305 if (param == 0)
307 HpPriv->procPhyErr &= ~ZM_HAL_PROCESS_ANI;
308 /* Turn off HW counters if we have them */
309 zfHpAniDetach(dev);
310 //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) &~ HAL_RX_FILTER_PHYERR);
312 else
313 { /* normal/auto mode */
314 HpPriv->procPhyErr |= ZM_HAL_PROCESS_ANI;
315 if (HpPriv->hasHwPhyCounters)
317 //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) &~ HAL_RX_FILTER_PHYERR);
319 else
321 //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) | HAL_RX_FILTER_PHYERR);
324 break;
325 case ZM_HAL_ANI_PHYERR_RESET:
326 HpPriv->stats.ast_ani_ofdmerrs = 0;
327 HpPriv->stats.ast_ani_cckerrs = 0;
328 break;
329 #endif /* AH_PRIVATE_DIAG */
330 default:
331 zm_debug_msg1("invalid cmd ", cmd);
332 return FALSE;
334 return TRUE;
337 void zfHpAniRestart(zdev_t* dev)
339 struct zsAniState *aniState;
340 struct zsHpPriv *HpPriv;
342 zmw_get_wlan_dev(dev);
343 HpPriv = (struct zsHpPriv*)wd->hpPrivate;
344 aniState = HpPriv->curani;
346 aniState->listenTime = 0;
347 if (HpPriv->hasHwPhyCounters)
349 //if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX)
351 // aniState->ofdmPhyErrBase = 0;
352 // zm_debug_msg0("OFDM Trigger is too high for hw counters");
354 //else
355 // aniState->ofdmPhyErrBase = AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
356 //if (aniState->cckTrigHigh > AR_PHY_COUNTMAX)
358 // aniState->cckPhyErrBase = 0;
359 // zm_debug_msg0("CCK Trigger is too high for hw counters");
361 //else
362 // aniState->cckPhyErrBase = AR_PHY_COUNTMAX - aniState->cckTrigHigh;
363 //zm_debug_msg2("Writing ofdmbase = 0x", aniState->ofdmPhyErrBase);
364 //zm_debug_msg2("Writing cckbase = 0x", aniState->cckPhyErrBase);
365 //OS_REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
366 //OS_REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
367 //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
368 //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
369 aniState->ofdmPhyErrBase = 0;
370 aniState->cckPhyErrBase = 0;
372 aniState->ofdmPhyErrCount = 0;
373 aniState->cckPhyErrCount = 0;
376 void zfHpAniOfdmErrTrigger(zdev_t* dev)
378 struct zsAniState *aniState;
379 s32_t rssi;
380 struct zsHpPriv *HpPriv;
382 zmw_get_wlan_dev(dev);
383 HpPriv = (struct zsHpPriv*)wd->hpPrivate;
385 //HALASSERT(chan != NULL);
387 if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
388 return;
390 aniState = HpPriv->curani;
391 /* First, raise noise immunity level, up to max */
392 if (aniState->noiseImmunityLevel < ZM_HAL_NOISE_IMMUNE_MAX)
394 zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1);
395 return;
397 /* then, raise spur immunity level, up to max */
398 if (aniState->spurImmunityLevel < ZM_HAL_SPUR_IMMUNE_MAX)
400 zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel + 1);
401 return;
403 rssi = BEACON_RSSI(dev);
404 if (rssi > aniState->rssiThrHigh)
407 * Beacon rssi is high, can turn off ofdm weak sig detect.
409 if (!aniState->ofdmWeakSigDetectOff)
411 zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, FALSE);
412 zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
413 return;
416 * If weak sig detect is already off, as last resort, raise
417 * first step level
419 if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
421 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
422 return;
425 else if (rssi > aniState->rssiThrLow)
428 * Beacon rssi in mid range, need ofdm weak signal detect,
429 * but we can raise firststepLevel
431 if (aniState->ofdmWeakSigDetectOff)
432 zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, TRUE);
433 if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
434 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
435 return;
437 else
440 * Beacon rssi is low, if in 11b/g mode, turn off ofdm
441 * weak sign detction and zero firstepLevel to maximize
442 * CCK sensitivity
444 if (wd->frequency < 3000)
446 if (!aniState->ofdmWeakSigDetectOff)
447 zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, FALSE);
448 if (aniState->firstepLevel > 0)
449 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, 0);
450 return;
455 void zfHpAniCckErrTrigger(zdev_t* dev)
457 struct zsAniState *aniState;
458 s32_t rssi;
459 struct zsHpPriv *HpPriv;
461 zmw_get_wlan_dev(dev);
462 HpPriv = (struct zsHpPriv*)wd->hpPrivate;
464 //HALASSERT(chan != NULL);
466 if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
467 return;
469 /* first, raise noise immunity level, up to max */
470 aniState = HpPriv->curani;
471 if (aniState->noiseImmunityLevel < ZM_HAL_NOISE_IMMUNE_MAX)
473 zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL,
474 aniState->noiseImmunityLevel + 1);
475 return;
477 rssi = BEACON_RSSI(dev);
478 if (rssi > aniState->rssiThrLow)
481 * Beacon signal in mid and high range, raise firsteplevel.
483 if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
484 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
486 else
489 * Beacon rssi is low, zero firstepLevel to maximize
490 * CCK sensitivity.
492 if (wd->frequency < 3000)
494 if (aniState->firstepLevel > 0)
495 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, 0);
500 void zfHpAniLowerImmunity(zdev_t* dev)
502 struct zsAniState *aniState;
503 s32_t rssi;
504 struct zsHpPriv *HpPriv;
506 zmw_get_wlan_dev(dev);
507 HpPriv = (struct zsHpPriv*)wd->hpPrivate;
508 aniState = HpPriv->curani;
510 rssi = BEACON_RSSI(dev);
511 if (rssi > aniState->rssiThrHigh)
514 * Beacon signal is high, leave ofdm weak signal detection off
515 * or it may oscillate. Let it fall through.
518 else if (rssi > aniState->rssiThrLow)
521 * Beacon rssi in mid range, turn on ofdm weak signal
522 * detection or lower first step level.
524 if (aniState->ofdmWeakSigDetectOff)
526 zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, TRUE);
527 return;
529 if (aniState->firstepLevel > 0)
531 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1);
532 return;
535 else
538 * Beacon rssi is low, reduce first step level.
540 if (aniState->firstepLevel > 0)
542 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1);
543 return;
546 /* then lower spur immunity level, down to zero */
547 if (aniState->spurImmunityLevel > 0)
549 zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel - 1);
550 return;
553 * if all else fails, lower noise immunity level down to a min value
554 * zero for now
556 if (aniState->noiseImmunityLevel > 0)
558 zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel - 1);
559 return;
563 #define CLOCK_RATE 44000
564 /* convert HW counter values to ms using 11g clock rate, goo9d enough
565 for 11a and Turbo */
568 * Return an approximation of the time spent ``listening'' by
569 * deducting the cycles spent tx'ing and rx'ing from the total
570 * cycle count since our last call. A return value <0 indicates
571 * an invalid/inconsistent time.
573 s32_t zfHpAniGetListenTime(zdev_t* dev)
575 struct zsAniState *aniState;
576 u32_t txFrameCount, rxFrameCount, cycleCount;
577 s32_t listenTime;
578 struct zsHpPriv *HpPriv;
580 zmw_get_wlan_dev(dev);
581 HpPriv = (struct zsHpPriv*)wd->hpPrivate;
583 txFrameCount = 0;//OS_REG_READ(ah, AR_TFCNT);
584 rxFrameCount = 0;//OS_REG_READ(ah, AR_RFCNT);
585 cycleCount = 0;//OS_REG_READ(ah, AR_CCCNT);
587 aniState = HpPriv->curani;
588 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount)
591 * Cycle counter wrap (or initial call); it's not possible
592 * to accurately calculate a value because the registers
593 * right shift rather than wrap--so punt and return 0.
595 listenTime = 0;
596 HpPriv->stats.ast_ani_lzero++;
598 else
600 s32_t ccdelta = cycleCount - aniState->cycleCount;
601 s32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
602 s32_t tfdelta = txFrameCount - aniState->txFrameCount;
603 listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
605 aniState->cycleCount = cycleCount;
606 aniState->txFrameCount = txFrameCount;
607 aniState->rxFrameCount = rxFrameCount;
608 return listenTime;
612 * Do periodic processing. This routine is called from the
613 * driver's rx interrupt handler after processing frames.
615 void zfHpAniArPoll(zdev_t* dev, u32_t listenTime, u32_t phyCnt1, u32_t phyCnt2)
617 struct zsAniState *aniState;
618 //s32_t listenTime;
619 struct zsHpPriv *HpPriv;
621 zmw_get_wlan_dev(dev);
622 HpPriv = (struct zsHpPriv*)wd->hpPrivate;
625 * Since we're called from end of rx tasklet, we also check for
626 * AR processing now
629 aniState = HpPriv->curani;
630 //HpPriv->stats.ast_nodestats = *stats;
632 //listenTime = zfHpAniGetListenTime(dev);
633 //if (listenTime < 0)
635 // HpPriv->stats.ast_ani_lneg++;
636 // /* restart ANI period if listenTime is invalid */
637 // zfHpAniRestart(dev);
638 // return;
640 aniState->listenTime += listenTime;
642 if (HpPriv->hasHwPhyCounters)
644 //u32_t phyCnt1, phyCnt2;
645 u32_t ofdmPhyErrCnt, cckPhyErrCnt;
647 /* NB: these are not reset-on-read */
648 //phyCnt1 = 0;//OS_REG_READ(ah, AR_PHY_ERR_1);
649 //phyCnt2 = 0;//OS_REG_READ(ah, AR_PHY_ERR_2);
650 //if (phyCnt1 < aniState->ofdmPhyErrBase ||
651 // phyCnt2 < aniState->cckPhyErrBase)
653 // if (phyCnt1 < aniState->ofdmPhyErrBase)
654 // {
655 // zm_debug_msg2("phyCnt1 = 0x", phyCnt1);
656 // zm_debug_msg2("resetting counter value to 0x", aniState->ofdmPhyErrBase);
657 // //OS_REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
658 // //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
659 // }
660 // if (phyCnt2 < aniState->cckPhyErrBase)
661 // {
662 // zm_debug_msg2("phyCnt2 = 0x", phyCnt2);
663 // zm_debug_msg2("resetting counter value to 0x", aniState->cckPhyErrBase);
664 // //OS_REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
665 // //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
666 // }
667 // return;
669 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
670 //ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
671 //HpPriv->stats.ast_ani_ofdmerrs += ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
672 //aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
673 ofdmPhyErrCnt = phyCnt1;
674 HpPriv->stats.ast_ani_ofdmerrs += ofdmPhyErrCnt;
675 aniState->ofdmPhyErrCount += ofdmPhyErrCnt;
677 //cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
678 //HpPriv->stats.ast_ani_cckerrs += cckPhyErrCnt - aniState->cckPhyErrCount;
679 //aniState->cckPhyErrCount = cckPhyErrCnt;
680 cckPhyErrCnt = phyCnt2;
681 HpPriv->stats.ast_ani_cckerrs += cckPhyErrCnt;
682 aniState->cckPhyErrCount += cckPhyErrCnt;
685 * If ani is not enabled, return after we've collected
686 * statistics
688 if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
689 return;
690 if (aniState->listenTime > 5 * HpPriv->aniPeriod)
693 * Check to see if need to lower immunity if
694 * 5 aniPeriods have passed
696 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
697 aniState->ofdmTrigLow/1000 &&
698 aniState->cckPhyErrCount <= aniState->listenTime *
699 aniState->cckTrigLow/1000)
700 zfHpAniLowerImmunity(dev);
701 zfHpAniRestart(dev);
703 else if (aniState->listenTime > HpPriv->aniPeriod)
705 /* check to see if need to raise immunity */
706 if (aniState->ofdmPhyErrCount > aniState->listenTime *
707 aniState->ofdmTrigHigh / 1000)
709 zfHpAniOfdmErrTrigger(dev);
710 zfHpAniRestart(dev);
712 else if (aniState->cckPhyErrCount > aniState->listenTime *
713 aniState->cckTrigHigh / 1000)
715 zfHpAniCckErrTrigger(dev);
716 zfHpAniRestart(dev);