upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / staging / otus / hal / hpani.c
1 /*
2  * Copyright (c) 2007-2008 Atheros Communications Inc.
3  *
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.
7  *
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.
15  */
16 #include "../80211core/cprecomp.h"
17 #include "hpani.h"
18 #include "hpusb.h"
19
20
21 extern u16_t zfDelayWriteInternalReg(zdev_t *dev, u32_t addr, u32_t val);
22 extern u16_t zfFlushDelayWrite(zdev_t *dev);
23
24 /*
25  * Anti noise immunity support.  We track phy errors and react
26  * to excessive errors by adjusting the noise immunity parameters.
27  */
28
29 /******************************************************************************
30  *
31  * New Ani Algorithm for Station side only
32  *
33  *****************************************************************************/
34
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 */
38
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
51
52 #define ZM_HAL_EP_RND(x, mul) \
53     ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
54
55 s32_t BEACON_RSSI(zdev_t *dev)
56 {
57     s32_t rssi;
58     struct zsHpPriv *HpPriv;
59
60     zmw_get_wlan_dev(dev);
61     HpPriv = (struct zsHpPriv *)wd->hpPrivate;
62
63     rssi = ZM_HAL_EP_RND(HpPriv->stats.ast_nodestats.ns_avgbrssi, ZM_HAL_RSSI_EP_MULTIPLIER);
64
65     return rssi;
66 }
67
68 /*
69  * Setup ANI handling.  Sets all thresholds and levels to default level AND
70  * resets the channel statistics
71  */
72
73 void zfHpAniAttach(zdev_t *dev)
74 {
75     u32_t i;
76     struct zsHpPriv *HpPriv;
77
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 };
82
83     zmw_get_wlan_dev(dev);
84     HpPriv = (struct zsHpPriv *)wd->hpPrivate;
85
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];
91     }
92
93     /* owl has phy counters */
94     HpPriv->hasHwPhyCounters = 1;
95
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;
112         }
113     }
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);
119     }
120     HpPriv->aniPeriod = ZM_HAL_ANI_PERIOD;
121     //if (ath_hal_enableANI)
122     HpPriv->procPhyErr |= ZM_HAL_PROCESS_ANI;
123
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;
127 }
128
129 /*
130  * Control Adaptive Noise Immunity Parameters
131  */
132 u8_t zfHpAniControl(zdev_t *dev, ZM_HAL_ANI_CMD cmd, int param)
133 {
134     typedef s32_t TABLE[];
135     struct zsHpPriv *HpPriv;
136     struct zsAniState *aniState;
137
138     zmw_get_wlan_dev(dev);
139     HpPriv = (struct zsHpPriv *)wd->hpPrivate;
140     aniState = HpPriv->curani;
141
142     switch (cmd)
143     {
144     case ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL:
145     {
146         u32_t level = param;
147
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;
152         }
153
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);
171
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;
178     }
179     case ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION:
180     {
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;
188
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));
213
214         if (on)
215         {
216             zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
217                     HpPriv->regPHYSfcorrLow | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
218         }
219         else
220         {
221             zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
222                     HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
223         }
224         zfFlushDelayWrite(dev);
225         if (!on != aniState->ofdmWeakSigDetectOff)
226         {
227             if (on)
228                 HpPriv->stats.ast_ani_ofdmon++;
229             else
230                 HpPriv->stats.ast_ani_ofdmoff++;
231             aniState->ofdmWeakSigDetectOff = !on;
232         }
233         break;
234     }
235     case ZM_HAL_ANI_CCK_WEAK_SIGNAL_THR:
236     {
237         const TABLE weakSigThrCck = { 8, 6 };
238         u32_t high = param ? 1 : 0;
239
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)
246         {
247             if (high)
248                 HpPriv->stats.ast_ani_cckhigh++;
249             else
250                 HpPriv->stats.ast_ani_ccklow++;
251             aniState->cckWeakSigThreshold = (u8_t)high;
252         }
253         break;
254     }
255     case ZM_HAL_ANI_FIRSTEP_LEVEL:
256     {
257         const TABLE firstep = { 0, 4, 8 };
258         u32_t level = param;
259
260         if (level >= ARRAY_SIZE(firstep))
261         {
262             zm_debug_msg1("level out of range, desired level : ", level);
263             zm_debug_msg1("max level : ", ARRAY_SIZE(firstep));
264             return FALSE;
265         }
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;
277     }
278     case ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL:
279     {
280         const TABLE cycpwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 };
281         u32_t level = param;
282
283         if (level >= ARRAY_SIZE(cycpwrThr1))
284         {
285             zm_debug_msg1("level out of range, desired level : ", level);
286             zm_debug_msg1("max level : ", ARRAY_SIZE(cycpwrThr1));
287             return FALSE;
288         }
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;
300     }
301     case ZM_HAL_ANI_PRESENT:
302         break;
303 #ifdef AH_PRIVATE_DIAG
304     case ZM_HAL_ANI_MODE:
305         if (param == 0)
306         {
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);
311         }
312         else
313         {           /* normal/auto mode */
314             HpPriv->procPhyErr |= ZM_HAL_PROCESS_ANI;
315             if (HpPriv->hasHwPhyCounters)
316             {
317                 //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) &~ HAL_RX_FILTER_PHYERR);
318             }
319             else
320             {
321                 //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) | HAL_RX_FILTER_PHYERR);
322             }
323         }
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;
333     }
334     return TRUE;
335 }
336
337 void zfHpAniRestart(zdev_t* dev)
338 {
339     struct zsAniState *aniState;
340     struct zsHpPriv *HpPriv;
341
342     zmw_get_wlan_dev(dev);
343     HpPriv = (struct zsHpPriv*)wd->hpPrivate;
344     aniState = HpPriv->curani;
345
346     aniState->listenTime = 0;
347     if (HpPriv->hasHwPhyCounters)
348     {
349         //if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX)
350         //{
351         //    aniState->ofdmPhyErrBase = 0;
352         //    zm_debug_msg0("OFDM Trigger is too high for hw counters");
353         //}
354         //else
355         //    aniState->ofdmPhyErrBase = AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
356         //if (aniState->cckTrigHigh > AR_PHY_COUNTMAX)
357         //{
358         //    aniState->cckPhyErrBase = 0;
359         //    zm_debug_msg0("CCK Trigger is too high for hw counters");
360         //}
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;
371     }
372     aniState->ofdmPhyErrCount = 0;
373     aniState->cckPhyErrCount = 0;
374 }
375
376 void zfHpAniOfdmErrTrigger(zdev_t* dev)
377 {
378     struct zsAniState *aniState;
379     s32_t rssi;
380     struct zsHpPriv *HpPriv;
381
382     zmw_get_wlan_dev(dev);
383     HpPriv = (struct zsHpPriv*)wd->hpPrivate;
384
385     //HALASSERT(chan != NULL);
386
387     if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
388         return;
389
390     aniState = HpPriv->curani;
391     /* First, raise noise immunity level, up to max */
392     if (aniState->noiseImmunityLevel < ZM_HAL_NOISE_IMMUNE_MAX)
393     {
394         zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1);
395         return;
396     }
397     /* then, raise spur immunity level, up to max */
398     if (aniState->spurImmunityLevel < ZM_HAL_SPUR_IMMUNE_MAX)
399     {
400         zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel + 1);
401         return;
402     }
403     rssi = BEACON_RSSI(dev);
404     if (rssi > aniState->rssiThrHigh)
405     {
406         /*
407          * Beacon rssi is high, can turn off ofdm weak sig detect.
408          */
409         if (!aniState->ofdmWeakSigDetectOff)
410         {
411             zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, FALSE);
412             zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
413             return;
414         }
415         /*
416          * If weak sig detect is already off, as last resort, raise
417          * first step level
418          */
419         if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
420         {
421             zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
422             return;
423         }
424     }
425     else if (rssi > aniState->rssiThrLow)
426     {
427         /*
428          * Beacon rssi in mid range, need ofdm weak signal detect,
429          * but we can raise firststepLevel
430          */
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;
436     }
437     else
438     {
439         /*
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
443          */
444         if (wd->frequency < 3000)
445         {
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;
451         }
452     }
453 }
454
455 void zfHpAniCckErrTrigger(zdev_t* dev)
456 {
457     struct zsAniState *aniState;
458     s32_t rssi;
459     struct zsHpPriv *HpPriv;
460
461     zmw_get_wlan_dev(dev);
462     HpPriv = (struct zsHpPriv*)wd->hpPrivate;
463
464     //HALASSERT(chan != NULL);
465
466     if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
467         return;
468
469     /* first, raise noise immunity level, up to max */
470     aniState = HpPriv->curani;
471     if (aniState->noiseImmunityLevel < ZM_HAL_NOISE_IMMUNE_MAX)
472     {
473         zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL,
474                  aniState->noiseImmunityLevel + 1);
475         return;
476     }
477     rssi = BEACON_RSSI(dev);
478     if (rssi >  aniState->rssiThrLow)
479     {
480         /*
481          * Beacon signal in mid and high range, raise firsteplevel.
482          */
483         if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
484             zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
485     }
486     else
487     {
488         /*
489          * Beacon rssi is low, zero firstepLevel to maximize
490          * CCK sensitivity.
491          */
492         if (wd->frequency < 3000)
493         {
494             if (aniState->firstepLevel > 0)
495                 zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, 0);
496         }
497     }
498 }
499
500 void zfHpAniLowerImmunity(zdev_t* dev)
501 {
502     struct zsAniState *aniState;
503     s32_t rssi;
504     struct zsHpPriv *HpPriv;
505
506     zmw_get_wlan_dev(dev);
507     HpPriv = (struct zsHpPriv*)wd->hpPrivate;
508     aniState = HpPriv->curani;
509
510     rssi = BEACON_RSSI(dev);
511     if (rssi > aniState->rssiThrHigh)
512     {
513         /*
514          * Beacon signal is high, leave ofdm weak signal detection off
515          * or it may oscillate. Let it fall through.
516          */
517     }
518     else if (rssi > aniState->rssiThrLow)
519     {
520         /*
521          * Beacon rssi in mid range, turn on ofdm weak signal
522          * detection or lower first step level.
523          */
524         if (aniState->ofdmWeakSigDetectOff)
525         {
526             zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, TRUE);
527             return;
528         }
529         if (aniState->firstepLevel > 0)
530         {
531             zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1);
532             return;
533         }
534     }
535     else
536     {
537         /*
538          * Beacon rssi is low, reduce first step level.
539          */
540         if (aniState->firstepLevel > 0)
541         {
542             zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1);
543             return;
544         }
545     }
546     /* then lower spur immunity level, down to zero */
547     if (aniState->spurImmunityLevel > 0)
548     {
549         zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel - 1);
550         return;
551     }
552     /*
553      * if all else fails, lower noise immunity level down to a min value
554      * zero for now
555      */
556     if (aniState->noiseImmunityLevel > 0)
557     {
558         zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel - 1);
559         return;
560     }
561 }
562
563 #define CLOCK_RATE 44000    /* XXX use mac_usec or similar */
564 /* convert HW counter values to ms using 11g clock rate, goo9d enough
565    for 11a and Turbo */
566
567 /*
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.
572  */
573 s32_t zfHpAniGetListenTime(zdev_t* dev)
574 {
575     struct zsAniState *aniState;
576     u32_t txFrameCount, rxFrameCount, cycleCount;
577     s32_t listenTime;
578     struct zsHpPriv *HpPriv;
579
580     zmw_get_wlan_dev(dev);
581     HpPriv = (struct zsHpPriv*)wd->hpPrivate;
582
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);
586
587     aniState = HpPriv->curani;
588     if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount)
589     {
590         /*
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.
594          */
595         listenTime = 0;
596         HpPriv->stats.ast_ani_lzero++;
597     }
598     else
599     {
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;
604     }
605     aniState->cycleCount = cycleCount;
606     aniState->txFrameCount = txFrameCount;
607     aniState->rxFrameCount = rxFrameCount;
608     return listenTime;
609 }
610
611 /*
612  * Do periodic processing.  This routine is called from the
613  * driver's rx interrupt handler after processing frames.
614  */
615 void zfHpAniArPoll(zdev_t* dev, u32_t listenTime, u32_t phyCnt1, u32_t phyCnt2)
616 {
617     struct zsAniState *aniState;
618     //s32_t listenTime;
619     struct zsHpPriv *HpPriv;
620
621     zmw_get_wlan_dev(dev);
622     HpPriv = (struct zsHpPriv*)wd->hpPrivate;
623
624     /*
625      * Since we're called from end of rx tasklet, we also check for
626      * AR processing now
627      */
628
629     aniState = HpPriv->curani;
630     //HpPriv->stats.ast_nodestats = *stats;       /* XXX optimize? */
631
632     //listenTime = zfHpAniGetListenTime(dev);
633     //if (listenTime < 0)
634     //{
635     //    HpPriv->stats.ast_ani_lneg++;
636     //    /* restart ANI period if listenTime is invalid */
637     //    zfHpAniRestart(dev);
638     //    return;
639     //}
640     /* XXX beware of overflow? */
641     aniState->listenTime += listenTime;
642
643     if (HpPriv->hasHwPhyCounters)
644     {
645         //u32_t phyCnt1, phyCnt2;
646         u32_t ofdmPhyErrCnt, cckPhyErrCnt;
647
648         /* NB: these are not reset-on-read */
649         //phyCnt1 = 0;//OS_REG_READ(ah, AR_PHY_ERR_1);
650         //phyCnt2 = 0;//OS_REG_READ(ah, AR_PHY_ERR_2);
651         /* XXX sometimes zero, why? */
652         //if (phyCnt1 < aniState->ofdmPhyErrBase ||
653         //    phyCnt2 < aniState->cckPhyErrBase)
654         //{
655         //    if (phyCnt1 < aniState->ofdmPhyErrBase)
656         //    {
657         //        zm_debug_msg2("phyCnt1 = 0x", phyCnt1);
658         //        zm_debug_msg2("resetting counter value to 0x", aniState->ofdmPhyErrBase);
659         //        //OS_REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
660         //        //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
661         //    }
662         //    if (phyCnt2 < aniState->cckPhyErrBase)
663         //    {
664         //        zm_debug_msg2("phyCnt2 = 0x", phyCnt2);
665         //        zm_debug_msg2("resetting counter value to 0x", aniState->cckPhyErrBase);
666         //        //OS_REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
667         //        //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
668         //    }
669         //    return;     /* XXX */
670         //}
671         /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
672         //ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
673         //HpPriv->stats.ast_ani_ofdmerrs += ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
674         //aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
675         ofdmPhyErrCnt = phyCnt1;
676         HpPriv->stats.ast_ani_ofdmerrs += ofdmPhyErrCnt;
677         aniState->ofdmPhyErrCount += ofdmPhyErrCnt;
678
679         //cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
680         //HpPriv->stats.ast_ani_cckerrs += cckPhyErrCnt - aniState->cckPhyErrCount;
681         //aniState->cckPhyErrCount = cckPhyErrCnt;
682         cckPhyErrCnt = phyCnt2;
683         HpPriv->stats.ast_ani_cckerrs += cckPhyErrCnt;
684         aniState->cckPhyErrCount += cckPhyErrCnt;
685     }
686     /*
687      * If ani is not enabled, return after we've collected
688      * statistics
689      */
690     if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
691         return;
692     if (aniState->listenTime > 5 * HpPriv->aniPeriod)
693     {
694         /*
695          * Check to see if need to lower immunity if
696          * 5 aniPeriods have passed
697          */
698         if (aniState->ofdmPhyErrCount <= aniState->listenTime *
699              aniState->ofdmTrigLow/1000 &&
700             aniState->cckPhyErrCount <= aniState->listenTime *
701              aniState->cckTrigLow/1000)
702             zfHpAniLowerImmunity(dev);
703         zfHpAniRestart(dev);
704     }
705     else if (aniState->listenTime > HpPriv->aniPeriod)
706     {
707         /* check to see if need to raise immunity */
708         if (aniState->ofdmPhyErrCount > aniState->listenTime *
709             aniState->ofdmTrigHigh / 1000)
710         {
711             zfHpAniOfdmErrTrigger(dev);
712             zfHpAniRestart(dev);
713         }
714         else if (aniState->cckPhyErrCount > aniState->listenTime *
715                aniState->cckTrigHigh / 1000)
716         {
717             zfHpAniCckErrTrigger(dev);
718             zfHpAniRestart(dev);
719         }
720     }
721 }