• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/otus/hal/
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
21extern u16_t zfDelayWriteInternalReg(zdev_t *dev, u32_t addr, u32_t val);
22extern 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
55s32_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
73void 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 */
132u8_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
337void 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
376void 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
455void 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
500void 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
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 */
573s32_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 */
615void 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;
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    aniState->listenTime += listenTime;
641
642    if (HpPriv->hasHwPhyCounters)
643    {
644        //u32_t phyCnt1, phyCnt2;
645        u32_t ofdmPhyErrCnt, cckPhyErrCnt;
646
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)
652        //{
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;
668        //}
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;
676
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;
683    }
684    /*
685     * If ani is not enabled, return after we've collected
686     * statistics
687     */
688    if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
689        return;
690    if (aniState->listenTime > 5 * HpPriv->aniPeriod)
691    {
692        /*
693         * Check to see if need to lower immunity if
694         * 5 aniPeriods have passed
695         */
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);
702    }
703    else if (aniState->listenTime > HpPriv->aniPeriod)
704    {
705        /* check to see if need to raise immunity */
706        if (aniState->ofdmPhyErrCount > aniState->listenTime *
707            aniState->ofdmTrigHigh / 1000)
708        {
709            zfHpAniOfdmErrTrigger(dev);
710            zfHpAniRestart(dev);
711        }
712        else if (aniState->cckPhyErrCount > aniState->listenTime *
713               aniState->cckTrigHigh / 1000)
714        {
715            zfHpAniCckErrTrigger(dev);
716            zfHpAniRestart(dev);
717        }
718    }
719}
720