The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 
   26 #include "ar5212/ar5212.h"
   27 #include "ar5212/ar5212reg.h"
   28 #include "ar5212/ar5212desc.h"
   29 
   30 /*
   31  * Return the hardware NextTBTT in TSF
   32  */
   33 uint64_t
   34 ar5212GetNextTBTT(struct ath_hal *ah)
   35 {
   36 #define TU_TO_TSF(_tu)  (((uint64_t)(_tu)) << 10)
   37         return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0));
   38 #undef TU_TO_TSF
   39 }
   40 
   41 /*
   42  * Initialize all of the hardware registers used to
   43  * send beacons.  Note that for station operation the
   44  * driver calls ar5212SetStaBeaconTimers instead.
   45  */
   46 void
   47 ar5212SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
   48 {
   49         struct ath_hal_5212 *ahp = AH5212(ah);
   50 
   51         /*
   52          * Limit the timers to their specific resolutions:
   53          *
   54          * + Timer 0 - 0..15 0xffff TU
   55          * + Timer 1 - 0..18 0x7ffff TU/8
   56          * + Timer 2 - 0..24 0x1ffffff TU/8
   57          * + Timer 3 - 0..15 0xffff TU
   58          */
   59         OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt & 0xffff);
   60         OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba & 0x7ffff);
   61         OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba & 0x1ffffff);
   62         /* XXX force nextatim to be non-zero? */
   63         OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim & 0xffff);
   64         /*
   65          * Set the Beacon register after setting all timers.
   66          */
   67         if (bt->bt_intval & AR_BEACON_RESET_TSF) {
   68                 /*
   69                  * When resetting the TSF,
   70                  * write twice to the corresponding register; each
   71                  * write to the RESET_TSF bit toggles the internal
   72                  * signal to cause a reset of the TSF - but if the signal
   73                  * is left high, it will reset the TSF on the next
   74                  * chip reset also! writing the bit an even number
   75                  * of times fixes this issue
   76                  */
   77                 OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_RESET_TSF);
   78         }
   79         OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval);
   80         ahp->ah_beaconInterval = (bt->bt_intval & HAL_BEACON_PERIOD);
   81 }
   82 
   83 /*
   84  * Old api for setting up beacon timer registers when
   85  * operating in !station mode.  Note the fixed constants
   86  * adjusting the DBA and SWBA timers and the fixed ATIM
   87  * window.
   88  */
   89 void
   90 ar5212BeaconInit(struct ath_hal *ah,
   91         uint32_t next_beacon, uint32_t beacon_period)
   92 {
   93         HAL_BEACON_TIMERS bt;
   94 
   95         bt.bt_nexttbtt = next_beacon;
   96         /* 
   97          * TIMER1: in AP/adhoc mode this controls the DMA beacon
   98          * alert timer; otherwise it controls the next wakeup time.
   99          * TIMER2: in AP mode, it controls the SBA beacon alert
  100          * interrupt; otherwise it sets the start of the next CFP.
  101          */
  102         switch (AH_PRIVATE(ah)->ah_opmode) {
  103         case HAL_M_STA:
  104         case HAL_M_MONITOR:
  105                 bt.bt_nextdba = 0xffff;
  106                 bt.bt_nextswba = 0x7ffff;
  107                 break;
  108         case HAL_M_HOSTAP:
  109         case HAL_M_IBSS:
  110                 bt.bt_nextdba = (next_beacon -
  111                     ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */
  112                 bt.bt_nextswba = (next_beacon -
  113                     ah->ah_config.ah_sw_beacon_response_time) << 3;     /* 1/8 TU */
  114                 break;
  115         }
  116         /*
  117          * Set the ATIM window 
  118          * Our hardware does not support an ATIM window of 0
  119          * (beacons will not work).  If the ATIM windows is 0,
  120          * force it to 1.
  121          */
  122         bt.bt_nextatim = next_beacon + 1;
  123         bt.bt_intval = beacon_period &
  124                 (AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
  125         ar5212SetBeaconTimers(ah, &bt);
  126 }
  127 
  128 void
  129 ar5212ResetStaBeaconTimers(struct ath_hal *ah)
  130 {
  131         uint32_t val;
  132 
  133         OS_REG_WRITE(ah, AR_TIMER0, 0);         /* no beacons */
  134         val = OS_REG_READ(ah, AR_STA_ID1);
  135         val |= AR_STA_ID1_PWR_SAV;              /* XXX */
  136         /* tell the h/w that the associated AP is not PCF capable */
  137         OS_REG_WRITE(ah, AR_STA_ID1,
  138                 val & ~(AR_STA_ID1_USE_DEFANT | AR_STA_ID1_PCF));
  139         OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD);
  140 }
  141 
  142 /*
  143  * Set all the beacon related bits on the h/w for stations
  144  * i.e. initializes the corresponding h/w timers;
  145  * also tells the h/w whether to anticipate PCF beacons
  146  */
  147 void
  148 ar5212SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
  149 {
  150         struct ath_hal_5212 *ahp = AH5212(ah);
  151         uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod;
  152 
  153         HALASSERT(bs->bs_intval != 0);
  154         /* if the AP will do PCF */
  155         if (bs->bs_cfpmaxduration != 0) {
  156                 /* tell the h/w that the associated AP is PCF capable */
  157                 OS_REG_WRITE(ah, AR_STA_ID1,
  158                         OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF);
  159 
  160                 /* set CFP_PERIOD(1.024ms) register */
  161                 OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod);
  162 
  163                 /* set CFP_DUR(1.024ms) register to max cfp duration */
  164                 OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration);
  165 
  166                 /* set TIMER2(128us) to anticipated time of next CFP */
  167                 OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3);
  168         } else {
  169                 /* tell the h/w that the associated AP is not PCF capable */
  170                 OS_REG_WRITE(ah, AR_STA_ID1,
  171                         OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF);
  172         }
  173 
  174         /*
  175          * Set TIMER0(1.024ms) to the anticipated time of the next beacon.
  176          */
  177         OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt);
  178 
  179         /*
  180          * Start the beacon timers by setting the BEACON register
  181          * to the beacon interval; also write the tim offset which
  182          * we should know by now.  The code, in ar5211WriteAssocid,
  183          * also sets the tim offset once the AID is known which can
  184          * be left as such for now.
  185          */
  186         OS_REG_WRITE(ah, AR_BEACON, 
  187                 (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM))
  188                 | SM(bs->bs_intval, AR_BEACON_PERIOD)
  189                 | SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM)
  190         );
  191 
  192         /*
  193          * Configure the BMISS interrupt.  Note that we
  194          * assume the caller blocks interrupts while enabling
  195          * the threshold.
  196          */
  197         HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR));
  198         ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR)
  199                         | SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR);
  200         OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
  201 
  202         /*
  203          * Program the sleep registers to correlate with the beacon setup.
  204          */
  205 
  206         /*
  207          * Oahu beacons timers on the station were used for power
  208          * save operation (waking up in anticipation of a beacon)
  209          * and any CFP function; Venice does sleep/power-save timers
  210          * differently - so this is the right place to set them up;
  211          * don't think the beacon timers are used by venice sta hw
  212          * for any useful purpose anymore
  213          * Setup venice's sleep related timers
  214          * Current implementation assumes sw processing of beacons -
  215          *   assuming an interrupt is generated every beacon which
  216          *   causes the hardware to become awake until the sw tells
  217          *   it to go to sleep again; beacon timeout is to allow for
  218          *   beacon jitter; cab timeout is max time to wait for cab
  219          *   after seeing the last DTIM or MORE CAB bit
  220          */
  221 #define CAB_TIMEOUT_VAL     10 /* in TU */
  222 #define BEACON_TIMEOUT_VAL  10 /* in TU */
  223 #define SLEEP_SLOP          3  /* in TU */
  224 
  225         /*
  226          * For max powersave mode we may want to sleep for longer than a
  227          * beacon period and not want to receive all beacons; modify the
  228          * timers accordingly; make sure to align the next TIM to the
  229          * next DTIM if we decide to wake for DTIMs only
  230          */
  231         beaconintval = bs->bs_intval & HAL_BEACON_PERIOD;
  232         HALASSERT(beaconintval != 0);
  233         if (bs->bs_sleepduration > beaconintval) {
  234                 HALASSERT(roundup(bs->bs_sleepduration, beaconintval) ==
  235                                 bs->bs_sleepduration);
  236                 beaconintval = bs->bs_sleepduration;
  237         }
  238         dtimperiod = bs->bs_dtimperiod;
  239         if (bs->bs_sleepduration > dtimperiod) {
  240                 HALASSERT(dtimperiod == 0 ||
  241                         roundup(bs->bs_sleepduration, dtimperiod) ==
  242                                 bs->bs_sleepduration);
  243                 dtimperiod = bs->bs_sleepduration;
  244         }
  245         HALASSERT(beaconintval <= dtimperiod);
  246         if (beaconintval == dtimperiod)
  247                 nextTbtt = bs->bs_nextdtim;
  248         else
  249                 nextTbtt = bs->bs_nexttbtt;
  250         nextdtim = bs->bs_nextdtim;
  251 
  252         OS_REG_WRITE(ah, AR_SLEEP1,
  253                   SM((nextdtim - SLEEP_SLOP) << 3, AR_SLEEP1_NEXT_DTIM)
  254                 | SM(CAB_TIMEOUT_VAL, AR_SLEEP1_CAB_TIMEOUT)
  255                 | AR_SLEEP1_ASSUME_DTIM
  256                 | AR_SLEEP1_ENH_SLEEP_ENA
  257         );
  258         OS_REG_WRITE(ah, AR_SLEEP2,
  259                   SM((nextTbtt - SLEEP_SLOP) << 3, AR_SLEEP2_NEXT_TIM)
  260                 | SM(BEACON_TIMEOUT_VAL, AR_SLEEP2_BEACON_TIMEOUT)
  261         );
  262         OS_REG_WRITE(ah, AR_SLEEP3,
  263                   SM(beaconintval, AR_SLEEP3_TIM_PERIOD)
  264                 | SM(dtimperiod, AR_SLEEP3_DTIM_PERIOD)
  265         );
  266         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n",
  267             __func__, bs->bs_nextdtim);
  268         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n",
  269             __func__, nextTbtt);
  270         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: beacon period %d\n",
  271             __func__, beaconintval);
  272         HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: DTIM period %d\n",
  273             __func__, dtimperiod);
  274 #undef CAB_TIMEOUT_VAL
  275 #undef BEACON_TIMEOUT_VAL
  276 #undef SLEEP_SLOP
  277 }

Cache object: 22bf126449bd612adccd847272e9a308


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.