Home | History | Annotate | Line # | Download | only in ar5211
      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.2 2009/01/06 06:03:57 mrg 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_nextdba = 0;
     59 	bt.bt_nextswba = 0;
     60 	bt.bt_nexttbtt = next_beacon;
     61 	/*
     62 	 * TIMER1: in AP/adhoc mode this controls the DMA beacon
     63 	 * alert timer; otherwise it controls the next wakeup time.
     64 	 * TIMER2: in AP mode, it controls the SBA beacon alert
     65 	 * interrupt; otherwise it sets the start of the next CFP.
     66 	 */
     67 	switch (AH_PRIVATE(ah)->ah_opmode) {
     68 	case HAL_M_STA:
     69 	case HAL_M_MONITOR:
     70 		bt.bt_nextdba = 0xffff;
     71 		bt.bt_nextswba = 0x7ffff;
     72 		break;
     73 	case HAL_M_IBSS:
     74 	case HAL_M_HOSTAP:
     75 		bt.bt_nextdba = (next_beacon -
     76 			ath_hal_dma_beacon_response_time) << 3;	/* 1/8 TU */
     77 		bt.bt_nextswba = (next_beacon -
     78 			ath_hal_sw_beacon_response_time) << 3;	/* 1/8 TU */
     79 		break;
     80 	}
     81 	/*
     82 	 * Set the ATIM window
     83 	 * Our hardware does not support an ATIM window of 0
     84 	 * (beacons will not work).  If the ATIM windows is 0,
     85 	 * force it to 1.
     86 	 */
     87 	bt.bt_nextatim = next_beacon + 1;
     88 	bt.bt_intval = beacon_period &
     89 		(AR_BEACON_PERIOD | AR_BEACON_RESET_TSF | AR_BEACON_EN);
     90 	ar5211SetBeaconTimers(ah, &bt);
     91 }
     92 
     93 void
     94 ar5211ResetStaBeaconTimers(struct ath_hal *ah)
     95 {
     96 	uint32_t val;
     97 
     98 	OS_REG_WRITE(ah, AR_TIMER0, 0);		/* no beacons */
     99 	val = OS_REG_READ(ah, AR_STA_ID1);
    100 	val |= AR_STA_ID1_PWR_SAV;		/* XXX */
    101 	/* tell the h/w that the associated AP is not PCF capable */
    102 	OS_REG_WRITE(ah, AR_STA_ID1,
    103 		val & ~(AR_STA_ID1_DEFAULT_ANTENNA | AR_STA_ID1_PCF));
    104 	OS_REG_WRITE(ah, AR_BEACON, AR_BEACON_PERIOD);
    105 }
    106 
    107 /*
    108  * Set all the beacon related bits on the h/w for stations
    109  * i.e. initializes the corresponding h/w timers;
    110  * also tells the h/w whether to anticipate PCF beacons
    111  */
    112 void
    113 ar5211SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
    114 {
    115 	struct ath_hal_5211 *ahp = AH5211(ah);
    116 
    117 	HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: setting beacon timers\n", __func__);
    118 
    119 	HALASSERT(bs->bs_intval != 0);
    120 	/* if the AP will do PCF */
    121 	if (bs->bs_cfpmaxduration != 0) {
    122 		/* tell the h/w that the associated AP is PCF capable */
    123 		OS_REG_WRITE(ah, AR_STA_ID1,
    124 			OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PCF);
    125 
    126 		/* set CFP_PERIOD(1.024ms) register */
    127 		OS_REG_WRITE(ah, AR_CFP_PERIOD, bs->bs_cfpperiod);
    128 
    129 		/* set CFP_DUR(1.024ms) register to max cfp duration */
    130 		OS_REG_WRITE(ah, AR_CFP_DUR, bs->bs_cfpmaxduration);
    131 
    132 		/* set TIMER2(128us) to anticipated time of next CFP */
    133 		OS_REG_WRITE(ah, AR_TIMER2, bs->bs_cfpnext << 3);
    134 	} else {
    135 		/* tell the h/w that the associated AP is not PCF capable */
    136 		OS_REG_WRITE(ah, AR_STA_ID1,
    137 			OS_REG_READ(ah, AR_STA_ID1) &~ AR_STA_ID1_PCF);
    138 	}
    139 
    140 	/*
    141 	 * Set TIMER0(1.024ms) to the anticipated time of the next beacon.
    142 	 */
    143 	OS_REG_WRITE(ah, AR_TIMER0, bs->bs_nexttbtt);
    144 
    145 	/*
    146 	 * Start the beacon timers by setting the BEACON register
    147 	 * to the beacon interval; also write the tim offset which
    148 	 * we should know by now.  The code, in ar5211WriteAssocid,
    149 	 * also sets the tim offset once the AID is known which can
    150 	 * be left as such for now.
    151 	 */
    152 	OS_REG_WRITE(ah, AR_BEACON,
    153 		(OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_PERIOD|AR_BEACON_TIM))
    154 		| SM(bs->bs_intval, AR_BEACON_PERIOD)
    155 		| SM(bs->bs_timoffset ? bs->bs_timoffset + 4 : 0, AR_BEACON_TIM)
    156 	);
    157 
    158 	/*
    159 	 * Configure the BMISS interrupt.  Note that we
    160 	 * assume the caller blocks interrupts while enabling
    161 	 * the threshold.
    162 	 */
    163 	HALASSERT(bs->bs_bmissthreshold <= MS(0xffffffff, AR_RSSI_THR_BM_THR));
    164 	ahp->ah_rssiThr = (ahp->ah_rssiThr &~ AR_RSSI_THR_BM_THR)
    165 			| SM(bs->bs_bmissthreshold, AR_RSSI_THR_BM_THR);
    166 	OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
    167 
    168 	/*
    169 	 * Set the sleep duration in 1/8 TU's.
    170 	 */
    171 #define	SLEEP_SLOP	3
    172 	OS_REG_RMW_FIELD(ah, AR_SCR, AR_SCR_SLDUR,
    173 		(bs->bs_sleepduration - SLEEP_SLOP) << 3);
    174 #undef SLEEP_SLOP
    175 }
    176