Home | History | Annotate | Line # | Download | only in ar5211
ar5211_beacon.c revision 1.1
      1 /*
      2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  * Copyright (c) 2002-2006 Atheros Communications, Inc.
      4  *
      5  * Permission to use, copy, modify, and/or distribute this software for any
      6  * purpose with or without fee is hereby granted, provided that the above
      7  * copyright notice and this permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  *
     17  * $Id: ar5211_beacon.c,v 1.1 2008/12/11 04:46:31 alc Exp $
     18  */
     19 #include "opt_ah.h"
     20 
     21 #include "ah.h"
     22 #include "ah_internal.h"
     23 
     24 #include "ar5211/ar5211.h"
     25 #include "ar5211/ar5211reg.h"
     26 #include "ar5211/ar5211desc.h"
     27 
     28 /*
     29  * Routines used to initialize and generated beacons for the AR5211/AR5311.
     30  */
     31 
     32 /*
     33  * Initialize all of the hardware registers used to send beacons.
     34  */
     35 void
     36 ar5211SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
     37 {
     38 
     39 	OS_REG_WRITE(ah, AR_TIMER0, bt->bt_nexttbtt);
     40 	OS_REG_WRITE(ah, AR_TIMER1, bt->bt_nextdba);
     41 	OS_REG_WRITE(ah, AR_TIMER2, bt->bt_nextswba);
     42 	OS_REG_WRITE(ah, AR_TIMER3, bt->bt_nextatim);
     43 	/*
     44 	 * Set the Beacon register after setting all timers.
     45 	 */
     46 	OS_REG_WRITE(ah, AR_BEACON, bt->bt_intval);
     47 }
     48 
     49 /*
     50  * Legacy api to initialize all of the beacon registers.
     51  */
     52 void
     53 ar5211BeaconInit(struct ath_hal *ah,
     54 	uint32_t next_beacon, uint32_t beacon_period)
     55 {
     56 	HAL_BEACON_TIMERS bt;
     57 
     58 	bt.bt_nexttbtt = next_beacon;
     59 	/*
     60 	 * TIMER1: in AP/adhoc mode this controls the DMA beacon
     61 	 * alert timer; otherwise it controls the next wakeup time.
     62 	 * TIMER2: in AP mode, it controls the SBA beacon alert
     63 	 * interrupt; otherwise it sets the start of the next CFP.
     64 	 */
     65 	switch (AH_PRIVATE(ah)->ah_opmode) {
     66 	case HAL_M_STA:
     67 	case HAL_M_MONITOR:
     68 		bt.bt_nextdba = 0xffff;
     69 		bt.bt_nextswba = 0x7ffff;
     70 		break;
     71 	case HAL_M_IBSS:
     72 	case HAL_M_HOSTAP:
     73 		bt.bt_nextdba = (next_beacon -
     74 			ath_hal_dma_beacon_response_time) << 3;	/* 1/8 TU */
     75 		bt.bt_nextswba = (next_beacon -
     76 			ath_hal_sw_beacon_response_time) << 3;	/* 1/8 TU */
     77 		break;
     78 	}
     79 	/*
     80 	 * Set the ATIM window
     81 	 * Our hardware does not support an ATIM window of 0
     82 	 * (beacons will not work).  If the ATIM windows is 0,
     83 	 * force it to 1.
     84 	 */
     85 	bt.bt_nextatim = next_beacon + 1;
     86 	bt.bt_intval = beacon_period &
     87 		(AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
     88 	ar5211SetBeaconTimers(ah, &bt);
     89 }
     90 
     91 void
     92 ar5211ResetStaBeaconTimers(struct ath_hal *ah)
     93 {
     94 	uint32_t val;
     95 
     96 	OS_REG_WRITE(ah, AR_TIMER0, 0);		/* no beacons */
     97 	val = OS_REG_READ(ah, AR_STA_ID1);
     98 	val |= AR_STA_ID1_PWR_SAV;		/* XXX */
     99 	/* tell the h/w that the associated AP is not PCF capable */
    100 	OS_REG_WRITE(ah, AR_STA_ID1,
    101 		val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF));
    102 	OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD);
    103 }
    104 
    105 /*
    106  * Set all the beacon related bits on the h/w for stations
    107  * i.e. initializes the corresponding h/w timers;
    108  * also tells the h/w whether to anticipate PCF beacons
    109  */
    110 void
    111 ar5211SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
    112 {
    113 	struct ath_hal_5211 *ahp = AH5211(ah);
    114 
    115 	HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__);
    116 
    117 	HALASSERT(bs->bs_intval != 0);
    118 	/* if the AP will do PCF */
    119 	if (bs->bs_cfpmaxduration != 0) {
    120 		/* tell the h/w that the associated AP is PCF capable */
    121 		OS_REG_WRITE(ah, AR_STA_ID1,
    122 			OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF);
    123 
    124 		/* set CFP_PERIOD(1.024ms) register */
    125 		OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod);
    126 
    127 		/* set CFP_DUR(1.024ms) register to max cfp duration */
    128 		OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration);
    129 
    130 		/* set TIMER2(128us) to anticipated time of next CFP */
    131 		OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3);
    132 	} else {
    133 		/* tell the h/w that the associated AP is not PCF capable */
    134 		OS_REG_WRITE(ah, AR_STA_ID1,
    135 			OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF);
    136 	}
    137 
    138 	/*
    139 	 * Set TIMER0(1.024ms) to the anticipated time of the next beacon.
    140 	 */
    141 	OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt);
    142 
    143 	/*
    144 	 * Start the beacon timers by setting the BEACON register
    145 	 * to the beacon interval; also write the tim offset which
    146 	 * we should know by now.  The code, in ar5211WriteAssocid,
    147 	 * also sets the tim offset once the AID is known which can
    148 	 * be left as such for now.
    149 	 */
    150 	OS_REG_WRITE(ah, AR_BEACON,
    151 		(OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM))
    152 		| SM(bs->bs_intval, AR_BEACON_PERIOD)
    153 		| SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM)
    154 	);
    155 
    156 	/*
    157 	 * Configure the BMISS interrupt.  Note that we
    158 	 * assume the caller blocks interrupts while enabling
    159 	 * the threshold.
    160 	 */
    161 	HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR));
    162 	ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR)
    163 			| SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR);
    164 	OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
    165 
    166 	/*
    167 	 * Set the sleep duration in 1/8 TU's.
    168 	 */
    169 #define	SLEEP_SLOP	3
    170 	OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLDUR,
    171 		(bs->bs_sleepduration - SLEEP_SLOP) << 3);
    172 #undef SLEEP_SLOP
    173 }
    174